The front end of basic skills (VII): Inheritance (prototype, the prototype chain, implementation inheritance) javascript in

1. js inheritance mechanism

javascirpt no concept of "sub-class" and "parent", there is no distinction between "classes" (class) and "instance" (instance) of, thanks to a very peculiar "prototype chain" (prototype chain) mode to implementation inheritance. Inheritance means that the copy operation, but does not copy the default JavaScript object's properties, on the contrary, JavaScript just create an association between two objects so that one object can access the properties and function through the commission of another object, so its called inheritance, commissioned by the statement would be more accurate.

2. What is the prototype, the prototype chain

1. distinguish prototype, __ proto __, constructor
  1. prototype: This is an attribute that every function in javascript will have a prototype property, ordinary objects that do not have this property. Constructor prototype property attribute value is the prototype of the constructor instance created.
  2. __proto__: Every JavaScript object (except null) has a property called __proto__, this property will point to the prototype of the object.
  3. constructor: Each prototype has a constructorproperty that points associated constructor.
function Person() {

}
var person = new Person();
console.log(person.__proto__ === Person.prototype); //true;

function Person() {

}
var person = new Person();
console.log(Person === Person.prototype.constructor); //true
//其实 person 中并没有constructor 属性,当不能读取到constructor属性时,会从 person 的原型也就是 Person.prototype中读取,正好原型中有该属性
console.log(person.constructor === Person); // true
复制代码
2. prototype chain

JavaScript, all objects are inherited by the object from its prototype. And the prototype object itself is a target, it also has its own prototype object, such layers traced, to form a similar list structure, which is the prototype chain (prototype chain). All endpoints were Object prototype prototype chain property function, because the object will assume a JavaScript Object () configuration. Prototype object Objec.prototype also has pointed to a prototype, but its prototype is null, null and there is no prototype.

3. js implementation inheritance

  1. Prototype chain inheritance: take the instance of the parent class to act as a sub-class prototype object
function Super(){
    this.val = 1;
    this.arr = [1];
}
function Sub(){
    // ...
}
Sub.prototype = new Super();    // 核心

var sub1 = new Sub();
var sub2 = new Sub();
sub1.val = 2;
sub1.arr.push(2);
alert(sub1.val);    // 2
alert(sub2.val);    // 1

alert(sub1.arr);    // 1, 2
alert(sub2.arr);    // 1, 2
// 优点: 简单,易于实现
// 缺点: 1. 修改sub1.arr后sub2.arr也变了,因为来自原型对象的引用属性是所有实例共享的。 2. 创建子类实例时,无法向父类构造函数传参
复制代码
  1. Inheritance borrow constructors: by parent class constructor subclass instance be enhanced, and so was the parent class instance attributes to a replicated instance of a subclass fitted (no prototypes used)
function Super(val){
    this.val = val;
    this.arr = [1];

    this.fun = function(){
        // ...
    }
}
function Sub(val){
    Super.call(this, val);   // 核心
    // ...
}

var sub1 = new Sub(1);
var sub2 = new Sub(2);
sub1.arr.push(2);
alert(sub1.val);    // 1
alert(sub2.val);    // 2

alert(sub1.arr);    // 1, 2
alert(sub2.arr);    // 1

alert(sub1.fun === sub2.fun);   // false
// 优点: 1. 解决了子类实例共享父类引用属性的问题 2. 创建子类实例时,可以向父类构造函数传参 
// 缺点: 无法实现函数复用,每个子类实例都持有一个新的fun函数,太多了就会影响性能,内存爆炸。。
复制代码
  1. Combination of inherited (common): Examples of the functions on the prototype object, in order to achieve the function reuse. While also retaining the advantages of borrowing constructor method.
// 通过Super.call(this);继承父类的基本属性和引用属性并保留能传参的优点;通过Sub.prototype = new Super();继承父类函数,实现函数复用
function Super(){
    // 只在此处声明基本属性和引用属性
    this.val = 1;
    this.arr = [1];
}
//  在此处声明函数
Super.prototype.fun1 = function(){};
Super.prototype.fun2 = function(){};
//Super.prototype.fun3...
function Sub(){
    Super.call(this);   // 核心
    // ...
}
Sub.prototype = new Super();    // 核心

var sub1 = new Sub(1);
var sub2 = new Sub(2);
alert(sub1.fun === sub2.fun);   // true
// 优点: 1. 不存在引用属性共享问题 2. 可传参 3. 函数可复用
// 缺点:(一点小瑕疵)子类原型上有一份多余的父类实例属性,因为父类构造函数被调用了两次,生成了两份,而子类实例上的那一份屏蔽了子类原型上的。。。又是内存浪费,比刚才情况好点,不过确实是瑕疵
复制代码
  1. Inheritance parasitic composition (best mode): cut redundant parent class instance attributes share the prototype object.
function beget(obj){   // 生孩子函数 beget:龙beget龙,凤beget凤。
    var F = function(){};
    F.prototype = obj;
    return new F();
}
function Super(){
    // 只在此处声明基本属性和引用属性
    this.val = 1;
    this.arr = [1];
}
//  在此处声明函数
Super.prototype.fun1 = function(){};
Super.prototype.fun2 = function(){};
//Super.prototype.fun3...
function Sub(){
    Super.call(this);   // 核心
    // ...
}
// 用beget(Super.prototype);切掉了原型对象上多余的那份父类实例属性
var proto = beget(Super.prototype); // 核心
proto.constructor = Sub;            // 核心
Sub.prototype = proto;              // 核心

var sub = new Sub();
alert(sub.val);
alert(sub.arr);
复制代码
  1. Prototype formula: to thereby give a function children "pure" new object ( "pure" because there is no instance attribute), and then with the gradual increase (fill instance attribute)
function beget(obj){   // 生孩子函数 beget:龙beget龙,凤beget凤。
    var F = function(){};
    F.prototype = obj;
    return new F();
}
function Super(){
    this.val = 1;
    this.arr = [1];
}

// 拿到父类对象
var sup = new Super();
// 生孩子
var sub = beget(sup);   // 核心
// 增强
sub.attr1 = 1;
sub.attr2 = 2;
//sub.attr3...

alert(sub.val);     // 1
alert(sub.arr);     // 1
alert(sub.attr1);   // 1
//ES5提供了Object.create()函数,内部就是原型式继承,IE9+支持
// 优点:从已有对象衍生新对象,不需要创建自定义类型(更像是对象复制,而不是继承。。
// 缺点: 1. 原型引用属性会被所有实例共享,因为是用整个父类对象来充当了子类原型对象,所以这个缺陷无可避免 2. 无法实现代码复用(新对象是现取的,属性是现添的,都没用函数封装,怎么复用)
复制代码
  1. Parasitic: prototype formula to inherit wearing a vest only, create a new object -> Enhance -> return the object, this process is called Parasitic inheritance, it does not matter how a new object is created.
// 有缺陷的寄生式继承 + 不完美的组合继承 = 完美的寄生组合式继承
function beget(obj){   // 生孩子函数 beget:龙beget龙,凤beget凤。
    var F = function(){};
    F.prototype = obj;
    return new F();
}
function Super(){
    this.val = 1;
    this.arr = [1];
}
function getSubObject(obj){
    // 创建新对象
    var clone = beget(obj); // 核心
    // 增强
    clone.attr1 = 1;
    clone.attr2 = 2;
    //clone.attr3...

    return clone;
}

var sub = getSubObject(new Super());
alert(sub.val);     // 1
alert(sub.arr);     // 1
alert(sub.attr1);   // 1
// 优点: 还是不需要创建自定义类型
// 缺点: 无法实现函数复用(没用到原型,当然不行)
复制代码

Reproduced in: https: //juejin.im/post/5d08cc95f265da1bb31c3af3

Guess you like

Origin blog.csdn.net/weixin_34054866/article/details/93170446