2013-05-25 169 views
19

我試圖讓我的頭部圍繞稱爲JavaScript的這種黑色藝術 - 而且,我必須承認,對此非常興奮。我一直在尋找代碼示例,主要來自easeljs,因爲這是我將主要使用的。而我有點困惑..爲什麼要在JavaScript中爲實例變量聲明原型屬性

我(想我)理解使用原型的功能或屬性是'類'變量和使用this.someProp'實例'變量之間的差異(是的,我明白有在JavaScript中沒有類)

我已經看過的代碼,我使用作爲我自己的代碼模板,聲明原型變量,然後是指他們與這即

在構造函數中:這.name = name;

然後聲明:Object.prototype.name;

後來,this.name =「Freddy」;

這是在'new'中調用的函數,所以在這種情況下,據我所知,'this'是指當前對象。令我困惑的是原型聲明正在做什麼以及爲什麼我們將它用於實例變量?

謝謝,戴夫

OK,有點澄清。在下面的代碼,我看不出有什麼半徑的原型聲明實現:

(function(){ 
    // constructor 
    function MyCircle(radius){ 
     this.radius = radius; 
    } 
    MyCircle.prototype.radius; 
    this.area = function(){ 
     return 3.14*this.radius*this.radius; 
    }; 
    window.MyCircle = MyCircle; 
}()); 
+0

@jayeshjain不一樣的問題 - 這是一個有關聲明的原型「正常值」,不功能。 – Alnitak

+0

re:你的編輯 - 有問題的代碼很有意義。剛纔說'MyCircle.prototype.radius'的行什麼也不做。 – Alnitak

+2

'MyCircle.prototype.radius;'行不是聲明。這是對「未定義」屬性的匿名訪問。它基本上與編寫'undefined;'相同。 – eyelidlessness

回答

10

存儲在原型值提供一個對應的屬性默認值。

如果隨後向該屬性寫入值,則實例將獲取該新值,從而隱藏原型上的值,該值將保持不變。

在現在你已經加入到這個問題的代碼的情況下:

MyCircle.prototype.radius; 

絕對沒有。這是一個無操作 - 它試圖讀取該屬性,然後丟棄結果。

46

原型上的值具有與直接在實例上設置的屬性不同的關鍵行爲。試試這個:

// Create a constructor 
function A() {} 

// Add a prototype property 
A.prototype.name = "Freddy"; 

// Create two object instances from 
// the constructor 
var a = new A(); 
var b = new A(); 

// Both instances have the property 
// that we created on the prototype 
console.log(a.name); // Freddy 
console.log(b.name); // Freddy 

// Now change the property on the 
// prototype 
A.prototype.name = "George"; 

// Both instances inherit the change. 
// Really they are just reading the 
// same property from the prototype 
// rather than their own property 
console.log(a.name); // George 
console.log(b.name); // George 

如果沒有原型繼承,這是不可能的。

您可以使用hasOwnProperty方法測試屬性是實例屬性還是原型屬性。

console.log(a.hasOwnProperty("name")); // false 

實例可以覆蓋值prototype

b.name = "Chris"; 
console.log(b.hasOwnProperty("name")); // true 
console.log(a.name); // George 
console.log(b.name); // Chris 

並返回到prototype的值。

delete b.name; 
console.log(b.hasOwnProperty("name")); // false 
console.log(b.name); // George 

這是原型繼承的有力組成部分。

在其它模式:

function A() { 
    this.name = "George"; 
} 

this.name變量與每一個新的實例再次聲明。

將方法作爲函數在原型上聲明是有道理的。所有實例都可以共享一個函數,而不是在每個實例上重新聲明函數定義。

在變量而不是函數方面,如果實例沒有設置自己的值,原型可以用作默認值。

The code in a fiddle

+0

是的,我明白了。但我一直在看的代碼更像這樣: – DaveM

+0

評論你的更新 –

0

是的,我同意原型可用於屬性(變量)的默認值。構造函數不需要聲明屬性;它可能有條件地完成。

function Person(name, age) { 
    this.name = name; 

    if (age) { 
     this.age = age; 
    } 
} 

Person.prototype.sayHello = function() { 
    console.log('My name is ' + this.name + '.'); 
}; 

Person.prototype.sayAge = function() { 
    if (this.age) { 
     console.log('I am ' + this.age + ' yrs old!'); 
    } else { 
     console.log('I do not know my age!'); 
    } 
}; 

Person.prototype.age = 0.7; 

//----------- 

var person = new Person('Lucy'); 
console.log('person.name', person.name); // Lucy 
console.log('person.age', person.age); // 0.7 
person.sayAge();       // I am 0.7 yrs old! 

查看如何露西的age有條件聲明並初始化。

0

其他答案已經解釋了原型與實例屬性之間的區別。

但只是添加到答案,讓我們打破你的代碼片段:

(function(){       // <------- 1 
    // constructor 
    function MyCircle(radius){  // <------- 2 
     this.radius = radius;   // <------- 2.1 
    } 
    MyCircle.prototype.radius;  // <------- 3 
    this.area = function(){   // <------- 4 
     return 3.14*this.radius*this.radius; 
    }; 
    window.MyCircle = MyCircle;  // <------- 5 
}()); 
  1. 創建IIFE充當內碼
  2. 一個範圍容器聲明一個函數使用一個名爲MyCircle一個構造函數模式(但要注意它永遠不會被「構造」,所以應該可能會因爲誤導而丟掉大寫字母)
    • 調用時造成的調用對象
  3. ,試圖在MyCircle功能的prototype不存在訪問radius財產上radius實例屬性,因此計算結果爲undefined
  4. 創建全局窗口上area實例屬性對象併爲其分配函數表達式
  5. window對象上創建MyCircle實例屬性併爲其分配MyCircle函數

摘要:好像它創造了全球window對象上的areaMyCircle屬性,當調用MyCircle它會創建一個額外的radius屬性。

用法: MyCircle應區之前,因爲面積依賴於MyCircle初始化半徑調用:

window.MyCircle(10); 
window.area(); // evaluates to 314 
相關問題