var 、let 和 const 是三个声明变量的关键字,可以用于保存任何类型的数据。每个变量的实质一个用于保存任意值的命名占位符。var 在 ECMAScript 的所有版本中都可以使用,而 const 和 let 只能在 ECMAScript 6 及更晚的版本中使用。
var 关键字:
let 声明:
const 声明:
1、var 定义变量,可以声明同名变量,可以不进行初始化。
可以用它保存任何类型的值,不初始化的情况下会保存一个特殊值 undefined 。
var message;
console.log(message); // undefined
var message = "Hello";
console.log(message); // hello
var message = "Hello";
var message = "Hi";
console.log(message); // hi
var message = 100; // 合法但不推荐
console.log(message); // 100
在函数内部:使用 var 定义一个变量,它会成为这个函数的局部变量,函数退出时会被销毁。
function test(){
var message = "Hi";
console.log(message); // hi
}
test();
console.log(message); // 出错
在函数内部:去掉之前的 var 操作符之后,message 就变成了全局变量只要调用一次函数test(),就回定义这个变量,并且可以在函数外部访问到。(不建议这样做,局部作用域中定义的全局变量很难维护,容易造成困惑;所以严格模式下会直接抛出 ReferenceError )
function test() {
message = "Hi";
console.log(message); // hi
}
// console.log(message); // 出错
test();
console.log(message); // hi
function test() {
console.log(message); // undefined
var message = "Hi";
console.log(message); // hi
}
test();
上面的代码因为 var 的声明提升在代码运行时可看做等价于如下代码:
function test() {
var message;
console.log(message); // undefined
message = "Hi";
console.log(message); // hi
}
test();
var message = "hi";
console.log(window.message); // hi
var 关键字声明的 for 循环的迭代变量会渗透到循环体的外部,退出循环时迭代变量保存的是导致循环退出的值:5,随后才执行异步函数。
for (var i = 0; i < 5; ++i) {
// 循环逻辑
}
console.log(i); // 5
for (var a = 0; a < 5; ++a) {
setTimeout(() => console.log(a), 0);
}
// 你可能会以为会输出0、1、2、3、4
// 实际上是 5、5、5、5、5
不初始化的情况下保存一个特殊值 undefined
let a;
console.log(a); // undefined
let a = 6;
a = "12";
console.log(a); // 12
if (true) {
var message = "hi";
console.log(message); // hi
}
console.log(message); // hi
if (true) {
let name = "哈哈";
console.log(name); // 哈哈
}
console.log(name); // 未定义
var name;
var name;
let message;
let message; // SyntaxError message 已经声明过了
console.log(message); // ReferenceError 未定义
let message = "hi";
let message = "hi";
console.log(window.message); // undefined
let 声明的 for 循环的迭代变量时,JS引擎后台会为每个迭代循环声明一个新的迭代变量保存,随后执行异步函数时,引用的都是不同的变量实例。
for (let a = 0; a < 5; ++a) {
// 循环逻辑
setTimeout(() => console.log(a), 0);
}
// 输出0、1、2、3、4
for (let i = 0; i < 5; ++i) {
// 循环逻辑
}
console.log(i); // ReferenceError: i is not defined
const a; // SyntaxError
不能改变栈里面的数据,堆里面的数据可改变;(例如数字不可变,对象的属性等可变)
const obj = { name: "哈哈" };
obj.name = "张三";
console.log(obj); // {name:"张三"}
const a = 1;
a = 2; // 报错
const name = "嘻嘻";
if (true) {
const name = "哈哈";
console.log(name); // 哈哈
}
console.log(name); // 嘻嘻
const name = "嘻嘻";
const name = "哈哈"; //报错
const message = "hi";
console.log(window.message); // undefined
因为const 定义好之后“不能改变”,所以const 在 for 循环中只能声明一个不会被修改的 for 循环变量,这对 for-of 和 for-in 很有意义:
let i = 0;
for (const j = 7; i < 5; ++i) {
console.log(j); // 7,7,7,7,7
}
for (const key in { a: 1, b: 2 }) {
console.log(key); // a,b
}
for (const value of [1, 2, 3]) {
console.log(value); // 1,2,3
}
for (const value in [1, 2, 3]) {
console.log(value); // 0,1,2
}
通过了解 var、let、const 的特点,
1、尽量不使用 var 。限制自己只使用 let 和 const ,因为有了明确的作用域、声明位置,和不变的值,有助于提高代码质量。
2、const 优先,let 次之。const 声明可以让浏览器运行时强制保持变量不变,也可以让代码分析工具提前发现不合法的操作,避免意外发生。只在有意识修改变量时使用 let 。
如有不同见解,欢迎讨论,更多内容,正在更新中。。。。。。