Итак, я все еще читаю Apress Pro Javascript Techniques, и у меня проблемы с закрытием.
Как утверждает Джон Резиг:
Замыкания позволяют ссылаться на переменные, существующие в родительской функции. Однако он не предоставляет значение переменной во время ее создания; Он предоставляет последнее значение переменной в родительской функции. Наиболее распространенная проблема, при которой вы увидите это событие во время цикла for. Существует одна переменная, используемая в качестве интерферента (например, i). Внутри цикла for создаются новые функции, которые используют замыкание для повторной ссылки на итератор. Проблема заключается в том, что во время вызова новых закрытых функций они будут ссылаться на последнее значение итератора (т. е. на последнюю позицию в массиве), а не на то значение, которое вы ожидаете.
Затем он представляет в листинге 2-16 пример использования анонимных функций для определения области видимости.
/**
* Listing 2-16. Example of Using Anonymous Functions to induce the
* Scope Needed to Create Multiple Closure-Using Functions
*/
// An element with an ID of main
var obj = document.getElementById("main");
// An array of items to bind to
var items = ["click", "keypress"];
for (var i = 0; i < items.length; i++) {
// Use a self executed anonymous function to induce scope
(function() {
// Remembre the value within this scope
var item = items[i];
// Bind a function to the element
obj["on" + item] = function() {
// item refers to a parent variable that has been successfully
// scoped within the context of this loop
alert("thanks for your " + item);
};
})();
}
Этот пример работает так, как ожидалось, и поведение основного объекта правильное.
Далее он в другой раз использует самовыполняющуюся функцию для создания области действия во время итерации.
Цель функции — создать объект, определив геттеры и сеттеры для всех его свойств. В этом случае пример не работает.
/**
* Listing 2-25. Example of Dynamicaaly Generated Methods That Are Created
* When a New Object is instantiated
*/
// Create a new user object that accepts an object of properties
function User(properties) {
// Iterate thorugh the properties of the object, and make sure
// that it's properly scoped (sas discussed previously)
var that = this;
for (var i in properties) {
(function() {
console.log("property: " + i);
// Create a nwe getter for the property
that["get" + i] = function() {
return properties[i];
};
// Create a new setter for the property
that["set" + i] = function(val) {
properties[i] = val;
};
})();
}
}
// Create a new user object instance and pass in an object of
// properties to seed it with
var user = new User({
name: "Bob",
age: 44
});
// Just note that the name property does not exists, as it's private within the
// properties object
alert(user.name == null);
// However, we're able to access its value using the new getnaem()
// method that was dynamically generated
console.log("name: " + user.getname()); // name: 44 :(
alert(user.getname() == "Bob");
// Finally, we can see that it's possible to set and gt the age using
// the newly generated functions
user.setage(22);
alert(user.getage() == 22);
Вместо этого после передачи параметра i в качестве аргумента самовыполняющейся функции он работает.
for (var i in properties) {
(function(prop) {
console.log("property: " + i);
// Create a nwe getter for the property
that["get" + prop] = function() {
return properties[prop];
};
// Create a new setter for the property
that["set" + prop] = function(val) {
properties[prop] = val;
};
})(i);
}
Мой вопрос:
- Почему в первом случае (для цикла) параметр i передавать не нужно, а
во втором (для in) он нужен для корректной работы?