原型鏈、繼承--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調用傳參)對象
//簡版:應用new會設置__proto__連接的原理 兼容ES5之前版本 if(typeof Object.create !=='function') { Object.create = function(proto) { function F() {} F.prototype = proto; return new F(); } }
// 僅適用於Chrome和FireFox,在IE中不工做: Object.setPrototypeOf = Object.setPrototypeOf || function(obj, proto) { obj.__proto__ = proto; return obj; }
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)
寄生組合式繼承是開發者使用較多的繼承方式。