2016-06-20 85 views
7

發佈以下代碼到babel REPL爲什麼babel在繼承Object.create(superClass.prototype)時使用setProtoTypeOf來繼承?

class Test { 

} 

class Test2 extends Test { 

} 

你得到這個inherits功能

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 
    } 
    }); 
    if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; 
} 

它看起來沒什麼問題,直到我意識到它是做在原型Object.create一個setPrototypeOf通話。我沒有那麼熟悉setProtoTypeOf,所以我去了MDN那裏說:

如果你關心性能,你應該避免設置[[原型]]的對象。相反,使用Object.create()使用所需的[[Prototype]]創建一個新對象。

這對我來說很混亂,因爲他們都使用兩者。爲什麼會這樣?

應行改爲

if (superClass && !superClass.prototype) 

爲當原型是沒有設置,但它仍然有一個__proto__

回答

8

setPrototypeOf並設置[原型]]的subClass從它的原始值Function.prototypesuperClass,讓它繼承它的靜態屬性。

Object.create不能在這裏使用(就像它是爲.prototype對象),因爲它不允許創建函數。顯然,一個類的構造函數必須是一個函數,唯一的方法就是使用標準表達式/聲明來創建函數,然後再更改其原型。

+0

嗯,這對我來說有點困惑。你能創建一個代碼示例,說明Object.create()的缺點嗎?從我在[MDN]上閱讀的內容(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create),它將繼承靜態方法,因爲它們只是在原班級的原型權利? – m0meni

+1

@ AR7:靜態方法在類的構造函數對象上定義,而不是'.prototype'對象。我們正在討論在這裏彼此繼承的構造函數,而不是實例的原型鏈。 – Bergi

+0

哦,靜態你的意思是[this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static)。所以'Object.create'確實讓你繼承了原型方法,但是沒有使用'static'關鍵字定義的方法,對嗎?雖然我很好奇......爲什麼靜態方法存儲在'__proto__'對象而不是原型? – m0meni