原型鏈、繼承--Mr.Ember

原型鏈、繼承--Mr.Ember瀏覽器

構造函數、原型對象和實例之間的關係app

functionF(){};
var f = new F();
// 構造器
F.prototype.constructor === F; // true
F.__proto__ ===  Function.prototype; // true
Function.prototype.__proto__ === Object.prototype; // true
Object.prototype.__proto__ === null; // true

// 實例
f.__proto__ === F.prototype; // true
F.prototype.__proto__ === Object.prototype; // true
Object.prototype.__proto__ === null; // true

 

圖示表示以下函數

 

ES6 extends繼承作了什麼操做this

class Parent{
    constructor(name) {
        this.name = name;
    }
    static sayHello() {
        console.log('hello')
    }
    sayName() {
        console.log('name is' + this.name)
        return this.name
    }
}
class Child extends Parent{
    constructor(name, age) {
        super(name)
        this.age = age;
    }
    sayAge() {
        console.log('age is' + this.age)
        return this.age
    }
}

let parent = new Parent('Parent1');
let child = new Child('Child1', 18);
console.log('parent:' + parent);     //parent:[object Object]
Parent.sayHello();         //hello
parent.sayName();       //name is Parent1
console.log('child:' + child);    //child:[object Object]
Child.sayHello();   //hello
child.sayName();     //name is Child1
child.sayAge();   //age is 18

 

代碼中有兩條原型鏈 es5

// 一、構造器原型鏈
Child.__proto__ === Parent; // true
Parent.__proto__ === Function.prototype; // true
Function.prototype.__proto__ === Object.prototype; // true
Object.prototype.__proto__ === null; // true
// 二、實例原型鏈
child.__proto__ === Child.prototype; // true
Child.prototype.__proto__ === Parent.prototype; // true
Parent.prototype.__proto__ === Object.prototype; // true
Object.prototype.__proto__ === null; // true

 

此時兩條鏈以下圖所示關係spa

結合代碼知道,ES6extends繼承,主要是:prototype

1. 把子類構造函數(Child)的原型(__proto__)指向了父類構造函數(Parent)3d

2. 把子類實例child的原型對象(Child.prototype)的原型(__proto__)指向了父類parent的原型對象(Parent.prototype)code

3. 子類構造函數Child繼承了父類的構造函數Parent的屬性。使用super調用的(es5則用call或者apply調用傳參)對象

 

設置proto
new、Object.create和Object.setPrototypeof能夠設置__proto__
__proto__是瀏覽器廠商本身實現的
new出來的實例的__proto__指向構造函數的prototype,這就是new作的事
 
new作了什麼
(1)建立一個全新的對象
(2)這個對象會被執行[[prototype]](也就是__proto__)連接
(3)生成的新的對象會綁定到函數調用this
(4)經過new建立的新對象將最終被[[Prototype]]連接到這個函數的prototype對象上
(5)若是函數沒有返回對象類型Object(包含Function,Array,Date,RegExg,Error),那麼new表達式中的函數
       會自動返回這個新的對象。
 
Object.create: ES5提供的
Object.create(proto,[propertiesObject])方法建立一個新對象,使用現有的對象來提供新建立的對象的__proto__
它接受兩個參數,不過第二個可選參數是屬性描述符(不經常使用,默認undefined)。對於不支持ES5的瀏覽器能夠使用ployfill方案: MDN Object.create()
 
//簡版:應用new會設置__proto__連接的原理 兼容ES5之前版本
if(typeof Object.create !=='function') {
     Object.create = function(proto) {
         function F() {}
         F.prototype = proto;
         return new F();
     }
}

 

 
Object.setPropertyOf: ES6提供的
Object.setPropertyOf() 方法設置一個指定的對象原型(即內部[[Prototype]]屬性)到另外一個對象或null:Object.setPrototypeOf(obj, prototype)
 
// 僅適用於Chrome和FireFox,在IE中不工做:
Object.setPrototypeOf = Object.setPrototypeOf || function(obj, proto) {
   obj.__proto__ = proto;
   return obj;
}

 

 
 extends的ES5版本實現
知道了ES6 extends繼承作了什麼操做和設置 __proto__的知識點後,把上面 ES6例子的用 ES5就比較容易實現了,也就是說實現寄生組合式繼承,簡版代碼就是:
function Parent(name) {
    this.name = name;
}
Parent.sayHello = function() {
    console.log('hello')
}
Parent.prototype.sayName = function() {
    console.log('name is' + this.name);
    return this.name;
}

function Child(name, age) {
    // 至關於super
    Parent.call(this, name); //綁定this 繼承Parent的屬性
    this.age = age;
}
//new 
function object() {   //兼容es5的new新對象問題
    function F() {}
    F.prototype = proto;
    return new F();
}
function _inherits(Child, Parent) {
    //object.create
    Child.prototype = Object.create(Parent.prototype);
    //__proto__
    //Child.prototype.__proto__ = Parent.prototype;
    Child.prototype.constructor = Child;
    //ES6
    //Object.setPrototypeof(Child, Parent);
    //__proto__
    Child.__proto__ = Parent;
}
_inherits(Child, Parent)
Child.prototype.sayAge = function() {
    console.log('age is' + this.age)
    return this.age;
}
var parent = new Parent('parent2')
var child = new Child('Child2', 18)

 

寄生組合式繼承是開發者使用較多的繼承方式。

相關文章
相關標籤/搜索