2013-05-25 131 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 
相关问题