/*
闭包:
mdn对闭包的定义是闭包是能够自由访问变量的函数
那什么是自由变量呢?
自由变量是指再函数中使用的,但既不是函数参数也不是函数局部变量的变量,
由此我们可知道,闭包是由两部分组成:
闭包=函数+函数能够自由访问的变量
我们可以举个例子来看下:
*/
var a=41
function kop(){
console.log(a)
}
kop()//所以,所有含的函数都是闭包,只是用的好与不好的区别,会不会造成变量的污染等一系列问题
/*
我们可以来看下关于代码是怎么执行上下的:如下面的例子
*/
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
var foo = checkscope();
foo();
/*
执行顺序:
1.首先javascript会进去全局代码,创建全局的执行上下文,全局上下文执行压入执行上下文栈
2.全局执行上下文初始化
3.执行checkscope()函数,然后创建checkscope()函数执行上下文,checkscope()函数执行上下文栈
4.checkscope()函数创建上下文栈,初始变量,this,作用域链,对象等
5.checkscope()函数执行完毕之后,checkscope()执行上下文从执行上下文中弹出
6.执行f函数,然后创建f函数上下文,f函数执行上下文栈
7.f函数执行上下文初始化,创建变量对象,作用域链,对象等
8.f函数执行完毕,f函数从上下文栈中弹出
看了以上的执行顺序我们会知道,当执行f函数的时候,checkscope()函数已经销毁了,为什么f函数还能访问checkscope()函数呢?
因为在执行f函数的时候维护了一个作用域链:
fContext = {
Scope: [AO, checkscopeContext.AO, globalContext.VO],
}
就是因为由这一个作用域链,所以f函数仍然可以读取到checkscope()函数的值
所以我们可以看下从实践角度来说的闭包的定义:
1.即使创建他的上下文已经销毁,它仍然存在,(比如函数从父函数中返回)
2.在代码中引入了自然变量
*/
var data = [];
for (var i = 0; i < 3; i++) {
//声明一个函数,并马上调用这个匿名函数就叫做立即执行函数;也可以说立即执行函数是一种语法,让你的函数在定义以后立即执行
//这里的function就是一个立即执行函数
/*
立即执行函数的语法:
第一种: 匿名函数包括在括号里面,后面根一个小括号
(function(){})()
第二种:匿名函数包裹在括号里面,小括号跟在函数后面
(function(){}())
*/
data[i] = (function (i) {
console.log(i)
return function(){
console.log(i);
}
})(i);
}
/**
当执行到data[0]()的时候,此时for循环已经执行完毕了,也销毁了,因为由作用域链的存在,
所以还是可以访问到for循环的值的,但是此时的作用域链上的值都是一样的,所以for循环到最后的值是一样的,
而我们使用立即执行函数,就是相当于改变的作用域链的指向,声明这个函数就会马上调用,所以此时里面成为一个
闭包,一个作用域,用来报存不同的i值,所以会不一样
立即执行函数会形成一个单独的作用域,我们可以封装一些临时变量或者局部变量,避免污染全局变量
*/
data[0]();
data[1]();
data[2]();
js之深入理解闭包
最新推荐文章于 2022-11-08 12:27:29 发布