【翻譯】javascript中的prototype

原文地址:http://dailyjs.com/2012/05/20/js101-prototype/javascript

在花費了不少年研究面向對象編程以後,想在javascript使用是使人失望的。主要是從根源上缺乏一個class這樣的關鍵詞。然而,javascript的設計不會成爲阻礙 -- 精通它基於原型的繼承,將會加深你對該語言的理解。java

首先咱們須要弄清楚面向對象與面向類編程的區別。Javascript提供了咱們須要的工具來完成大多數語言的類能夠作的事情 -- 咱們只須要學習如何正確使用它。編程

咱們簡單的看一下prototype屬性,看它如何深化咱們對javascript的瞭解。瀏覽器

prototype屬性(The prototype Property)

prototype屬性是一個內部屬性,它被用於實現繼承。咱們這裏的「繼承」是一種特定的繼承形式。由於狀態和方法都由對象承載,因此咱們能夠說結構、行爲和狀態都是繼承的。這與基於類的語言造成對比,其狀態由實例承載,而方法由類承載。安全

構造函數就是一個具備屬性的方法,該屬性被稱做prototype:函數

function Animal() {
    
}
console.log(Animal.prototype);

{}標識Animal具備一個prototype屬性,可是沒有用戶定義它。咱們能夠隨意添加值和方法:工具

function Animal() {  
}

Animal.prototype.type = 'Unknown';  
Animal.prototype.weight = 0;  
Animal.prototype.weightUnits = 'kg';

Animal.prototype.toString = function() {  
  return this.type + ', ' + this.weight + this.weightUnits;
};

var molly = new Animal();  
molly.type = 'Dog';  
molly.weight = 28;

console.log(molly.toString());  // Dog, 28kg

這將會輸出"Dog, 28kg"。咱們可使用對象字面量將這些賦值分組:學習

function Animal() {  
}

Animal.prototype = {  
  type: 'Unknown',
  weight: 0,
  weightUnits: 'kg',

  toString: function() {
    return this.type + ', ' + this.weight + this.weightUnits;
  }
};

這樣就和你熟悉的類的方式差別不是很大。this

動態原型(Dynamic Prototypes)

經過指定值能夠給對象動態的添加屬性。prototype

var molly = new Animal()  
  , harley = new Animal();

molly.type = 'Dog';  
molly.weight = 28;

harley.type = 'Dog';  
harley.weight = 38;  
harley.name = 'Harley';

console.log(molly);  
console.log(harley);

// { type: 'Dog', weight: 28 }
// { type: 'Dog', weight: 38, name: 'Harley' }

在這裏添加name屬性隻影響了實例。然而,構造函數的屬性能夠被改變,而且將影響用這個原型建立的對象。

Animal.prototype.weightUnits = 'oz';

console.log(molly.toString())  
// Now displays 'Dog, 28oz'

這就是爲何人們只會擴展本身的庫而不去改變內置原型,或者說只有這麼作纔是安全的。咱們徹底有可能改變對象,例如使用String的內置方法作一些不安全的事情:

String.prototype.match = function() {  
  return true;
};

console.log('alex'.match(/1234/));

輸出爲true,因此如今我成功的破壞了不少程序都在依賴的基礎方法。
改變內置原型也不必定所有是壞的;咱們使用它有用的東西,如修補支持更舊版本的ECMAScript在舊版的瀏覽器。

若是咱們替換prototype屬性會發生什麼?

var molly = new Animal()  
  , harley;

molly.type = 'Dog';  
molly.weight = 28;

Animal.prototype = {  
  toString: function() {
    return '...';
  }
};

harley = new Animal;  
harley.type = 'Dog';  
harley.weight = 38;

console.log(molly.toString());  
console.log(harley.toString());

// Dog, 28kg
// ...

儘管事實上改變原型會影響全部實例,可是徹底替換構造函數的原型不會影響舊實例。爲何?實例具備對原型的引用,而不是離散拷貝。想象它就是這樣:使用new關鍵字建立的每一個實例都連接到原始原型。

相關文章
相關標籤/搜索