javascript闭包原理(javascript闭包例子)

图片授权基于 www.pixabay.com 相关协议

老生常谈的话题。

闭包是对它所在作用域的引用,当函数「可以记住并且可以访问」所在词法作用域的时候,就会产生闭包。

先举个例子,最常见面试题:输出 1-10,每隔一秒输出一个自增值。

for (var i = 1; i < 10; i++) {    setTimeout(function() {        console.log(i);    }, i * 1000);}

?

我以前就是这样写,但发现会输出10个10,并没有按我理解的来输出。

为什么没有按「字面理解」执行?

这是因为 for 循环执行完 1-10 的循环,setTimeout 还没有执行一次。

for 循环执行的是微任务,setTimeout 执行的是宏任务。微任务先执行完毕后,才去执行宏任务。查看关于宏任务文章 JavaScript 执行任务

它们都被封闭在一个作用域中了,因此呢,执行的时候只有一个 i ,共享一个 i 的引用。

如果要实现每隔一秒输出一个自增值,可以使用「闭包」。

修正版:

for (var i = 1; i <= 5; i++) {  (function(j) {    setTimeout(function timer() {      console.log(j);    }, j * 1000);  })(i);}

使用 IIFE 自执行函数可以为每一次执行都生成一个新的作用域,将每个新的作用域都封闭在作用域内部,每个作用域内部都会有一个正常的值。

要想理解闭包,需要了解「作用域」的问题。闭包就是把当前作用域的访问权限交出去,你在什么地方调用都可以访问「闭包」作用域的内容。关于作用域 JavaScript 词法作用域

function webFn() {    var web = \\\"webtext\\\";    console.log(web); //webtext 可以访问变量 web}console.log(web); //web is not defined

?

函数里面的 web 参数可以直接访问到 web 变量。如果函数内部找不到,会继续向外层查找,直到找到最近的一个为止,如果没有找到,则为「is not defined」没有被定义。

外部的 web 不能访问 webFn 函数里面的内容,web 变量被定义在 webFn 函数里。外部不可以访问。

外部如果想访问函数里面的内容,就需要用到「闭包」。

function webFn() {    var web = \\\"webtext\\\";    return web; //返回 web (外部可以访问)}var webcopy = webFn();// LHS 获取 webFn() 的value ,webcopy 是 webFn() 的引用console.log(webcopy); //webtext

看一个《你不知道的JavaScript》书里的例子

    function foo(){    var a = 2;    function bar(){        console.log(a);// 2    }    return bar;}var baz = foo();baz();// 2

    return bar; 返回的是 bar() 这个函数,bar() 函数呢,是可以访问 foo() 函数内变量 a 的;执行 foo() 后,内部的 bar() 函数赋值给变量 baz 调用 baz(),实际上通过不同的「标识符引用」调用了内部的函数 bar();

    如果不 return bar,foo() 这个函数执行完后就是要被「垃圾回收机制」回收的,闭包就阻止了垃圾回收。所以 bar() 可访问的作用域的区域,就叫闭包。

    闭包也可以称为「存活作用域」。

    无论如何处理,将内部函数的 return 到当前词法作用域之外,它都保有对原始作用域的「引用」,无论在哪执行,执行体都可称为闭包。


    参考资料:

    [1]《You don\\’t know JavaScript》

    [2]https://segmentfault.com/a/1190000011198232
    [3]https://www.liaoxuefeng.com/wiki/1022910821149312/1023021187855808

    原创文章,作者:小道研究,如若转载,请注明出处:https://www.sudun.com/ask/34551.html

    Like (0)
    小道研究的头像小道研究
    Previous 2024年4月21日
    Next 2024年4月21日

    相关推荐

    发表回复

    您的邮箱地址不会被公开。 必填项已用 * 标注