MyClass.prototype.settings = {}被第二次实例化覆盖

时间:2013-12-11 05:37:20

标签: javascript

我想知道为什么如果我将一个参数对象传递给我的构造函数,设置属性值会被后续实例化覆盖。

当我将参数作为单独的变量传递给构造函数时,不会发生这种情况。

此处示例:http://jsfiddle.net/KJ4CU/及以下

// First class
function Person(args) {
    for(s in args) {
       this.arguments[s] = args[s];   
    }
}

Person.prototype.arguments = {
    "gender" : null,
    "name" : null
};

Person.prototype.getGender = function() {
    return this.arguments.gender;
};

// Second class
function Animal(gender, name) {
    this.gender = gender;
    this.name = name;
}

Animal.prototype.getGender = function() {
    return this.gender; 
};

var p1 = new Person({ gender : "gal", name : "Jane"});
var p2 = new Person({ gender : "boy", name : "John"});
var a1 = new Animal("female", "Tina");
var a2 = new Animal("male", "Toto");

document.getElementById("p1").innerHTML = p1.getGender(); // boy
document.getElementById("p2").innerHTML = p2.getGender(); // boy
document.getElementById("a1").innerHTML = a1.getGender(); // female
document.getElementById("a2").innerHTML = a2.getGender(); // male

2 个答案:

答案 0 :(得分:0)

这是因为对象arguments是对象原型的属性:

Person.prototype.arguments = {
    "gender" : null,          
    "name" : null              
};

当你实例p2 = new Person()时,原型与p2共享,并且构造函数被调用:

function Person(args) {          // Constructor
    for(s in args) {             // Executed for each call to 'new Person()'
       this.arguments[s] = args[s];   
    }
}

this.arguments被解析为this.prototype.arguments,它指向Person.prototype.arguments:它是共享的,它是同一个对象。

因此,当您修改p2.arguments.name时,您需要修改p1.arguments.name

尝试在构造函数中向Person添加arguments属性,而不是使用原型。

function Person(args) {          // Constructor
    this.arguments = {           // Executed for each call to 'new Person()'
        gender: args.gender,     
        name: args.name
    };
}

这样,每次创建新this.argument时,Person都是新对象。

来自this answer

  

在基于类的系统中,方法(不是属性/字段)   被添加到原型中。而对象的字段是特定于实例的   因此在施工过程中会加入物体本身。

有关javascript原型的更多信息,另请参阅this article

答案 1 :(得分:-1)

你的Animal类是你应该怎么做的,我会坚持将一个对象作为参数传递,因为它使它更具可读性。在构造函数中,您可以选择如何处理缺少的参数(设置默认值或抛出错误)。

如果继承,传递一个参数对象也会更容易:Parent.call(this,args);

function Animal(args) {
    this.gender = args.gender||"boy";//defaults to boy
    //make name mandatory
    this.name = args.name||false;
    if(this.name===false)
      throw new Error("Can't create an Animal without passing a name");
}
Animal.prototype.getGender = function() {
    return this.gender; 
};
var p1 = new Animal({ gender : "gal", name : "Jane"});
var p2 = new Animal({ gender : "boy", name : "John"});