2013-12-11 1 views
0

Я хотел бы знать, почему, если я передаю объект аргументов моему конструктору, значения свойств параметра будут перезаписаны последующими экземплярами.MyClass.prototype.settings = {} перезаписывается вторым экземпляром

Этого не происходит, когда я передаю аргументы в виде отдельных vars для конструктора.

Пример здесь: 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 
+1

Параметр 'prototype' свойство является долевой собственностью. Почему вы используете его, если хотите, чтобы каждый экземпляр имел свой собственный? – Ian

+1

Экземпляр конкретного кода * always * входит в конструктор. Если вы хотите, чтобы каждый экземпляр имел свой собственный объект 'arguments', вам нужно создать объект в конструкторе. –

+0

Я просто хочу знать, почему prototype.settings.gender перезаписывается, а prototype.gender - нет. – user3062896

ответ

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.

Вместо использования прототипа попробуйте добавить свойства 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

Забавно, ссылка, предоставленная в вашем ответе, довольно хороша, но ответ с 739 неверен. Наследование, установив прототип Ребенка на экземпляр родителя, а не повторно, используя функцию родительского конструктора в Child, выполнив «Parent.apply (это, аргументы)», - это попытка начинающих использовать прототип в лучшем случае. Не стыдно признаться, что я совершил те же ошибки при запуске, но количество upvotes действительно отражает то, сколько программистов JS понимают, как работает прототип. – HMR

-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"}); 
+0

@ downvoter http://stackoverflow.com/help/privileges/vote-down «Используйте ваши downvotes всякий раз, когда вы сталкиваетесь с грубым, неряшливым, без усилий, пост или ответ, который явно и, возможно, опасно неверен». Я не думаю, что этот ответ относится к этим критериям. – HMR

Смежные вопросы