JavaScript中的块级作用域

块级作用域

  • ECMA新描述概念
  • let const的使用
  • let cons和var的区别
  • 块级作用域的使用
  • 模板字符串的详解
  • ES6函数的增强用法

1. ECMA文档中代码执行术语解析

ES5之前的术语:

  • 执行上下文栈(ECS)
  • 执行上下文(EC)
  • 变量对象(VO)
  • 全局对象(GO)
  • 激活对象(AO)
  • 作用域链(scope chain)

ES6之后的术语:

大差不差。

  1. 词法环境:
    1. 一个词法环境是由环境记录和一个外部词法环境组成。
    2. 一个词法环境经常用于关联函数声明、代码块语句、try-catch语句,当它们的代码被执行时,词法环境被创建出出来。

执行上下文会关联的词法环境有:

  • 词法环境
  • 变量环境

这两者在初始化时,值是一样的。

两者的区别:

  • 词法环境用于处理let const声明的标识符。
  • 变量环境用于处理var和function声明的标识符。
  1. 环境记录:
    1. 声明式环境记录:声明性环境记录用于ECMAScript语言语法元素的效果,比如函数声明、变量声明和直接将标识符绑定与ECMAScript语言值关联起来的Catch子句。
    2. 对象式环境记录:用于记录ECMAScript与元素效果,它将标识符绑定与某些对象的属性关联起来。

2. let/const

2.1 let/const基本使用

let与const都是用于声明变量的,使用方法与var差不多。

1
2
let a = 10;
const b = 20;

只是const有一点区别:

  • const声明的变量表示常量。
  • 它声明的变量一旦被赋值就不可以被更改。
1
2
const id = 001;
id = 002; // 报错
  • 如果声明的变量赋值是一个引用数据类型,可以更改该引用对象里面的内容,但是不可以更改该变量存储的对象地址值。
1
2
3
4
5
6
7
var obj = {
name:"adas",
age:12,
}

const info = obj;
info.name = "qwe"; // 成功,不报错

注意:

let与const不允许重复声明变量。

1
2
3
4
5
let name = "as";
let name = "qw"; // 报错

const id = "001";
const id = "002"; // 报错

2.2 let/const作用域提升

let/const与var另一个重要区别就是作用域提升

使用let声明的变量,在赋值之前访问时会报错。

但是不是在赋值之前变量都没有创建,而是

这些变量会在他们的词法环境被实例化时被创建,但是不可以访问,知道词法被绑定求值。

虽然变量在赋值之前就已经存在了,但是它并不能在赋值之前访问,所以我认为let/const没有作用域提升(作用域提升:在变量的作用域中,这个变量可以在声明之前被访问,这就是作用域提升)

所以:let/const没有作用域提升,但是会在解析阶段被创建出来。

  • 暂时性死区

    从作用域顶部到变量被声明赋值之前,这一段区域该变量都不可以被访问,这就是暂时性死区。

暂时性死区与定义的位置没有关系,只与代码执行的顺序有关系。

注意:

let/const不会添加到window。

var定义的变量是会默认添加到window的。

2.3 块级作用域

let-const的块级作用域。

代码块:

1
2
3
{
// 代码
}

也就是花括号包裹起来的一块代码,包括函数内部的函数体。

在ES5之前,只有全局作用域和函数作用域。

使用let/const/function/class声明的变量有块级作用域。