我想知道为什么如果我将一个参数对象传递给我的构造函数,设置属性值会被后续实例化覆盖。
当我将参数作为单独的变量传递给构造函数时,不会发生这种情况。
此处示例: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
答案 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"});