写点什么

开源一夏 | JavaScript 实战之闭包与函数调用的相互应用详解

作者:黎燃
  • 2022 年 8 月 20 日
    内蒙古
  • 本文字数:1789 字

    阅读完需:约 6 分钟

JavaScript 闭包


JavaScript 变量可以是局部变量或全局变量。私有变量可以使用闭包。

全局变量

函数可以访问函数内部定义的变量,例如:


function myFunction() {    var a = 4;    return a * a;}
复制代码



在后一个示例中,a 是全局变量。在网页中,全局变量属于窗口对象。全局变量可以应用于页面上的所有脚本。在第一个示例中,a 是局部变量。局部变量只能在定义它的函数内使用。不适用于其他函数或脚本代码。全局变量和局部变量是两个不同的变量,即使它们具有相同的名称。修改其中一个不会影响另一个的值。


如果在声明变量时不使用 VaR 关键字,则它是全局变量,即使它是在函数中定义的。

变量生命周期

全局变量的范围是全局的,也就是说,在整个 JavaScript 程序中,全局变量无处不在。函数内声明的变量仅在函数内工作。这些变量是局部变量,范围是局部的;函数的参数也是局部的,仅在函数内工作。

计数器困境

想象一下,如果您想对一些值进行计数,并且计数器在所有函数中都可用。您可以使用全局变量设置计数器:


var counter = 0; function add() {   return counter += 1;} add();add();add();
复制代码


运行结果如下:



执行 add()函数时,计数器值会更改。但问题是,即使没有调用 add()函数,页面上的任何脚本都可以更改计数器。如果在函数中声明计数器,则在不调用函数的情况下无法修改计数器的值:



本意是想输出 3, 但事与愿违,输出的都是 1


function add() {    var counter = 0;    return counter += 1;} add();add();add();
复制代码



上述代码将无法正确输出。每次调用 add()函数时,计数器将设置为 1。JavaScript 嵌入函数可以解决这个问题。

JavaScript 内嵌函数

所有函数都可以访问全局变量。事实上,在 JavaScript 中,所有函数都可以访问上一层的范围。JavaScript 支持嵌套函数。嵌套函数可以访问上一级的函数变量。在本例中,嵌入式函数 plus()可以访问父函数的计数器变量:


function add() {    var counter = 0;    function plus() {counter += 1;}    plus();        return counter; }
复制代码


如果我们可以从外部访问 plus()函数,我们就可以解决计数器的困境。我们还需要确保 counter=0 只执行一次。我们需要关闭。

JavaScript 闭包

var add = (function () {    var counter = 0;    return function () {return counter += 1;}})(); add();add();add();
复制代码


变量 add 指定函数自调用的返回字值。自调用函数只执行一次。将计数器设置为 0。并返回函数表达式。add 变量可用作函数。最重要的是,它可以访问函数上方一级作用域中的计数器。这称为 JavaScript 闭包。它使得函数可以具有私有变量。计数器受匿名函数的作用域保护,只能通过 add 方法修改。

作为一个函数调用

myFunction(10, 2) 返回 20


function myFunction(a, b) {    return a * b;}myFunction(10, 2); 
复制代码


上述函数不属于任何对象。但它始终是 JavaScript 中的默认全局对象。html 中的默认全局对象是 html 页面本身,因此函数属于 html 页面。浏览器中的页面对象是浏览器窗口(窗口对象)。上述函数将自动成为窗口对象的函数。Myfunction()和 window Myfunction()


function myFunction(a, b) {    return a * b;}window.myFunction(10, 2);
复制代码


当函数没有被它自己的对象调用时,该函数的值将成为全局对象。在 web 浏览器中,全局对象是浏览器窗口(窗口对象)。此实例返回的值为窗口对象:


function myFunction() {    return this;}myFunction(); 
复制代码


当函数作为全局对象调用时,其值将成为全局对象。使用窗口对象作为变量很容易导致程序崩溃。

作为函数方法调用函数

在 JavaScript 中,函数是对象。JavaScript 函数有其属性和方法。Call()和 apply()是预定义的函数方法。可以使用两种方法调用函数。两个方法的第一个参数必须是对象本身。


function myFunction(a, b) {    return a * b;}myObject = myFunction.call(myObject, 10, 2);  
复制代码


两种方法都使用对象本身作为第一个参数。两者之间的区别是第二个参数:apply 在参数数组中传递,也就是说,多个参数组合成一个数组,call 作为 call 的参数传入(从第二个开始)。


function myFunction(a, b) {    return a * b;}myArray = [10, 2];myObject = myFunction.apply(myObject, myArray);
复制代码


在 JavaScript 严格模式下,调用函数时,第一个参数将成为 this 的值,即使该参数不是对象。在 JavaScript 非严格模式下,如果第一个参数的值为 null 或未定义,它将使用全局对象。

发布于: 刚刚阅读数: 2
用户头像

黎燃

关注

前端工程师 2022.05.06 加入

专注学习分享前端知识。

评论

发布
暂无评论
开源一夏 | JavaScript实战之闭包与函数调用的相互应用详解_开源_黎燃_InfoQ写作社区