这是我参与更文挑战的第11天,活动详情查看:更文挑战
首先我们来看一个例子:
function foo() {
var myName = "啊巴啊巴"
let test1 = 1
const test2 = 2
var innerBar = {
getName: function() {
console.log(test1)
return myName
},
setName: function(newName) {
myName = newName
}
}
return innerBar
}
var bar = foo()
bar.setName("伊卡巴卡")
bar.getName()
console.log(bar.getName())
复制代码
构成闭包的是myName
和test1
此时有全局执行上下文和foo函数执行上下文,而执行上下文当中又分为变量环境和词法环境。
图片来自于极客时间专栏课程。
在 JavaScript 中,根据词法作用域的规则,内部函数总是可以访问其外部函数中声明的变量,当通过调用一个外部函数返回一个内部函数后,即使该外部函数已经执行结束了,但是内部函数引用外部函数的变量依然保存在内存中,我们就把这些变量的集合称为闭包。比如外部函数是 foo,那么这些变量的集合就称为 foo 函数的闭包。
所以实际上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
那么我们再看看下面这段代码:
var bar = { // 注意:此时的bar不是函数,而是变量
myName: "阿巴阿巴", // 因此该myName只是对象的一个属性
printName: function() { // 这里的printName是一个全局声明的函数
console.log(myName)
}
}
function foo() {
let myName = "伊卡巴卡"
return bar.printName // 调用的是bar变量,所以跟上一行的myName变量无关
}
let myName = "巴巴巴巴"
let _printName = foo()
_printName() // 巴巴巴巴
bar.printName() // 巴巴巴巴
复制代码
上面的这段代码不构成闭包。因为_printName()
调用的foo()
函数 return 的是bar
变量,也就是跟foo
函数里的myName
无关。 然后因为 bar
不是函数而是变量,所以跟bar里面的myName属性无关。最终寻找全局执行上下文中的词法环境中的myName也就是“巴巴巴巴”。
所以总结来说,闭包其实就是能够读取其他函数的内部变量的函数。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END