Skip to content

作用域和闭包 - 知识点

仲灏约 1 分钟

作用域和闭包 - 知识点

作用域

所谓作用域,即一个变量的合法使用范围

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

  • 作为普通函数调用
  • 使用 call apply bind
  • 作为对象方法调用
  • 在 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() // 打印什么

上次更新:

讨论区

欢迎留下想法与补充