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或未定义,它将使用全局对象。