Как уже упоминалось в комментариях, это проблема области видимости.
Ваша переменная действительно "поднята", но это не совсем проблема.Это главным образом потому, что переменная name
является частью глобальной области видимости.В JavaScript области видимости - это в основном функции.Управляющие структуры как циклы, условия ... не объявляют новые области.
Если вы сделаете это:
var first = {
bob: 'text',
jim: 42,
sue: true
},
second = {};
for (var name in first) {
Object.defineProperty(second, name, {
value: first[name],
enumerable: true
});
}
console.log(second.bob); // "test"
console.log(second.jim); // 42
console.log(second.sue); // true
Это будет работать, потому что first [name] оценивается на каждой итерации цикла.
Теперь, если вы это сделаете:
var first = {
bob: 'text',
jim: 42,
sue: true
},
second = {};
for (var name in first) {
Object.defineProperty(second, name, {
get: function() {
return first[name];
},
set: function(value) {
first[name] = value;
},
enumerable: true
});
}
console.log(second.bob); // true
console.log(second.jim); // true
console.log(second.sue); // true
Это не будет работать, потому что first [name] оценивается только при вызове функции getter / setter.Если после цикла вы выполните: second.bob
, будет вызвана функция-получатель, и она не найдет имя в своей области видимости.Затем он будет искать в родительской области, которая здесь является глобальной областью, где определено имя.Цикл завершен, имя равно последней итерации цикла.То же самое с сеттером, если вы делаете second.bob = 'new value';
.Область действия функции-установщика не имеет переменной name
и будет искать в глобальной области, где имя - это последняя итерация цикла.
Решение состоит в том, чтобы определить цикл структуры управления for
как область дляпеременная name
с ключевыми словами let
или const
.Вы также можете объявить свой процесс defineProperty в функции вне цикла и вызывать эту функцию только внутри цикла, передав ей параметр name
.В этом случае значение будет скопировано и «привязано» к новой области действия функции.
// With 'let'
for (let name in first) {
Object.defineProperty(second, name, {
// ...
});
}
// With 'const'
for (const name in first) {
Object.defineProperty(second, name, {
// ...
});
}
// With function
var defineProp = function (name) {
Object.defineProperty(second, name, {
// ...
});
};
for (var name in first) {
defineProp(name);
}