王晨旭的个人网站

变量

标识符的格式

无论是变量名、函数名、类名,还是其他,其本质都是一个名称,是一个标识符。

就想我们人的姓名一样(姓氏+名字),标识符也有一定的规则:

  • 只能由数字、字母、汉字、下划线(_)或美元符号($)
  • 不能由数字开头

但是并不是所有的标识符都可以用来作为变量名、函数名、类名等的。有一些标识符有特殊语义,被称为关键字(如if),还有一些,现在虽然没有特殊语义,但未来的版本中可能会有特殊语义,保留已做备用,被称为保留字(如char)。当然,有一些关键字或保留字,只会在特殊语境下,才会被解释器识别为关键字或保留字(如catch)。在一般编程中,不建议用关键字或保留字作为变量名、函数名、类名等。下面给出关键字及保留字一般表。

说明:部分关键字在低版本中仍然是保留字,甚至既不是关键字又不是保留字。具体请参考附录:关键字与保留字一览表

作用域

通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。 作用域的使用提高了程序逻辑的局部性,增强程序的可靠性,减少名字冲突。

例如:不在任何函数和块中的定义的变量,就是在全局作用域中变量,简称全局变量,整个程序中都能访问到。

ES 中有三种作用域:全局作用域(整个程序都能访问到)、函数作用域(每一个函数都构成一个函数作用域)、块作用域(每一个块都构成一个块作用域,ES6新增)。但并不是所有的语句都识别这三种作用域,例如 var 语句就识别全局作用域和函数作用域。

作用域的叠加

如果多个嵌套的作用域中拥有同名的变量,则在总是操作最小的作用域中的变量。

如果在全局作用域中声明了一个变量a, 又在函数作用域中声明了另一个同名的变量a,则在这个函数作用域操作的变量a将会是函数作用域的a,但退出函数作用域后,操作的是全局作用域中的a。例如:

var a = 1;
console.log(a); //输出 1
a = 2;
console.log(a); //输出 2
function demo() {
    var a = 7;
    console.log(a); //输出 7
    a = 8;
    console.log(a); //输出 8
}
demo();
console.log(a); //输出 2
a = 3
console.log(a); //输出 3

声明或定义提升

部分语句的声明或者定义,会提升到所属的最小作用域的顶部,称为声明提升或定义提升,比如下面要讲的 var 有声明提升。

用 var 声明变量

在上一节中我们讲解过,ECMAScript 中的变量是用 var 运算符加变量名定义的。例如:

var a;

当然,在声量变量时,可以同时为变量赋值(称谓初始化)。例如:

var a = 4;

相当于

var a;
a = 4;

也可以,用一个 var 声明多个变量。例如:

var a, b = 5, c = 6, d, e = 8;

相当于

var a;
var b = 5;
var c = 6;
var d;
var e = 8;

警告

var a = b = 1;

只是声明了一个变量a,相当于:

var a;
a = b = 1;

因为 var 在ES3以前的语法中定义,考虑到兼容,所以 var 只能识别全局作用域和函数作用域。此外,var 还存在这两种作用域中的声明提升。例如:

a = 5;
var a;
var b = a + 5;

实际上是:

var a;
var b;

a = 5;
b = a + 5;

如果在同一个作用域中,定义了多次同一个变量,则会自动合并。例如:

var a = 5;
var a = 7;

相当于:

var a;

a = 5;
a = 7;

在没有开启严格模式下,给未定义的变量赋值,未定义的变量将会被自动定义为全局变量。获取未定义的变量的值将会的到undefined

警告

现代的ECMAScript编程,普遍采用严格模式,在严格模式下,使用未定义的变量,将会报错。

es6 的 let 与 const

在原有的var的基础上,es6又引入了 定义变量的新的 let 语句。let 语句相对与 var 语句的区别:

  • let 支持全局作用域、函数作用域和块作用域三种作用域
  • let 不支持声明提升,也就是说,在声明前使用let声明的变量将会报错
  • let 不支持声明合并,也就是说在完全完全相同的作用域下,重复声明两次及以上同一个变量竟会报错

除了声明变量的 let, es6 还引入了声明常量的 const。除了不能二次赋值意外,const 几乎与let 相同,具体却别:

  • const 声明的常量必须进行初始化
  • const 声明的常量不能进行二次赋值。

注意

在完全相同的作用域下,同一个变量只能被 var、let、const 中的一个声明,否则会报错。

《ECMAScript 基础教程》
  • 附录1 关键字与保留字一览表
  • 附录2 进制转换
  • 附录3 原生API手册
  • 附录4 ECMAScript 运行时错误一览表
  • 附录5 部分提案
    • 附录5.1 do 表达式
    • 附录5.2 throw 表达式
    • 附录5.3 链判断运算符
    • 附录5.4 管道运算符
    • 附录5.5 数值分隔符
    • 附录5.6 BigInt 数据类型
  • * 参考链接