JavaScript闭包原理与使用

    科技2025-01-26  4

    闭包

    闭包就是能够读取其他函数内部变量的函数,例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数”。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。 闭包主要作用目的是防止变量污染,让闭包所在的函数中有相对独立的命名空间和作用域

    实例

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <button>我是按钮1</button> <button>我是按钮2</button> <button>我是按钮3</button> </body> </html> <script charset="utf-8"> /*var a = 1; var a_fn = 10, a_fn_fn1 = 20; function fn(){ var a_fn = 2; console.log("我在fn中"+a);//可以直接访问全局变量a function fn1(){ var a_fn_fn1 = 3; console.log("我在fn中的fn1中"+a); console.log("a_fn in fn1 "+ a_fn); function fn2(){ //这里就全部访问到 console.log("我在fn中的fn1中的fn2中") console.log(a,a_fn,a_fn_fn1); } return fn2; } return fn1; } fn()()();//作用域链的典型案例,每执行一次括号,就执行了返回的一个函数 console.log(a_fn);//这里报错,在外面访问不了函数内部的变量 console.log(a, a_fn, a_fn_fn1);//这里的变量和函数中定义的变量完全没有冲突,就可以实现相对独立的命名空间*/ /*function fun1(){ var a = 1; function fun2(){ a++; return a; } return fun2; } var f = fun1(); console.log(f()); f(); f(); console.log(f());//结果变为5了,说明每次执行f的时候,都会让a在原来的基础上计算 var f1 = fun1();//重新使用一块新的内存空间 console.log(f1());//这里的值又变回2了,说明每次用Var定义变量的时候,都会有一个新的首地址,相当于定义了一个新的函数,和之前定义的完全没有冲突 var f2 = f;//将f这个首地址给了f2 //同一个函数,同一片内存空间 console.log(f2());//这个地方的值是6,说明我们f2和f的首地址指向同一个地方,f2和f相当于是*/ //------------闭包在dom中的作用 /* //点击按钮任意按钮都是现实我是按钮3的问题 var nodes = document.getElementsByTagName("button"); for(var i = 0; i< nodes.length; i++){ nodes[i].onclick = function(){ alert("我是按钮"+i); } }*/ /*var arr = []; for(var i = 0; i < 4; i++){ setTimeout(() => { arr.push(i); },1000); }*/ console.log(arr);//这里是空数组,因为我们使用了异步操作,当我们打印arr的时候,arr还没有赋值 //--------------------- /* var arr = []; for(var i = 0; i < 4; i++){ setTimeout(() => { arr.push(i) //并不是把0-3赋值进去,而是循环结束以后的i值4 }, 1000); } setTimeout(() => { console.log(arr);//这里的结果都是4 }, 5000);*/ //--------------下面的过程才是上边循环过程 /* var arr = [] i = 0; setTimeout(() => { arr.push(i) //并不是把0-3赋值进去,而是循环结束以后的i值4 }, 1000); i = 1; setTimeout(() => { arr.push(i) //并不是把0-3赋值进去,而是循环结束以后的i值4 }, 1000); i = 2; setTimeout(() => { arr.push(i) //并不是把0-3赋值进去,而是循环结束以后的i值4 }, 1000); i = 3; setTimeout(() => { arr.push(i) //并不是把0-3赋值进去,而是循环结束以后的i值4 }, 1000); i = 4; setTimeout(() => { console.log(arr); }, 5000);*/ //--------------使用立即执行的函数的方法将i值立刻传过去,闭包原理 /*var arr = [] i = 0; (function(a){ setTimeout(() => { arr.push(a) //这里的a值是立即传进来的,并不是等1秒以后的i }, 1000) })(i) i = 1; (function(a){ setTimeout(() => { arr.push(a) //这里的a值是立即传进来的,并不是等1秒以后的i }, 1000) })(i) i = 2; (function(a){ setTimeout(() => { arr.push(a) //这里的a值是立即传进来的,并不是等1秒以后的i }, 1000) })(i) i = 3; (function(a){ setTimeout(() => { arr.push(a) //这里的a值是立即传进来的,并不是等1秒以后的i }, 1000) })(i) i = 4; setTimeout(() => { console.log(arr); }, 5000);*/ //------------------------------再回来修改之前的循环 /*var arr = []; for(var i = 0; i < 4; i++){ (function(a){ setTimeout(() => { arr.push(a) //这里的a是立即将i传进来的a,只不过是等1秒后执行而已 }, 1000); })(i) } setTimeout(() => { console.log(arr);//这里的结果是[0,1,2,3] }, 5000);*/ //------------再看遗留问题解决方案 var nodes = document.getElementsByTagName("button"); for(var i = 0; i < 3; i++){ (function(a){nodes[a].onclick = function(){ alert("我是按钮"+a+1); } })(i) } </script>
    Processed: 0.010, SQL: 8