简体   繁体   English

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

[英]Javascript - Set properties in the constructor or constructor's prototype property?

So I've seen and heard that the methods should be set in the constructor's prototype property so it doesn't have several different instances. 所以我已经看到并听说过这些方法应该在构造函数的prototype属性中设置,所以它没有几个不同的实例。 But what about properties themselves? 但物业本身呢? Which is best practice? 哪个是最佳做法? If that's the case, shouldn't constructor's always be empty? 如果是这样的话,构造函数不应该总是空的吗?

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

should this actually be...? 这应该是......?

function Gadget(name,color){}

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

If you set it on the prototype, the property is shared by all instances. 如果在原型上设置它,则属性由所有实例共享。 Not usually what you want. 通常不是你想要的。 II blogged about this at http://js-bits.blogspot.com/2014/10/understanding-prototypical-inheritance.html . 我在http://js-bits.blogspot.com/2014/10/understanding-prototypical-inheritance.html上发表了关于此的博文。 You usually want each Gadget to have their own name and color. 您通常希望每个小工具都有自己的名称和颜色。 How would you do that with the code you suggested? 你会用你建议的代码怎么做?

By the way, the code you suggested has undefined variables (name, color) 顺便说一下,你建议的代码有未定义的变量(名称,颜色)

The normal way is to set methods on the prototype, and regular values on the object itself. 通常的方法是在原型上设置方法,在对象本身上设置常规值。 Unless you do want a property to be shared by all instances, that's like what we would call static properties in static typed languages. 除非您确实希望所有实例共享一个属性,否则就像我们在静态类型语言中调用静态属性一样。

Here's an example 这是一个例子

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;
};

An important concept to remember is that writes (assignments) are always applied to the object itself, not the prototype. 要记住的一个重要概念是写入(赋值)始终应用于对象本身,而不是原型。 Reads, however, will traverse up the prototype chain looking for that property. 然而,读取将遍历寻找该属性的原型链。

That is 那是

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

For properties this may not behave the way you expect it to. 对于属性,这可能不像您期望的那样。 Methods should be declared as on the prototype, because you want all instances to share the same function reference. 应该在原型上声明方法,因为您希望所有实例共享相同的函数引用。 Properties are usually different per instance. 每个实例的属性通常不同。 You might not notice this when dealing with primitives, but you will experience "weird" behavior for properties that are objects (or arrays, …) 处理基元时可能不会注意到这一点,但对于作为对象(或数组,...)的属性,您遇到“怪异”行为

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM