var、let、const都是命名变量的关键字
表格中是结论
| 关键字 | 变量提升 | 块级作用域 | 重复声明同名变量 | 重新赋值 |
|---|---|---|---|---|
| var | √ | × | √ | √ |
| let | × | √ | × | √ |
| const | × | √ | × | × |
表格下面文字是对表格的解读。
一、var
1、 有变量提升
console.log(num); // undefined
var num = 10;
// 以上代码运行时,相当于下面的写法
var num; // 声明提升到作用域最顶端
console.log(num); // undefined
num = 10;
2、作用域
ps:一对大括号 就是 一个块级作用域
1)、 没有块级作用域
for (var i = 0; i < 5; i++) { }
console.log(i); // 5
if (true) { var num1 = 10; }
console.log(num1); // 10
2)、有函数作用域
function fn() {
var num = 10; // 局部变量
}
console.log(num); // Uncaught ReferenceError: num is not defined
二、let 和 const
相同点
1、都没有变量提升,必须先声明后使用。
console.log(num1); // Uncaught ReferenceError: num1 is not defined
let num1 = 10;
console.log(num2); // Uncaught ReferenceError: num2 is not defined
const num2 = 10;
2、都有块级作用域和函数作用域
for (let i = 0; i < 5; i++) { }
console.log(i); // Uncaught ReferenceError: i is not defined
if (true) { const num3 = 10; }
console.log(num3); // Uncaught ReferenceError: num3 is not defined
if (true) { let num4 = 12; }
console.log(num4); // Uncaught ReferenceError: num4 is not defined
不同点
let 声明的变量可以重新赋值
let num = 10;
num = 20;
console.log(num); // 20
const 只能在声明时赋值,之后不能再重新赋值
const num = 10;
num = 20; // Uncaught TypeError: Assignment to constant variable.
三、补充
1、var 关键字可以声明同名变量,实际第二次声明是对第一次声明的变量重新赋值
var num = 10;
var num = 20;
console.log(num); // 20
2、let 和const 关键字不能重复声明同名变量,即使之前是用var声明的也会报错
var num = 10;
let num = 20; // Uncaught SyntaxError: Identifier 'num' has already been declared
3、let和var 在声明变量时,可以不用初始化
let num;
console.log(num); // undefined
var num1;
console.log(num1); // undefined
4、const 声明常量时必须初始化,因为 const 关键字声明的是常量,声明后不能再赋值
const num2; // Uncaught SyntaxError: Missing initializer in const declaration
5、基本数据类型 的常量和 引用类型类型 的常量说明
如果const 声明的常量中保存的是基本数据类型,是不能再修改的;
const str = 'hello';
str.name = 'world';
console.log(str.name); // undefined
如果const声明的常量中保存的是引用数据类型,不能重新给常量赋值,但可以操作引用数据类型中的成员
// 对象是引用数据类型
const obj = {
name: 'change'
}
obj.name = '强哥';
obj.age = 28;
console.log(obj); // {name: "强哥", age: 28}
obj = {
name: '小美'
} // Uncaught TypeError: Assignment to constant variable.
1、基本数据类型的值都有固定的大小,往往都保存在栈内存中(闭包除外),由系统自动分配存储空间,因此基本数据类型是原始值,原始值创建后不能修改
2、引用数据类型,比如数组 Array, object 等,它们值的大小是不固定的。引用数据类型的值是保存在堆内存中对象,变量和常量只是引用(保存)对象在堆中的内存地址,堆中的对象是可以修改的,但内存地址不变.
3、所以常量中保存的引用类型是可以修改它的成员,但不能重新更换引用。
四、总结
ECMAScript 6 增加 let 和 const 从客观上为这门语言更精确地声明作用域和语义提供了更好的支持。行为怪异的 var 所造成的各种问题,已经让 JavaScript 社区为之苦恼了很多年。随着这两个新关键字的出现,新的有助于提升代码质量的最佳实践也逐渐显现。
1、不使用 var
有了 let 和 const,大多数开发者会发现自己不再需要 var 了。限制自己只使用 let 和 const 有助于提升代码质量,因为变量有了明确的作用域、声明位置,以及不变的值。
2、const 优先,let 次之
使用 const 声明可以让浏览器运行时强制保持变量不变,也可以让静态代码分析工具提前发现不 合法的赋值操作。因此,很多开发者认为应该优先使用 const 来声明变量,只在提前知道未来会有修改时,再使用 let。这样可以让开发者更有信心地推断某些变量的值永远不会变,同时也能迅速发现因意外赋值导致的非预期行为。