重点:

  • 声明提升
  • 暂时性死区

1.命名规则

  • 由字母(A-Za-z)、数字(0-9)、下划线(_)、美元符号( $ )组成,首字母只能为下划线、美元符号和字母
  • 严格区分大小写。var app; 和 var App; 是两个变量
  • 不能是关键字、保留字。
  • 遵守驼峰命名法。

    2. var

    按照早期JavaScript的约定,在全局代码块使用var声明(和具名函数声明语法)时,相当于在全局对象global上声明了一个属性,进而使所有代码都能将这些声明作为全局变量来访问。

  1. function test() {
  2. var message = "hi"; // 局部变量
  3. }
  4. test();
  5. console.log(message); // 出错!
  6. function test() {
  7. message = "hi"; // 全局变量
  8. }
  9. test();
  10. console.log(message); // "hi"

虽然可以通过省略var 操作符定义全局变量,但不推荐这么做。在局部作用域中定义的全局变量很难维护,也会造成困惑。这是因为不能一下子断定省略var 是不是有意而为之。在严格模式下,如果像这样给未声明的变量赋值,则会导致抛出 ReferenceError 。

声明提升

JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升(hoisting)

所谓的变量提升,是指在JavaScript代码执行过程中,JavaScript引擎把变量的声明部分和函数的声明部分提升到代码开头的“行为”。变量被提升后,会给变量设置默认值,这个默认值就是我们熟悉的undefined。

  1. // 在声明之前打印变量,可以验证变量会被提升。声明的提升
  2. // 意味着会输出undefined 而不是Reference Error
  3. function foo() {
  4. console.log(age);
  5. var age = 26;
  6. }
  7. foo(); // undefined
  • 变量函数在内的所有声明都会在任何代码被执行前首先被处理。
  • 比如 var a = 2,可能会认为这是一个声明,Javascript实际上会将其看成两个声明:var aa = 2,第一个定义声明是在编译阶段进行的,第二个赋值声明会被留在原地等待执行阶段。
  • 只有声明本身会被提升,而赋值或其他运行逻辑会留在原地。

变量声明和函数声明

  • 对于同名的变量声明,Javascript采用的是忽略原则,后声明的会被忽略,变量声明和赋值操作可以写在一起,但是只有声明会被提升,提升后变量的值默认为undefined,结果是在赋值操作执行前变量的值必为undefined
  • 对于同名的函数声明,Javascript采用的是覆盖原则,先声明的会被覆盖,因为函数在声明时会指定函数的内容,所以同一作用域下一系列同名函数声明的最终结果是调用时函数的内容和最后一次函数声明相同
  • 对于同名的函数声明和变量声明,采用的是忽略原则,由于在提升时函数声明会提升到变量声明之前,变量声明一定会被忽略,所以结果是函数声明有效

3.let/const

let 跟 var 的作用差不多,但有着非常重要的区别。最明显的区别是, let 声明的范围是块级作用域,而 var 声明的范围是函数作用域

块级作用域由最近的一对包含花括号{} 界定。换句话说, if 块、while 块、function块,甚至连单独的块也是let 声明变量的作用域

  • let 与 var 的另一个重要的区别,就是let 声明的变量不会在作用域中被提升。在let 声明之前的执行瞬间被称为”暂时性死区“(DZ,temporal dead zone),在此阶段引用任何后面才声明的变量都会抛出ReferenceError
  • 与 var 关键字不同,使用 let 在全局作用域中声明的变量不会成为 window 对象的属性( var 声明的变量则会)
  • var 来多次声明变量名,而用 let 却只能声明一次
  • 在 let 出现之前, for 循环中使用 var 定义的迭代变量会渗透到循环外

const 的行为与 let 基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且尝试修改 const 声明的变量会导致运行时错误。
const 声明的限制只适用于它指向的变量的引用。换句话说,如果 const 变量引用的是一个对象,那么修改这个对象内部的属性并不违反 const 的限制。

暂时性死区:在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为 “暂时性死区”( temporal dead zone,简称 TDZ

image.png

参考自JS高程4