一、作用域
作用域规定了变量保存与读取规则:一般情况下,内部作用域可以访问外层作用域中的变量,外部作用域无法读取内部作用域的数据。
js中作用域大概分为: 全局作用域,函数作用域,es6新增的会计作用域(for循环体和花括号’{}’,还有使用函数参数默认值时产生)
二、闭包
1、通俗理解:可以引用其他函数内部变量的函数。
开发者可以把数据保存在函数内部作用域独立管理,通过闭包的形式向外界提供访问权限。
2、闭包常见形式
可以访问其他函数内部变量的函数
(1)返回的内部函数
(2)函数作为参数调用
三、闭包应用
1、数据缓存
function myCache(){
let cache = {};
return {
set(key, val){
cache[key] = val
},
get(key){
return cache[key]
}
}
}
let cacheTool = myCache()
2、防抖节流函数
四、解决循环输出问题
for(var i=1;i<=5;i++){
setTimeout(function() {
console.log(i)
}, 0)
}
1、为什么会打印6
js解析器的运行规则:声明变量时,先查询该变量是否已经在当前作用域声明,如果已经声明则会对变量进行赋值操作。
(1)setTimeout和主线程同步代码都是宏任务,循环体执行完以后,全局作用域中保存了值为6的变量i
(2)之后执行setTimeout的回调函数,回调函数引用着全局作用域中的变量i,所以打印的都是6
2、解决方法
(1)给setTimeout传入第三个参数,在执行回调时作为参数传递给回调函数
(2)循环体中用let声明变量,可以创建多个作用域,分别保存不同的i变量供setTimeout回调引用
(3)利用匿名立即执行函数(IIFE),创建多个作用域,和let的原理一样