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

时间:2013-04-01 17:44:07

标签: javascript constructor prototype

所以我已经看到并且听说过这些方法应该在构造函数的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;
};

2 个答案:

答案 0 :(得分:8)

如果在原型上设置它,则属性由所有实例共享。通常不是你想要的。我在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 :(得分:2)

对于属性,这可能不像您期望的那样。应该在原型上声明方法,因为您希望所有实例共享相同的函数引用。每个实例的属性通常不同。处理基元时可能不会注意到这一点,但体验对象(或数组,...)属性的“奇怪”行为

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