学校网站建设目的与意义,合肥网页定制,wordpress技术服务,新平台怎么推广对闭包的理解
闭包是内层函数使用外层变量 (子级可以访问父级的变量#xff0c;但是父级不可以访问子级的)
闭包是指有权访问另一个函数作用域中变量的函数#xff0c;创建闭包的最常见的方式就是在一个函数内创建另一个函数#xff0c;创建的函数可以访问到当前函数的局部…对闭包的理解
闭包是内层函数使用外层变量 (子级可以访问父级的变量但是父级不可以访问子级的)
闭包是指有权访问另一个函数作用域中变量的函数创建闭包的最常见的方式就是在一个函数内创建另一个函数创建的函数可以访问到当前函数的局部变量。
闭包有两个常用的用途
闭包的第一个用途是使我们在函数外部能够访问到函数内部的变量。通过使用闭包可以通过在外部调用闭包函数从而在外部访问到函数内部的变量可以使用这种方法来创建私有变量。闭包的另一个用途是使已经运行结束的函数上下文中的变量对象继续留在内存中因为闭包函数保留了这个变量对象的引用所以这个变量对象不会被回收。 这是因为 JavaScript 的垃圾回收机制会检查对象是否还被引用如果没有引用则认为该对象是垃圾可以被回收。而闭包的内部函数可能会继续访问外部函数的变量。只有当闭包函数本身也被销毁时其引用的外部作用域才会被释放。 比如函数 A 内部有一个函数 B函数 B 可以访问到函数 A 中的变量那么函数 B 就是闭包。
function A() {let a 1;window.B function () {console.log(a);};
}
A();
B(); // 1面试真题
1. 基础题
在 JS 中闭包存在的意义就是让我们可以间接访问函数内部的变量。经典面试题循环中使用闭包解决 var 定义函数的问题
for (var i 1; i 5; i) {setTimeout(function timer() {console.log(i);}, i * 1000);
}首先因为 setTimeout 是个异步函数所以会先把循环全部执行完毕这时候 i 就是 6 了所以会输出一堆 6。解决办法有三种
第一种是使用闭包的方式
for (var i 1; i 5; i) {(function (j) {setTimeout(function timer() {console.log(j);}, j * 1000);})(i); // 把i作为参数传递给前面括号里的j
}使用立即执行函数包裹 setTimeout 的回调函数能够创建一个闭包 在上述代码中首先使用了立即执行函数将 i 传入函数内部这个时候值就被固定在了参数 j 上面不会改变当下次执行 timer 这个闭包的时候就可以使用外部函数的变量 j从而达到目的。
第二种就是使用 setTimeout 的第三个参数这个参数会被当成 timer 回调函数的参数传入。
for (var i 1; i 5; i) {setTimeout(function timer(j) {console.log(j);},i * 1000,i);
}第三种就是使用 let 定义 i 了来解决问题了这个也是最为推荐的方式
for (let i 1; i 5; i) {setTimeout(function timer() {console.log(i);}, i * 1000);
}2. 变形题
/* TASK A1In the following code, what will be printed to console if a user clicks the first and fourth button? Why?
*/var nodes document.getElementsByTagName(button);for (var i 0; i nodes.length; i) {nodes[i].addEventListener(click, function () {console.log(You clicked element # i);});}输出的是 nodes.length的值
因为var生命的是函数作用域
解决 方法1let 方法2闭包 var nodes document.getElementsByTagName(button);for (var i 0; i nodes.length; i) {(function (i) {nodes[i].addEventListener(click, function () {console.log(You clicked element # i);});})(i);}