Используемое вами значение this
относится к выражению функции автоматического вызова, которое у вас внутри цикла, и когда вы вызываете функцию таким образом, this
будет всегда обращаться к глобальному объект.
Редактировать: Я пропустил тот факт, что выражение функции пытается сделать захват переменной для обработки создания геттера / сеттера внутри цикла, но переменной цикла i
, для этого нужно передать в качестве аргумента, и поскольку здесь есть выражение функции, контекст (внешний this
) должен быть сохранен:
function UserDon( properties ) {
var instance = this; // <-- store reference to instance
for( var i in properties ) {
(function (i) { // <-- capture looping variable
instance[ "get" + i ] = function() {
return properties[i];
};
instance[ "set" + i ] = function(val) {
properties[i] = val;
};
})(i); // <-- pass the variable
}
}
var userdon = new UserDon( {
name: "Bob",
age: 44
});
userdon.getname(); // "Bob"
userdon.getage(); // 44
Вы также можете использовать метод call
для вызова выражения функции, сохранения контекста (значение this
) и введения циклической переменной в новую область за один шаг:
function UserDon( properties ) {
for( var i in properties ) {
(function (i) { // <-- looping variable introduced
this[ "get" + i ] = function() {
return properties[i];
};
this[ "set" + i ] = function(val) {
properties[i] = val;
};
}).call(this, i); // <-- preserve context and capture variable
}
}
Я бы также рекомендовал использовать if (properties.hasOwnProperty(i)) { ... }
внутри цикла for...in
, чтобы избежать перебора пользовательских расширенных свойств, унаследованных от Object.prototype
.