從別人的博客裏面盜了2張圖,這2張圖將對象/實例/prototype/__proto__/constructor之間的關係描繪的很清楚。html
1.prototype 爲 function的屬性,實例化的對象(即new以後的對象)沒有prototype,只有__proto__,且指向聲明該實力對象函數的prototypees6
2.babel 繼承源碼分析:express
class Base{ constructor(){ this.myname = 'jack'; } } Base.$inject = ['$http'] Base.prototype.age = 10; class HostController extends Base{ }
編譯後:babel
'use strict'; function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); }
//繼承父類的原型方法 subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });
//關鍵步驟,經過__proto__指向父類構造函數,實現父類靜態屬性,方法的繼承 if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } //該方法就是判斷 實例所屬 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Base = function Base() { _classCallCheck(this, Base); this.myname = 'jack'; }; Base.$inject = ['$http']; Base.prototype.age = 10; var HostController = function(_Base) { _inherits(HostController, _Base); function HostController() { _classCallCheck(this, HostController); return _possibleConstructorReturn(this, (HostController.__proto__ || Object.getPrototypeOf(HostController)).apply(this, arguments)); } return HostController; }(Base);
3.es6 中class extends 繼承,不只繼承了父類在構造函數中定義的屬性方法,還能夠繼承父類原型鏈上的屬性和方法,最後還有,父類定義的靜態屬性和方法也能繼承,只不過子類調用父類的靜態方法必須寫爲:Child.xxx(子類.父類屬性或方法)。app
class Base{ constructor(){ this.name = 'jack' } say(){ console.log('.............'); } } Base.inject = ['Base']; Base.prototype.age = 10; class Child extends Base{ } var c = new Child(); c.name; c.say(); Child.inject;
4.在babel繼承中,使用到了Object.setPrototypeOf()方法,該方法有2個參數:函數
Object.setPrototypeOf(obj,prototype):obj表明要目標對象,將prototype參數指定的對象賦給obj的__proto__,等同於:prototypeobj.__proto__ = ;