This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

1 introduction

Proto__ __proto__ constructor (); proto__ constructor (); proto__ constructor (); This is how to place the object you want to inherit on the prototype chain of the object you want to inherit.

2. Prototype chain inheritance

Prototype = Function ()

const Animal = function () {}
Animal.prototype.eat = function () {
  console.log('i eat')}const Dog = function () {}
// Dog.prototype = new Animal()
// Object.setPrototypeOf(Dog.prototype, new Animal())
Dog.prototype = Object.create(new Animal())
Dog.prototype.constructor = Dog // Better fix it
const dog = new Dog()
dog.eat()
Copy the code

Dog. Prototype (new Animal(), new Animal(eat), new Animal(eat)) Find eat on its prototype object animal. prototype

Other six inheritance modes

  • Borrow constructor inheritance
  • Combination of inheritance
  • Primary inheritance
  • Parasitic inheritance
  • Parasitic combinatorial inheritance
  • Mixin inherits multiple objects

It’s all rubbish, it’s all rubbish, it’s just I don’t want to remember…

4 class inheritance

The main thing to learn is class inheritance, which is also implemented through Prototype inheritance and is a syntax candy.

If possible, I would prefer not to modify prototype properties directly in the code, such as prototype.xxx = XXX. This code is really hard to read, and the implementation of inheritance code should be done first.

/ / parent class
class Animal {
  constructor(options) {
    typeof options === 'object' && Object.assign(this, options)
  }
  say() {
    console.log('i ... ')}}// Subclass inherits parent class
class Dog extends Animal {
  constructor(options) {
    // In the constructor of a subclass, we need super() before we can use this, so we can call the constructor of the parent class to get the instance properties of the parent class
    super(options)
    this.options = options
  }
  eat() {
    console.log('i eat')}}Copy the code

TSC converts TS to JS after simplifying the code result

/** * inherit method *@param {*} The child subclass *@param {*} The parent class b * /
var __extends = function (child, parent) {
  if (typeofb ! = ='function'&& parent ! = =null)
    throw new TypeError(
      'Class extends value ' + String(parent) + ' is not a constructor or null'
    )
  // Copy static methods from the parent class to the child class, because properties that cannot be read from child class will be read from parent class
  Object.setPrototypeOf(child, parent)

  if (parent === null) {
    // If the parent class is null, the stereotype is set to null
    child.prototype = Object.create(parent)
  } else {
    // If the parent class is a function,
    // Use prototype chain inheritance directly
    child.prototype = new parent()
    child.prototype.constructor = child
  }
}
// Why is it an immediate function, because class does not promote, it can be done this way.
// But const cannot be simulated
var Animal = / * *@class * / (function () {
  // Class is actually a function,
  // constructor is the function ontology
  function Animal(options) {
    typeof options === 'object' && Object.assign(this, options)
  }
  // The method is implemented through prototypes
  Animal.prototype.say = function () {
    console.log('i ... ')}return Animal
})()
var Dog = / * *@class * / (function (_super) {
  // Inherits the parent class
  __extends(Dog, _super)
  function Dog(options) {
    // Instantiate the parent class to get the instance attributes of the parent class
    var _this = _super.call(this, options) || this
    _this.options = options
    return _this
  }
  Dog.prototype.eat = function () {
    console.log('i eat')}return Dog
})(Animal)
Copy the code

5 diy inheritance

A purely diy

const protoArr = Symbol('protoArr')
const addProto = (child, parent) = > {
  if(! child[protoArr]) {// I can't change the pointing of child.prototype, so I can change the pointing of child.prototype
    const originProto = Object.getPrototypeOf(child.prototype)
    // Save its original prototype object and the prototype object to be added
    child[protoArr] = new Set([originProto, parent.prototype])
    const newProp = new Proxy({}, {get(target, key) {
          // Retrieve attributes from each of the saved prototype objects
          const value = [...child[protoArr]].find((i) = >i? .[key] ! = =void 0)? .[ key ]return value
        },
      }
    )
    // If the property is not read on child.prototype, go back to its prototype and read it. Then the proxy object is read and can be intercepted
    Object.setPrototypeOf(child.prototype, newProp)
  } else {
    // Add the desired prototype chain directly to the save location
    child[protoArr].add(parent.prototype)
  }
}

const delProto = (child, parent) = > {
  if(! child[protoArr]) {// There is no new prototype object
    return
  } else {
    // Delete it
    child[protoArr].delete(parent.prototype)
  }
}

class Style1 {
  width() {
    return 100}}class Style2 {
  height() {
    return 100}}class Style3 {
  color() {
    return '#ccc'}}class Style4 {}
Style4.prototype.fontSize = '12px'
class Style5 {
  backgroundColor() {
    return 'red'}}const getStyle = (style) = > {
  const keys = ['width'.'height'.'color'.'fontSize'.'backgroundColor']
  return keys.reduce((total, cur) = > {
    if (style[cur]) {
      total[cur] = typeof style[cur] === 'function' ? style[cur]() : style[cur]
    }
    return total
  }, {})
}
class Style {}

const style = new Style()
console.log(getStyle(style))
// {} At this point, it and its prototype chain cannot read any properties
addProto(Style, Style1)
addProto(Style, Style2)
addProto(Style, Style3)
addProto(Style, Style4)
addProto(Style, Style5)
console.log(getStyle(style))
/ / {
// width: 100,
// height: 100,
// color: '#ccc',
// fontSize: '12px',
// backgroundColor: 'red',
// }
delProto(Style, Style2)
console.log(getStyle(style))
/ / {
// width: 100,
// color: '#ccc',
// fontSize: '12px',
// backgroundColor: 'red',
// }
Copy the code

6 summarizes

Inheritance is achieved by modifying the prototype object.

7 finally

Inheritance remember so much, if there is some enlightenment for you, welcome to like, comment, pay attention to, collect…

As usual, I enclose a few previous posts

  1. Vue2 source code analysis nextTick
  2. Code snippet JS flow limiting scheduler
  3. Linked Lists of Data Structures and Algorithms (1)
  4. Vue2 source code parsing event system $on
  5. Vue2 – Global API source code analysis
  6. Vue-class-component (1)
  7. Js native syntax prototype,__proto__ and constructor