01.【JS读书笔记】作用域

1.作用域的嵌套

在当前作用域中无法找到某个变量时,引擎就会在外层嵌套的作用域中继续查找,直到找到该变量,或抵达最外层的作用域(全局)为止。

LHS 查询和 RHS查询:如果查找的目的是对变量进行赋值,则使用LHS查询;如果目的是获取变量的值,则使用RHS查询

  • 不成功的LHS引用会导致自动隐式地创建一个全局变量(非严格模式下)
  • 不成功的RHS引用会导致抛出ReferenceError

2.词法作用域

查找 始终从运行时说出的最内部作用域开始,逐级向外/向上运行,知道遇到第一个匹配的标识符为止。

遮蔽效应:在多层的嵌套作用域中可以定义同名的标识符,内部的标识符“遮蔽”了外部的标识符,这被称为~。

词法作用域完全由写代码期间函数所声明的位置定义。

欺骗词法

欺骗词法(运行时修改词法作用域) ——— 导致性能下降,不建议使用

有两种机制实现(但并不推荐)

  • eval()
  • with

3.函数作用域和块作用域

3.1 函数中的作用域

含义: 属于这个函数的全部变量都可以在整个函数的范围内使用及复用(嵌套的作用域中也可)。

“隐藏”作用域中的变量和函数:符合最小授权/最小暴露原则;规避冲突

区分函数声明和表达式的方法:看function位置。function是声明中的第一个词,则是函数声明,否则是函数表达式。

3.2 块作用域

  • with —— 用with创建出的作用域仅在with声明中而非外部作用域中有效
  • try/catch —— 声明的变量仅在catch内部有效
  • let —— ES6引入的新let关键字,可以为其声明的变量隐式所在的块作用域
  • const —— 类似于let,但其值是固定的(常量)

4.变量提升

函数声明会被提升,但函数表达式不会。

//函数声明
function foo {
    console.log(a);     //undefined
    var a = 2;
};

等价于

//函数声明
function foo {
    var a;
    console.log(a);     //undefined
    a = 2;
};

但在函数表达式中,则不会发生提升

//函数表达式
foo();      //TypeError! (而不是ReferenceError)
bar();      //ReferenceError!

var foo = function bar (){
    // ...
};

实际上其等价于:

//函数表达式
var foo;
foo();      //TypeError! (而不是ReferenceError)
bar();      //ReferenceError!

foo = function (){
    var bar = ...self...
    // ...
};

注: 函数声明和变量声明都会被提升,但函数优先。

你可能感兴趣的:(01.【JS读书笔记】作用域)