闭包
闭包就是能够读取其他函数内部变量的函数,例如在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>
转载请注明原文地址:https://blackberry.8miu.com/read-36211.html