Javascript - 在构造函数或构造函数的prototype属性中设置属性?

问题描述:

所以我见过并且听说应该在构造函数的prototype属性中设置方法,所以它没有多个不同的实例。但是属性本身呢?最佳做法是什么?如果是这样的话,不应该构造函数总是空的?Javascript - 在构造函数或构造函数的prototype属性中设置属性?

function Gadget(name, color) { 
    this.name = name; 
    this.color = color; 
    this.whatAreYou = function(){ 
     return 'I am a ' + this.color + ' ' + this.name; 
    } 
} 

这实际上应该是......?

function Gadget(name,color){} 

Gadget.prototype.name = name; 
Gadget.prototype.color = color; 
Gadget.prototype.whatAreYou = function() { 
    return 'I am a ' + this.color + ' ' + this.name; 
}; 

如果您在原型上设置它,则属性将由所有实例共享。通常不是你想要的。我在博客http://js-bits.blogspot.com/2014/10/understanding-prototypical-inheritance.html上发帖。您通常希望每个小工具都有自己的名称和颜色。你如何用你建议的代码来做到这一点?

顺便说一句,你的代码已经建议未定义的变量(名称,颜色)

正常的方法是设置对象本身上的原型方法,并定期值。除非你想要一个属性被所有的实例共享,这就像我们将静态类型语言中的静态属性一样。

下面是一个例子

function Gadget(name,color){ 
    this.name = name; 
    this.color = color; 
    // Since all gadgets in on the prototype, this is shared by all instances; 
    // It would more typically be attached to Gadget.allGadgets instead of the prototype 
    this.allGadgets.push(this); 
    // Note that the following would create a new array on the object itself 
    // not the prototype 
    // this.allGadgets = []; 

} 

Gadget.prototype.allGadgets = []; 
Gadget.prototype.whatAreYou = function() { 
    return 'I am a ' + this.color + ' ' + this.name; 
}; 

的一个重要概念要记住的是,写入(分配)总是应用于对象本身,而不是该原型。然而,阅读将遍历原型链寻找该属性。

也就是说

function Obj() { 
    this.map = {}; 
} 

function SharedObj() {} 
SharedObj.prototype.map = {}; 

var obj1 = new Obj(); 
var obj2 = new Obj(); 
var shared1 = new SharedObj(); 
var shared2 = new SharedObj(); 

obj1.map.newProp = 5; 
obj2.map.newProp = 10; 
console.log(obj1.map.newProp, obj2.map.newProp); // 5, 10 

// Here you're modifying the same map 
shared1.map.newProp = 5; 
shared2.map.newProp = 10; 
console.log(shared1.map.newProp, shared2.map.newProp); // 10, 10 

// Here you're creating a new map and because you've written to the object directly  
// You don't have access to the shared map on the prototype anymore 
shared1.map = {}; 
shared2.map = {}; 
shared1.map.newProp = 5; 
shared1.map.newProp = 10; 
console.log(shared1.map.newProp, shared2.map.newProp); // 5, 10 
+1

注:穿上原型的属性可以作为一个_default_行动值的实例值。 – Alnitak

+0

Duh ..感谢您指出......所以说构造函数只应该为传入的值设置属性是否公平? – KingKongFrog

+1

@Alnitak没关系,只要它不是引用类型(对象,数组)就可以共享 –

有关属性,这可能不是表现你期望的方式。应该在原型上声明方法,因为您希望所有实例共享相同的函数引用。每个实例的属性通常不同。与原语打交道时,你可能没有注意到这一点,但你体验“怪异”的行为是对象的属性(或阵列,...)

function Test(){} 
Test.prototype.foo = {bar: 1}; 
Test.prototype.baz = 1; 

var one = new Test(); 
var two = new Test(); 
one.foo.bar = 3; 
two.foo.bar === 3; // true, because of object reference 
// BUT: 
one.baz = 3; 
two.baz === 1; // true 
+1

奇怪的行为 - >共享属性。当你了解正在发生的事情时,并不奇怪。 –

+0

现在我很困惑......大声笑。所以你改变了bar的值,它更新了所有的实例,因为它是一个对象引用。但是,这些属性没有改变,因为它们都有自己的?我用数组'Test.prototype.bee = [1,2,3];'然后'one.bee.push(8);'尝试了同样的事情,并且这也只更新/创建了'one '...但不是'两'。所以这只适用于对象,而不是数组? – KingKongFrog

+0

@KingKongFrog如果你做'one.bee = []'在对象本身创建一个新的数组,而不是原型,它不共享。如果你做'one.bee.push(8)'你只修改现有的数组。写入(赋值运算符)始终在对象本身上,但是通过原型链完成读取。 –