道格拉斯·克羅克福特在2006年提出了原型式繼承,他的想法是基於已有的對象藉助原型建立新對象,同時還沒必要所以建立一個自定義類型。爲此,他給出了下面的函數:javascript
function object(obj){ function F(){} F.prototype = obj; return new F(); }
在object
函數內部,先建立了一個臨時性的構造函數,而後將傳入的對象做爲這個構造函數的原型,最後返回了這個臨時類型的一個新實例。其實本質仍是原型鏈繼承,只不過達到的效果是沒有爲新建立的對象單獨聲明一個類型,至關於簡化版的原型鏈繼承。來看下面具體的示例:java
let p = { name: 'bob', friends: ['jack', 'rose'] } let p2 = object(p); console.log(p); console.log(p2);
結果以下:程序員
這個效果和下面這種寫法差很少web
let p2 = {}; p2.__proto__ = p; console.log(p); console.log(p2);
結果以下:編程
那爲何不直接使用這種方式呢?緣由之一是直接操做對象的__proto__
屬性比較損耗瀏覽器的性能。瀏覽器
既然仍是原型鏈繼承,那麼原型鏈繼承的數據共享問題固然也是存在的,以下示例:編程語言
p2.friends.push('lily'); console.log(p.friends);//["jack", "rose", "lily"] console.log(p2.friends);//["jack", "rose", "lily"]
更改了p2
的friends
,致使p
的friends
也被更改了。函數
那麼原型式繼承的意義在哪兒呢?某些狀況下只是簡單地想讓一個對象與另外一個對象保持繼承關係,沒有必要興師動衆地先建立一個構造函數,這時原型式繼承就派上用場了。實際上原型式繼承如此好用,以至於ECMAScript標準委員會都看不下去了,在ECMAScript 5中經過新增Object.create()
方法規範化了原型式繼承。這個方法接收兩個參數:一個用做新對象的原型,一個用於定義新對象的額外屬性。在只傳入一個參數的狀況下,Object.create()
和object()
效果相同。仍是上面的示例,使用Object.create()
建立p3
,代碼以下:工具
let p3 = Object.create(p);
結果以下:性能
傳入兩個參數,以下代碼所示:
let p4 = Object.create(p, { name: { value: 'greg' } });
結果以下:
因此之後想要使用原型式繼承,調用Object.create()
方法就能夠了。
關於道格拉斯·克羅克福特:
道格拉斯·克羅克福特(英語:Douglas Crockford)是美國程序員和企業家,知名於對網頁編程語言JavaScript推動和改良;且爲輕量級數據交換格式「JSON」的建立者。他仍是衆多JavaScript語言開發工具的創造者,例如JSLint和JSMin。近段時間,他在PayPal擔任JavaScript語言高級顧問,固然他也是JavaScript、JSON以及web技術的佈道者,在這些方面出版發行了不少知名的書籍及演講,是《JavaScript:語言精粹》(JavaScript: The Good Parts,2008年)的做者。——維基百科