Related learning of six ways of js object inheritance

1. Understand some basic concepts

(1) Clarify the relationship between constructor, object instance, prototype object prototype and object prototype __proto__

  1. Constructor: A function used to create an object, which generates an object instance through the new keyword. Function names are usually capitalized.
  2. Object instance: The new keyword generates an object instance.
  3. Prototype object prototype: Each function has a prototype attribute, which is a pointer to a prototype object (the prototype object is created at the same time when the function is defined).
  4. Object prototype: Each instance object created by the constructor has a __proto__ attribute, which is used to point to the prototype object prototype of the constructor. It can be understood that the two are equivalent.

(2) Primitive value, reference value, value transfer

  1. Original value:expresssingleThe data, the variable holding the original value is accessed by value,Manipulate the actual value stored in variable memory. ES6 has six primitive values: undefined, Null, Boolean, Number, String, Symbol, etc.
  2. reference value: The reference value refers to themultiple valuesconstitutedobject. When actually manipulating objects,The memory address where the object is saved is accessed, which is a reference to the object. The way a reference value (object) can add, modify and delete its properties at any time (dynamic properties).
  3. Passing by value: The process of copying a value to a variable. Like the original value, the information stored in the variable is assigned to another variable.

2. Six ways of inheritance

1. Prototype chain inheritance (prototype inheritance)

function Person() {
    
    
  this.color = ['red', 'green']
}
Person.prototype.getColor = function() {
    
    
  return this.color
}
function My(name) {
    
    
  this.name = name
}
// 通过创建My的实例继承了Person
My.prototype = new Person()
var m1 = new My('ljc')
var m2 = new My('xlt')
m1.color.push('black')
console.log(m1.color, m2.color)

insert image description here

Summary: All properties (reference values) of the prototype object will be used by all instancesshared, which causes modifications to one instance to affect the other.

2. Constructor inheritance (with call or apply)

function Person() {
    
    
  this.color = ['red', 'green']
}
Person.prototype.getColor = function() {
    
    
  return this.color
}
function My(name) {
    
    
  Person.call(this)
  this.name = name
}
var m1 = new My('ljc')
var m2 = new My('ljc')
m1.color.push('black')
console.log(m1.color)
console.log(m2.color)
console.log(m1.getColor())
The difference between call and apply parameter passing, the former is in the form of a list, while the latter is in the form of an array

insert image description here
insert image description here

Summary: Solve the shortcomings of prototype chain inheritance (all properties ((reference values)) of prototype objects are shared), and prototype (prototype) properties or methods cannot be inherited.

3. Combined inheritance (combined prototype chain inheritance + constructor inheritance)

 function Person(name) {
    
    
   this.name = name
   this.color = ['red', 'green']
}
Person.prototype.getColor = function() {
    
    
  return this.color
}
function My(name) {
    
    
   Person.call(this, name)
   // Person.apply(this, [name])
}
My.prototype = new Person()
// 手动挂上构造器,指向自己的构造函数
My.prototype.constructor = My
var m1 = new My('ljc')
var m2 = new My('xlt')
m1.color.push('black')
console.log(m1.color)
console.log(m2.color)
console.log(m1.getColor())
console.log(m2.getColor())

insert image description here

Summary: The first two shortcomings are solved, but no matter what the situation is, the constructor of the parent class (Person) will be called twice, once when creating the subtype prototype (My.prototype = new Person()), Once inside the subtype constructor (Person.call(this, name)), there are efficiency issues.

4. Prototype inheritance

After ES5, the Object.create() method is used. This method receives two parameters: one is the object used as the prototype of the new object, and the other is the object (optional parameter) that defines additional properties for the new object.

 const obj = {
    
    
   color: ['red', 'green', 'blue'],
   name: 'obj'
 }
 const t1 = Object.create(obj)
 const t2 = Object.create(obj)
 t1.color.push('balck')
 t1.name = 'ljc'
 console.log(t1.color, t2.color)
 console.log(t1.name, t2.name)

insert image description here

Summary: Shallow clone an object to create another object, and inherit the prototype properties of the object at the same time, so shallow clone, so if the object properties shared by the instance are reference values, they will be polluted.

5. Parasitic inheritance

const obj = {
    
    
  color: ['red', 'green', 'blue'],
  name: 'obj',
  getName: function() {
    
    
    return this.name
  }
}
function clone(obj) {
    
    
  const newObj = Object.create(obj)
  newObj.getColor = function() {
    
    
    return this.color
  }
  return newObj
}
 const t1 = clone(obj)
 const t2 = clone(obj)
 t1.color.push('balck')
 t1.name = 'ljc'
 console.log(t1.color, t2.color)
 console.log(t1.name, t2.name)
 console.log(t1.getName(), t2.getName())
 console.log(t1.getColor(), t2.getColor())

insert image description here

Summary: Create another object based on an object clone, and enhance the object. Adding functions to objects through parasitic inheritance will make the functions difficult to reuse, similar to the constructor mode.

6. Parasitic combined inheritance (constructor + prototype inheritance)

function Person(name) {
    
    
  this.name = name
  this.color = ['green', 'red']
}
Person.prototype.getName = function() {
    
    
  return this.name
}
function My(name, age) {
    
    
  Person.call(this, name)
  this.age = age
}
function clone(Sup, Sub) {
    
    
  Sub.prototype = Object.create(Sup.prototype)
  Sub.prototype.constructor = Sub
}
clone(Person, My)
My.prototype.getAge = function() {
    
    
  return this.age
}
const m1 = new My('ljc', 24)
const m2 = new My('xlt', 23)
m1.color.push('black')
m2.color.push('white')
console.log(m1.color, m2.color)
console.log(m1.getName(), m1.getAge())

insert image description here

Summary: It can basically solve the shortcomings of the previous inheritance methods, and only calls the constructor of the parent class (Person.call(this, name)) once to improve efficiency.

3. The extends keyword of ES6 implements logic

class Person {
    
    
  constructor(name) {
    
    
    this.name = name
  }
  getName() {
    
    
    return this.name
  }
}
class My extends Person {
    
    
  constructor(name, age) {
    
    
    super(name)
    this.age = age
  }
}
const my = new My('ljc', 23)
console.log(my.getName(), my.age)
Summary: The this keyword always points to the current object where the function is located. ES6 adds another similar keyword super, which points to the prototype object of the current object. The constructor of the subclass must execute the super function once.

Guess you like

Origin blog.csdn.net/qq_45616003/article/details/124930686