欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

顽皮的闭包 博客分类: 前端脚本 JavaScriptASPHTML 

程序员文章站 2024-03-08 13:36:52
...
部分引用来源:http://www.cnblogs.com/rubylouvre/archive/2009/07/24/1530074.html


问题描述
有个函数fn, 定义在某作用域r中, 函数fn的定义语句中包含对作用域v的某个变量v的引用, 由于变量v的作用域在v中, 所以倘若函数a将变量v绑定到位于其他作用域的应用中时, 变量v无法以window.v 或者 obj.v 的形式在后期引用, 只好以指针或者变量地址方式保存在函数a中用以持久变量v.

问题实质
Javascript中的函数可通过作用域链来访问自身未定义的变量, 但是因为被引用的变量位于某局部作用域, 实际引用会导致其生命周期被持久维持, 形成闭包.

相关资料
引用
闭包,是指语法域位于某个特定的区域,具有持续参照(读写)位于该区域内自身范围之外的执行域上的非持久型变量值能力的段落。这些外部执行域的非持久型变量神奇地保留它们在闭包最初定义(或创建)时的值(深连结)。

理解 JavaScript 闭包
深入理解Javascript闭包(closure)

解决方案
1. 使用可访问的全局对象成员变量存储有效引用, 即局部变全局
2. 使用绑定时可访问的私有作用域的成员变量存储有效引用, 即私有的, 一对一的更多闭包

实例
<ul>
    <li id="a1">aa</li>
    <li id="a2">aa</li>
    <li id="a3">aa</li>
</ul>

<script type="text/javascript">

for (var i=1; i < 4; i++) {
    var id = document.getElementById("a" + i);
    // 这里生成了一个匿名函数并赋值给对象id_i;
    id.onclick = function() {
        // 这个i来源于局部变量,无法以window.i或者obj.i的形式在后期引用,
        // 只好以指针或者变量地址方式保存在这个匿名函数中,
        // 这就是传说的闭包,所以所有这个过程中生成的事件句柄都使用引用
        // 的方式来持久这个变量,也就是这些匿名函数共用一个变量i;
        alert(i); // => 现在都是返回4
    };
}

// 局部变全局

for (var i = 1; i < 4; i++) {
    var id = document.getElementById("a" + i);
    id.i = i; // 这个i有了根[1]
    id.onclick = function() {
        alert(this.i);
    };
};

for (var i = 1; i < 4; i++) {
    var id = document.getElementById("a" + i);
    window[id.id] = i; // 这个i有了根[1]
    id.onclick = function() {
        alert(window[this.id]);
    };
}

// 产生一对一的更多闭包

for (var i = 1; i < 4; i++) {
    var id = document.getElementById("a" + i);
    id.onclick = (function(i) {
        return function() {
            alert(i); // 这个i是实参的闭包[2]
        }
    })(i);
};

for (var i = 1; i < 4; i++) {
    var id = document.getElementById("a" + i);
    id.onclick = new function() {
        var i2 = i; // 这个i是闭包的闭包[2]
        return function() {
            alert(i2);
        }
    };
}

</script>
  • closure.rar (1.4 KB)
  • 描述: Test Case
  • 下载次数: 1