作用域和闭包 - 知识点
作用域
所谓作用域,即一个变量的合法使用范围
js
let a = 0
function fn1() {
let a1 = 100
function fn2() {
let a2 = 200
function fn3() {
let a3 = 300
return a + a1 + a2 + a3
}
fn3()
}
fn2()
}
fn1()作用域分类
- 全局作用域:在全局定义的变量,全局都可用,像 document
- 函数作用域:在某个函数中定义的变量,只能用于当前函数,像 a b
- 块级作用域(ES6):只能活跃于当前的块,示例如下
js
// ES6 块级作用域
if (true) {
let x = 100
}
console.log(x) // 会报错自由变量
- 一个变量在该作用域没有被定义,但被使用
- 向上级作用域去寻找该变量,层层往上找 —— 如上面的示例
闭包
闭包 —— 作用域应用的一个特殊情况。一般有两种书写形式:
- 函数作为参数被传入
- 函数作为返回值
js
// 函数作为返回值
function create() {
let a = 100
return function () {
console.log(a)
}
}
let fn = create()
let a = 200
fn()
// 函数作为参数
function print(fn) {
let a = 200
fn()
}
let a = 100
function fn() {
console.log(a)
}
print(fn)以上代码得出 —— 要在函数定义的地方(不是执行的地方)去寻找上级作用域!!!
闭包示例
js
// 隐藏数据,只提供 API
function createCache() {
let data = {} // 闭包中的数据,被隐藏,不被外界访问
return {
set: function (key, val) {
data[key] = val
},
get: function (key) {
return data[key]
}
}
}
let c = createCache()
c.set('a', 100)
console.log( c.get('a') )this
- 作为普通函数调用
- 使用
callapplybind - 作为对象方法调用
- 在 class 的方法中调用
- 箭头函数
js
// this 场景题 - 1
function fn1() {
console.log(this)
}
fn1() // 打印什么
fn1.call({ x: 100 }) // 打印什么
const fn2 = fn1.bind({ x: 200 })
fn2() // 打印什么
// this 场景题 - 2
const zhangsan = {
name: '张三',
sayHi() {
console.log(this)
},
wait() {
setTimeout(function() {
console.log(this)
})
},
waitAgain() {
setTimeout(() => {
console.log(this)
})
}
}
zhangsan.sayHi() // 打印什么
zhangsan.wait() // 打印什么
zhangsan.waitAgain() // 打印什么
// this 场景题 - 2
class People {
constructor(name) {
this.name = name
this.age = 20
}
sayHi() {
console.log(this)
}
}
const zhangsan = new People('张三')
zhangsan.sayHi() // 打印什么
讨论区
欢迎留下想法与补充