JS知识点3
1. 闭包(Closure)概念
ep:
function fn() {
var x = '文浩最帅'
return function () {
console.log(x)
}
}
var f = fn()
f() // 文浩最帅
来分析一下为什么f能读取到fn的内部变量
按照之前所说,fn()执行完毕后,将会被释放(浏览器回收),但是由于fn()中开辟的堆内存(0x001)被当前上下文(EC(FN))以外的变量或其他所占用(var f = fn()),所以当前上下文不能被释放
函数执行,会形成一个私有的上下文
- 里面的私有变量,收到私有上下文的“保护”,不受外界干扰
- 有可能形成不被释放的上下文,里面的私有变量和一些值,就会被“保护”起来,这些值可以供其“下级”上下文调用 我们把函数的这种“保护机制",称之为“闭包“(Closure)
2.关于闭包的练习
let x = 5
function fn(x) {
return function (y) {
console.log(y + (++x))
}
}
let f = fn(6)
f(7) // 14
fn(8)(9) // 18
f(10) // 18
let a = 0,
b = 0;
function A(a) {
A = function (b) {
alert(a + b++)
}
alert(a++)
}
A(1) // 1
A(2) // 4
想要给三个按钮添加上点击事件,使得点击打印出他们各自的索引。 但你用下面的代码,发现每个按钮点击打印出的索引值都是3,为什么呢?
let buttons = document.querySelectorAll('button')
for (let i = 0; i < buttons.length; i++) {
buttons[i].onclick = function () {
console.log(`当前点击按钮的索引:${i}`)
}
}
原理如下:
在循环的过程中,i在不断累加
到点击事件发生时,由于所有的函数的i值都是全局作用域下的i,故导致打印出的索引都是3
那怎么解决呢?就可以使用我们的闭包
let buttons = document.querySelectorAll('button')
for (let i = 0; i < buttons.length; i++) {
(function(i){
buttons[i].onclick = function () {
console.log(`当前点击按钮的索引:${i}`)
}
})(i)
}
使用自调用使得i成为每个函数中的私有变量,又因为形成了闭包不被释放,所以当被点击时,就会打印相应的索引了