重学JS-8-函数作用域、闭包

2023-04-22 16:18:05 浏览数 (2)

思维导图

通过下面的思维导图,我们先对JavaScript的函数作用域、闭包一些基本的了解。

函数作用域

作用域决定了变量的可访问性,全局作用域,局部作用域(函数作用域)。

let和const具有块作用域,块级作用域包括在函数内部和在一个代码块内部。

作用域链

表示不同作用域里面,有多个同名变量,变量的优先次序。

例如在下面的例子中,a变量的作用域链是:局部变量a(banana)->全局变量a(apple),优先取到局部变量。

代码语言:javascript复制
let a = 'apple';
function say(){
    let a = 'banana';
    console.log(a);  // banana
}
say();

*var的声明提升

用var声明变量,会把变量声明提升到所有代码之前,类似示例2.

代码语言:javascript复制
// 示例1
var a = 'apple';
function say(){
    console.log(a);  // undefined
    var a = 'banana';
    console.log(a);  // banana
}
say();

上面的示例1等同于示例2。

代码语言:javascript复制
// 示例1
var a = 'apple';
function say(){
    var a;
    console.log(a);  // undefined
    a = 'banana';
    console.log(a);  // banana
}
say();

闭包

一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。

词法环境

词法环境(Lexical Environment)是作用域内部(隐藏)的关联对象。

词法环境对象由两部分组成:

  1. 环境记录(Environment Record) —— 一个存储所有局部变量作为其属性(包括一些其他信息,例如 this 的值)的对象。
  2. 外部词法环境 的引用,与外部代码相关联。

函数的执行,可以分为创建词法环境的阶段和执行的阶段。

创建阶段

创建作用域链、变量对象、决定this。

执行阶段

变量赋值、函数引用等。

看下面这个例子

代码语言:javascript复制
let name = 'apple'
function say(){
    let name = 'banana';
    console.log(name);
}

内部的语法环境,有name这个变量,外部的语法环境也有name这个变量。

代码访问变量时,先搜索内部的语法环境,如果逐层搜索外层的外部环境。

0 人点赞