js闭包两种写法的区别

(function(j) {  // j = i
    setTimeout(function() {
        console.log(new Date, j);
    }, 1000);
})(i);
function f1(){
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999

例子是随便找的,这两种写法有什么区别和相同点呢?

阅读 4.4k
3 个回答

不太清楚你想了解什么
闭包就是一种特性,用在哪里的目的都是保存上一层的作用域内的变量,没有什么区别
硬要说区别只是你用他的特性来做不同的事情
在我的理解里,你直接在全局作用域下定义一个函数,他也是一个闭包,因为他随时都可以访问到顶层作用域里的变量
再说一下你举的例子
1.严格来讲,这个例子应该叫自执行函数的应用,跟闭包关系不太大,真正用到闭包的是setTimeout里面的这个函数,他访问了外层的参数j(注意当执行的时候j的值是i传递的),所以这个也常用在for循环内,网上例子很多。
2.这个就是很常见的闭包使用了,暴露给外界一个接口函数,用来访问内部的n,可以用来模拟私有变量。

第一种常用语for循环中
因为js中只有函数内有独立作用域
for循环的i是全局变量 因为setTimeout延时执行调用的时候i值早已循环到4所以取到的都是4
通过自执行函数传入参数形成局部变量,获取的之后获取的局部作用域的i

for(var i=0;i<5;i++){
    setTimeout(function(j) {
        console.log(new Date, j);
    }, 1000, i);//setTimeout第三个参数之后都是回调的参数
}

第二种获取函数内局部变量
常用两种:
通过返回值

function f1() {
    var n = 999;
    function f2() {
        alert(n);
    }
    return f2;
}
var result1 = f1();
result1(); // 999

通过回调参数

function f2(fn) {
    var n = 999;
    fn(n);
}
f2(function(n) {
    alert(n)//999
});

不太清楚你想问什么。
我猜你第一种是想处理下面的情况

// 隔1秒输出5, 5, 5, 5, 5
for (var i = 0; i < 5; i++) {
    setTimeout(function () {
        // 直接使用i,因为i指向的内存不变,输出的时候i的值经过循环变成了5,所以输出5
        console.log(new Date(), i);
    }, i * 1000);
}

// 隔1秒输出0, 1, 2, 3, 4
for (var i = 0; i < 5; i++) {
    (function (j) {
        // 使用闭包,浏览器给j分配新的内存,不会随i的变化而变化
        setTimeout(function () {
            console.log(new Date(), j);
        }, j * 1000);
    })(i);
}

第二个则是

function f1() {
    // 闭包防止数据被外部访问
    var n = 999;
    function f2() {
        alert(n);
    }
    // 给f2一个add方法操作数据
    f2.add = function () {
        n++;
    }
    // 将f2暴露到外部
    return f2;
}

var result = f1();
result();   // 999
result.add();
result();   // 1000
result.n;   // undefined,无法获取到变量n
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题