简单示例理解神闭包

闭包,一个近乎神话的概念,对于那些有一点javascript使用经验但从未真正理解闭包概念的人来讲,理解闭包能够看作是某种意义上的重生,可是须要付出很是多的努力才能理解这个概念,今天咱们经过简单示例来理解一下神闭包。
// 最简单的闭包示例
function foo(){
    var a = 2;

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

    return bar;
}

var baz = foo();
baz(); // 2   ----朋友,这就是闭包效果

// 传递函数的闭包效果
function foo(){
    var a = 2;

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

    bar(baz);
}

function bar(fn){
    fn();     // 妈呀快看啊,这就是闭包效果
}

// 传递函数固然也能够是间接的
var fn;

function foo(){
    var a = 2;

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

    fn = baz;
}

function bar(){
    fn();   // 妈呀快看啊,这就是闭包效果
}

foo();

bar(); // 2

// 到处都是闭包,延时器方法来演示闭包
function wait(message){

    setTimeout(function timer(){
        console.log(message);
    }, 1000);
}

wait("hello,closure!");

//将一个内部函数(名为timer)传递给setTimeout(..)。timer具备涵盖wait(..)做用域的闭包。所以还保有对变量message的引用。
//wait(..)执行1000毫秒后,它的内部做用域并不会消失,timer函数依然保有wait(..)做用域的闭包。
//深刻到引擎的内部原理中,内置的工具函数setTimeout(..)持有对一个参数的引用,这个参数也许叫作fn或者func,或者其余相似的名字。
//引擎会调用这个函数,在例子中就是内部的timer函数,而词法做用域在这个过程当中保持完整。
//这就是闭包。

// 循环和闭包
// 要说明闭包,for循环是最多见的例子。
for(var i=1;i<=5;i++){
    setTimeout(function timer(){
        console.log(i);
    }, i*1000);
}

// 正常状况下,咱们对这段代码行为的预期是分别输出数字1~5,每秒一次,每次一个。
// 但实际上,这段代码在运行时会以每秒一次的频率输出五次6.

// 仔细想一想缘由,关键在于延迟函数的回调会在循环结束时才执行,而当循环结束后,i的值已经变为了6
// 咱们能够看看最终运行的顺序是下面这样的
setTimeout(function timer(){
    console.log(6);
}, 1*1000);
setTimeout(function timer(){
    console.log(6);
}, 2*1000);
setTimeout(function timer(){
    console.log(6);
}, 3*1000);
setTimeout(function timer(){
    console.log(6);
}, 4*1000);
setTimeout(function timer(){
    console.log(6);
}, 5*1000);

// 想要实现咱们要的效果,实际上须要给回调函数一个独立的i的副本,这样i的值变化,就不会影响回调函数执行中得副本值了
for(var i=1;i<=5;i++){
    (function(){
        var j = i;
        setTimeout(function timer(){
            console.log(j);
        }, j*1000);
    })();
}

// 或者以下写法也能够
for(var i=1;i<=5;i++){
    (function(j){
        setTimeout(function timer(){
            console.log(j);
        }, j*1000);
    })(i);
}

// 重返块做用域,let关键字能够实现,但由于目前对浏览器的支持不够,支持javascript1.8版本以上的浏览器才能够,因此咱们建议非特殊状况,不使用这个关键字
for(var i=1;i<=5;i++){
    let j=i;
    setTimeout(function timer(){
        console.log(j);
    }, j*1000);
}
//或者更简单写法
for(let i=1;i<=5;i++){
    setTimeout(function timer(){
        console.log(i);
    }, i*1000);
}

//正确的效果的运行顺序以下:
setTimeout(function timer(){
    console.log(1);
}, 1*1000);
setTimeout(function timer(){
    console.log(2);
}, 2*1000);
setTimeout(function timer(){
    console.log(3);
}, 3*1000);
setTimeout(function timer(){
    console.log(4);
}, 4*1000);
setTimeout(function timer(){
    console.log(5);
}, 5*1000);

  

经过这几个简单示例,对闭包有了初步了解,闭包到处都在,在意咱们如何观察和理解
更多信息能够看看个人博文,并下载相关资料
相关文章
相关标签/搜索