【重读你不知道的js Plan】作用域与闭包【2】

作用域闭包

1. 概念

先来回忆一下词法作用域的概念:词法作用域就是定义在这个阶段的作用域,在你写代码时将变量和块作用域写在哪里来决定的。

当一个函数可以记住并访问所在的词法作用域的时候,就产生了闭包

function foo() {
    var a = 2;

    function bar() {
        console.log(a); // 2
    }
    bar();
 }
 foo();

当执行bar函数的时候 console.log(a); 这个a是不在bar的作用域里面的,
但是它会往外部函数寻找,如果有,就拿来使用

bar对a的引用,是词法作用域的一种查找规则 这种规则只是闭包的一部分

像上面这种就是符合bar执行刚好在词法作用域内,然后可以访问这个a

下面来看看如果bar执行的时候不在词法作用域里面,以便我们更好的理解闭包

2. 更清楚的闭包

function foo() {
    var a = 2;

    function bar() {
        console.log(a);
    }
    return bar;  // 当执行了foo() 返回bar
}
// 当foo执行完之后 函数和里面的变量本应该消失的,但是由于产生了闭包
// bar在foo执行完之后,依旧可以使用foo的内部作用域

var baz = foo(); // 将bar作为一个值传给baz 执行

baz(); //2

// bar在定义的词法作用域外面执行了

无论使用何种方式对函数类型的值进行传递,当函数在别处被调用的时候都会产生闭包

function foo() {
    var a = 2;

    function baz() {
        console.log(a);
    }

    bar(baz);
 }

 function bar(fn) {
     fn();  // baz 在这里被执行了 也是在块级作用域外面被执行
 }

function wait(message) {
    setTimeout( function timer() {
        console.log(message)
    },1000);
}
wait("hell");
// 将一个内部函数名为timer传递给setTimeout(...) timer具有涵盖wait作用一的闭包
// 因此还保存有对便利message的引用

3. 循环和闭包

for (var i = 0;i <= 5;i++) {
    setTimeout(function () {
        console.log( i ); // i封闭在一个共享的全局作用域中,因此实际只有一个i
    }, (i * 1000)); 
}

// 每次迭代都应该有一个作用域
var i;
for (i = 0;i <= 5;i++) {
    setTimeout(function () {
        console.log(i)
    }, (i * 1000));
}

每隔一秒都是输出6

如果要实现输出1,2,3,4,5.

for (var i = 1;i <= 5;i++) {
    (function(j) {
        setTimeout(function timer() {
            console.log(j)
        },j * 1000)
    })(i) // 每次都把i传进去
}

for (let i = 0;i <= 5;i++) {
        setTimeout(function () {
        console.log(i)
    }, (i * 1000));
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值