编程语言
首页 > 编程语言> > Javascript关闭问题

Javascript关闭问题

作者:互联网

所以,我还在阅读Apress Pro Javascript技术,我遇到了关闭问题.

正如John Resig所说:

Closures allow you to reference variables that exist within the parent function.
However it does not provide the value of the variable at the time it is created; It provides the last value of the variable withing the parent function. The most common issue under which you’ll see this occurr during a for loop. There is one variable being used as an interaor (e.g., i). Inside of the for loop, new functions are being created that utilize the closure to reference the iterator again. The rpoblem is tat the time the new closured functions are called, they will reference the last value of the iterator (i.e., the last position in an array), not the value taht you woul expect.

然后他在清单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);
        };
    })();               
}

此示例按预期工作,主对象的行为正确.

在下文中,它在迭代期间使用另一个时间自动执行函数来引入范围.

该函数的目的是创建一个对象,为其所有属性定义getter和setter.在这种情况下,该示例不起作用.

/**
 * 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);                   
    }

我的问题是:

>为什么在第一种情况下(for循环),没有必要传递i参数,而
在第二个(for in)需要它才能正常工作?

解决方法:

在第一个示例中,您声明了一个局部变量中数组元素内容的副本:

var item = items[i];

正如内联评论所说,这里我们记住了闭包范围内的价值.

在第二个示例中,您可以完成以下操作,而不是将i作为参数传递:

   (function() {

       var prop = i; // See here!

       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作为参数传递,而不是在变量中详细声明它.

(function(item) {
    // Bind a function to the element
    obj["on" + items[item] = function() {
        // item refers to a parent variable that has been successfully
        // scoped within the context of this loop
        alert("thanks for your " + items[item]);
    };
})(i);     

使用var语句声明变量的本地副本或将其作为参数传递给自执行函数是任意的.

编辑:

@Zecc在评论中买了个好点,我想解释一下:

(function (i) {

    // using `i` works as expected. 

}(i));

在哪里:

(function () {

    var i = i;

    // using `i` doesn't work... i = undefined.

}());

这是因为var variable = value语句是有效的:

(function () {

    var i;

    i = i;

}());    

并且var关键字始终使用值undefined分配其后的变量.

标签:for-in-loop,javascript,for-loop,closures
来源: https://codeday.me/bug/20190903/1795211.html