[英]Why declare properties on the prototype for instance variables in JavaScript
我試圖了解這種名為JavaScript的黑色藝術 - 而且,我必須承認,對此非常興奮。 我一直在尋找代碼示例,主要來自“easeljs”,因為這是我將主要使用的。 我有點困惑..
我(我想)理解使用prototype
作為class
變量的函數或屬性與使用this.someProp
作為'實例'變量之間的區別(是的,我知道JavaScript中沒有類。)
我看過的代碼,我用作自己代碼的模板, declare
prototype
變量,然后用它來引用它們
在構造函數中:
this.name = name;
然后聲明:
Object.prototype.name;
然后,
this.name = "Freddy";
這是在用'new'調用的函數中,所以在這種情況下,據我所知, this
是指當前對象。 令我困惑的是原型聲明正在做什么以及為什么我們將它用於實例變量?
澄清 :在下面的代碼中,我沒有看到radius的原型聲明實現了什么:
(function(){
// constructor
function MyCircle(radius){
this.radius = radius;
}
MyCircle.prototype.radius;
this.area = function(){
return 3.14*this.radius*this.radius;
};
window.MyCircle = MyCircle;
}());
原型上的值具有與直接在實例上設置的屬性不同的鍵行為。 試試這個:
// 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
方法測試屬性是實例屬性還是prototype屬性。
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
變量。
將方法作為在原型上聲明的函數是有道理的。 所有實例都可以共享一個函數,而不是在每個實例上重新聲明函數定義。
就變量而不是函數而言,在實例未設置其自己的值的情況下,原型可以用於默認值。
存儲在原型上的值為該屬性提供默認值。
如果您隨后將值寫入該屬性,則實例將獲取該新值,隱藏原型上的值,該值將保持不變。
在代碼的上下文中,您現在已添加到問題中:
MyCircle.prototype.radius;
什么都不做。 這是一個無操作 - 它試圖讀取該屬性然后丟棄結果。
是的,我同意原型可以用於屬性(變量)的默認值。 構造函數不需要聲明屬性; 它可以有條件地完成。
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
是如何有條件地宣布和初始化的。
其他答案已經解釋了原型與實例屬性之間的區別。
但只是為了添加答案,讓我們分解你的代碼片段:
(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
}());
IIFE
,它充當內部代碼的范圍容器 MyCircle
的函數(但是觀察它永遠不會被“構造”所以應該擺脫大寫字母,因為它會誤導)
radius
實例屬性 MyCircle
函數prototype
中不存在的radius
屬性,因此求值為undefined
area
實例屬性並為其指定函數表達式 window
對象上創建MyCircle
實例屬性並MyCircle
分配MyCircle
函數 簡介:看起來它正在全局window
對象上創建一個area
和MyCircle
屬性,並且當調用MyCircle
時,它會創建一個額外的radius
屬性。
用法:應該在區域之前調用MyCircle,因為區域依賴於MyCircle初始化半徑:
window.MyCircle(10);
window.area(); // evaluates to 314
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.