ES6 let
let
是 ES6 新增的命令,用来声明变量
let 用法和 var 类似,区别:
- var 声明变量存在变量提升,let 不存在变量提升
- var 可以重复声明变量,let 不可以重复声明
- let 声明变量存在块作用域({} 内)
js 闭包
闭包
就是能够读取其他函数内部变量的函数。由于 js 作用域链,只有函数内部的子函数才能读取函数内部的局部变量,所以可以把闭包简单理解成"定义在一个函数内部的函数",本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁
闭包用途:
- 使函数外部能够读取函数内部的变量
function fn() { var num = 1 //闭包:getNum函数通过作用域链可以访问到变量num,并将其返回到fn函数外部 return function getNum() { return num } } //变量num为fn函数的局部变量,函数外面无法访问 console.log(num) //报错:num is not defined //getNum函数作为fn函数的返回值被赋值给n,执行n返回num var n = fn() console.log(n()) //1
- 让函数内部变量的值始终保存在内存中
function add() { var num = 1 //闭包:addNum函数通过作用域链可以访问到变量num,并将其的累加值返回到add函数外部 return function addNum() { return num++ } } //addNum函数作为add函数的返回值被赋值给全局变量n,执行n返回num的累加值 //add函数内部引用着add函数里的变量num,所以变量num始终被保存在内存中,不会被释放 var n = add() console.log(n()) //1 console.log(n()) //2 console.log(n()) //3
使用 let 解决的闭包问题
举例:预期输出 0 1 2 3 4
for(var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i)
}, 0)
}
实际输出:
分析:
由于 js 是单线程的,按照 js 的事件循环机制,在执行同步任务 for 循环时,异步任务 setTimeout 定时器被放到任务队列中排队等待执行,等待 for 循环执行完,此时 i 的的值已经为5,任务队列中的五个 setTimeout 开始执行,访问到的 i 的值都为5,所以打印出来五个5
问题:
全局作用域中 var 声明的变量为全局变量,每次循环 i 的值不能被保存,这就会出现闭包问题
使用立即执行函数解决:
for(var i = 0; i < 5; i++) {
(function(i) {
setTimeout(function() {
console.log(i)
}, 0)
})(i)
}
输出:
分析:
在 for 循环中,将 setTimeout 定时器放到一个立即执行函数中,将每次循环 i 的值保存到函数作用域里,作为参数传递给 setTimeout,在执行五个 setTimeout 时访问到的 i 为当前函数作用域里每次循环保存起来的 i 的值,所以打印出来0 1 2 3 4
总结:
利用函数作用域形成闭包,保存每次循环 i 的值
使用 let 解决:
for(let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i)
}, 0)
}
输出:
分析:
将 for 循环中的 var 改为 let,这样在每次 for 循环之前都会生成一个块级作用域,每个块级作用域互不干扰,let 声明的变量 i 只在当前循环的块级作用域中有效,每一次循环的 i 都被声明为一个新的变量,在执行五个 setTimeout 定时器时访问到的 i 为当前块级作用域里声明的 i 的值,所以打印出来0 1 2 3 4
总结:
利用块级作用域形成闭包,保存每次循环 i 的值
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!