JavaScript繼承(四)——原型式繼承

道格拉斯·克羅克福特在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"]

更改了p2friends,致使pfriends也被更改了。函數

那麼原型式繼承的意義在哪兒呢?某些狀況下只是簡單地想讓一個對象與另外一個對象保持繼承關係,沒有必要興師動衆地先建立一個構造函數,這時原型式繼承就派上用場了。實際上原型式繼承如此好用,以至於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年)的做者。——維基百科

相關文章
相關標籤/搜索