引用:
- 变量的本质:变量可以看作是内存空间的引用,它代表了一个存储在内存中的数据值。每个变量都关联一个特定的内存位置,这个位置存储了变量的值。
- 定义变量的本质:定义变量实际上是告诉计算机在内存中为该变量分配一定的空间。
- 给变量赋值的本质:赋值操作是将某个数据值存入该变量关联的内存空间中。之后,每当我们引用这个变量,计算机就会访问这块内存空间并读取其中的值。
- 若一个空间没有变量指向它,那么这块空间将被 JS 视作垃圾,会被自动回收
- 变量可以在声明的时候同时完成赋值操作(语法糖)
- 使用 var 关键字声明的变量的值是可变的,变量可以被重新赋值,新的值会覆盖原来的值
- 任何可以书写数据的地方,都可以书写变量
- 若使用一个未声明(不存在)的变量,会导致错误。特殊情况:使用
typeof
检测变量的数据类型时,可以是未声明的变量,得到的结果是"undefined"
- JS 中存在变量提升,所有变量的声明,会自动的提到代码的最顶部
- 变量提升不会超越脚本块
“变量”是什么
变量是对“值”的具名引用。变量就是为“值”起名,然后引用这个名字,就等同于引用这个值。变量的名字就是变量名。
var a = 1;
上面的代码先声明变量a
,然后在变量a
与数值1之间建立引用关系,称为将数值1“赋值”给变量a
。以后,引用变量名a
就会得到数值1。最前面的var
,是变量声明命令。它表示通知解释引擎,要创建一个变量a
。
注意,js 的变量名区分大小写,**A**
和**a**
是两个不同的变量。
变量的声明和赋值,是分开的两个步骤,上面的代码将它们合在了一起,实际的步骤是下面这样。
// var a = 1;
var a;
a = 1;
如果只是声明变量而没有赋值,则该变量的值是**undefined**
。undefined
是一个特殊的值,表示“无定义”。
var a;
a // undefined
如果变量赋值的时候,忘了写var
命令,这条语句也是有效的。
var a = 1;
// 基本等同
a = 1;
但是,不写var
的做法,不利于表达意图,而且容易不知不觉地创建全局变量,所以建议总是使用var
命令声明变量。
如果一个变量没有声明就直接使用,js 会报错,告诉你变量未定义。
x
// ReferenceError: x is not defined
上面代码直接使用变量x
,系统就报错,告诉你变量x
没有声明。
可以在同一条**var**
命令中声明多个变量。
var a, b;
// 多个变量之间用逗号分隔
var a, b, c, d;
JavaScript 是一种动态类型语言,也就是说,变量的类型没有限制,变量可以随时更改类型。
var a = 1; // a 存放的值是一个数字类型
a = 'hello'; // 修改变量 a 的值,改为一个字符串类型
上面代码中,变量a
起先被赋值为一个数值,后来又被重新赋值为一个字符串。第二次赋值的时候,因为变量a
已经存在,所以不需要使用var
命令。
如果使用var
重新声明一个已经存在的变量,是无效的。
var x = 1;
var x; // 该语句相当于不存在
x // 1
上面代码中,变量x
声明了两次,第二次声明是无效的。
但是,如果第二次声明的时候还进行了赋值,则会覆盖掉前面的值。
var x = 1;
var x = 2; // 本次声明时进行了赋值操作(声明的同时进行初始化操作),那么赋的值会覆盖先前的值
// 等同于
var x = 1;
var x; // 相当于不存在
x = 2;
变量提升
js 引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升(hoisting)。
console.log(a); // => undefined
var a = 1;
上面代码首先使用console.log
方法,在控制台(console)显示变量a
的值。这时变量a
还没有声明和赋值,所以这是一种错误的做法,但是实际上不会报错。因为存在变量提升,真正运行的是下面的代码。
var a;
console.log(a);
a = 1;
最后的结果是显示undefined
,表示变量a
已声明,但还未赋值。
var 已退出历史舞台
ES6 推出了两个新的用于定义变量的关键字 let、const,它们解决了 var 关键字在定义变量时的诸多“问题”。为了方便相关知识点的介绍,后续文档中依旧会使用 var 来声明变量,但是,在实际工作中,不推荐使用 var 来声明变量,应该使用 let、const。