JavaScript 变量与常量

本文最后更新于:2024年3月18日 凌晨

JavaScript 变量与常量

变量

  • var和let用于声明一个或多个变量。
  • 与代数一样,JavaScript 变量可用于存放值(比如 x=5)和表达式(比如 z=x+y)
  • 变量必须以字母开头。
  • 变量也能以 $ 和 _ 符号开头(不过我们不推荐这么做)
  • 变量名称对大小写敏感(y 和 Y 是不同的变量)

变量的作用域

块级作用域(Block Scope)

  • 使用 var 关键字声明的变量不具备块级作用域的特性,它在{}外依然能被访问到。
1
2
3
4
{
var x = 2;
}
// 这里可以使用 x 变量。
  • 在 ES6 之前,是没有块级作用域的概念的。
  • ES6 可以使用 let 关键字来实现块级作用域。
  • let 声明的变量只在 let 命令所在的代码块{}内有效,在{}之外不能访问。
1
2
3
4
{
let x = 2;
}
// 这里不能使用 x 变量。

循环作用域

  • 使用 var 关键字:
1
2
3
4
5
var i = 5;
for (var i = 0; i < 10; i++) {
// 一些代码...
}
// 这里输出 i 为 10
  • 使用let关键字:
1
2
3
4
5
let i = 5;
for (let i = 0; i < 10; i++) {
// 一些代码...
}
// 这里输出 i 为 5
  • 在第一个实例中,使用了 var 关键字,它声明的变量是全局的,包括循环体内与循环体外。
  • 在第二个实例中,使用 let 关键字,它声明的变量作用域只在循环体内,循环体外的变量不受影响。

函数作用域

  • 在函数体内使用 varlet 关键字声明的变量有点类似。
  • 它们的作用域都是 局部的:
1
2
3
4
5
6
7
8
9
// 使用 var
function myFunction() {
var carName = "Volvo"; // 局部作用域。
}

// 使用 let
function myFunction() {
let carName = "Volvo"; // 局部作用域。
}

全局作用域

  • 在函数体外或代码块外使用 varlet 关键字声明的变量也有点类似。
  • 它们的作用域都是 全局的:
1
2
3
4
5
// 使用 var
var x = 2; // 全局作用域。

// 使用 let
let x = 2; // 全局作用域。
  • 注意:变量声明时如果不使用 var 关键字,那么它就是一个全局变量,即便它在函数内定义。

HTML 代码中使用全局变量

  • 在 JavaScript 中,全局作用域是针对 JavaScript 环境。
  • 在 HTML 中,全局作用域是针对 window 对象。
  • 使用 var 关键字声明的全局作用域变量属于 window 对象:
1
2
var carName = "Volvo";
// 可以使用 window.carName 访问变量。
  • 使用 let 关键字声明的全局作用域变量不属于 window 对象:
1
2
let carName = "Volvo";
// 不能使用 window.carName 访问变量。

重新声明变量

  • 使用 var 关键字声明的变量在任何地方都可以修改:
  • 在块中重新声明变量也会重新声明块外的变量:
1
2
3
4
5
6
7
8
9
var x = 2;
// x 为 2
var x = 10;
// 这里输出 x 为 10
{
var x = 2;
// 这里输出 x 为 2
}
// 这里输出 x 为 2
  • let 关键字在不同作用域,或不同块级作用域中可以重新声明赋值。
  • 但是在相同的作用域或块级作用域中,不可以重新声明赋值。
1
2
3
4
5
6
7
let x = 2;       // 合法。
let x = 3; // 不合法。

{
let x = 4; // 合法。
let x = 5; // 不合法。
}
  • 在相同的作用域或块级作用域中,不能使用 let 关键字来重置 var 关键字声明的变量:
1
2
3
4
5
6
var x = 2;       // 合法。
let x = 3; // 不合法。
{
var x = 4; // 合法。
let x = 5 // 不合法。
}
  • 在相同的作用域或块级作用域中,不能使用 var 关键字来重置 let 关键字声明的变量:
1
2
3
4
5
6
let x = 2;       // 合法。
var x = 3; // 不合法。
{
let x = 4; // 合法。
var x = 5; // 不合法。
}

向未声明的 JavaScript 变量分配值

  • 如果您把值赋给尚未声明的变量,该变量将被自动作为 window 的一个属性。
  • 这条语句:
1
carname="Volvo";
  • 将声明 window 的一个属性 carname
  • 非严格模式下给未声明变量赋值创建的全局变量,是全局对象的可配置属性,可以删除。
1
2
3
4
5
6
7
8
9
10
11
12
13
var var1 = 1; // 不可配置全局属性。
var2 = 2; // 没有使用 var 声明,可配置全局属性。

console.log(this.var1); // 1
console.log(window.var1); // 1
console.log(window.var2); // 2

delete var1; // false 无法删除。
console.log(var1); //1

delete var2;
console.log(delete var2); // true
console.log(var2); // 已经删除报错变量未定义。

变量提升

  • 函数及变量的声明都将被提升到函数的最顶部。
  • 变量可以在使用后声明,也就是变量可以先使用再声明。
1
2
3
4
5
6
x = 5; // 变量 x 设置为 5

elem = document.getElementById("demo"); // 查找元素。
elem.innerHTML = x; // 在元素中显示 x

var x; // 声明 x
  • 要理解以上实例就需要理解hoisting(变量提升)
  • 变量提升:函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体的最顶部。

不提升变量的特殊情况

  • JavaScript 只有声明的变量会提升,初始化的不会。
1
2
3
4
5
6
var x = 5; // 初始化 x

elem = document.getElementById("demo"); // 查找元素。
elem.innerHTML = x + " " + y; // 显示 x 和 y

var y = 7; // 初始化 y
  • let 关键字定义的变量则不可以在使用后声明,也就是变量需要先声明再使用。
1
2
3
// 在这里不可以使用 carName 变量。

let carName;

常量

  • const 用于声明一个或多个常量,声明时必须进行初始化,且初始化后值不可再修改:
1
2
3
const PI = 3.141592653589793;
PI = 3.14; // 报错。
PI = PI + 10; // 报错。
  • const定义常量与使用let 定义的变量相似:
    • 二者都是块级作用域。
    • 都不能和它所在作用域内的其他变量或函数拥有相同的名称。
  • 两者还有以下两点区别:
    • const声明的常量必须初始化,而let声明的变量不用。
    • const 定义常量的值不能通过再赋值修改,也不能再次声明,而 let 定义的变量值可以修改。
1
2
3
4
5
6
7
var x = 10;
// 这里输出 x 为 10
{
const x = 2;
// 这里输出 x 为 2
}
// 这里输出 x 为 10
  • const 声明的常量必须初始化:
1
2
3
4
5
6
// 错误写法。
const PI;
PI = 3.14159265359;

// 正确写法。
const PI = 3.14159265359;
  • const 的本质: const 定义的变量并非常量,并非不可变,它定义了一个常量引用一个值。
  • 使用 const 定义的对象或者数组,其实是可变的,下面的代码并不会报错:
1
2
3
4
5
6
7
8
// 创建常量对象。
const car = {type:"Fiat", model:"500", color:"white"};

// 修改属性:
car.color = "red";

// 添加属性。
car.owner = "Johnson";
  • 但是我们不能对常量对象重新赋值:
1
2
const car = {type:"Fiat", model:"500", color:"white"};
car = {type:"Volvo", model:"EX60", color:"red"}; // 错误。
  • 以下实例修改常量数组:
1
2
3
4
5
6
7
8
// 创建常量数组。
const cars = ["Saab", "Volvo", "BMW"];

// 修改元素。
cars[0] = "Toyota";

// 添加元素。
cars.push("Audi");
  • 但是我们不能对常量数组重新赋值:
1
2
const cars = ["Saab", "Volvo", "BMW"];
cars = ["Toyota", "Volvo", "Audi"]; // 错误。