var、let、const的区别

197 阅读4分钟

varletconst 都是命名变量的关键字

表格中是结论

关键字变量提升块级作用域重复声明同名变量重新赋值
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、letconst 关键字不能重复声明同名变量,即使之前是用var声明的也会报错

var num = 10;
let num = 20;  // Uncaught SyntaxError: Identifier 'num' has already been declared 

3、letvar 在声明变量时,可以不用初始化

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 增加 letconst 从客观上为这门语言更精确地声明作用域和语义提供了更好的支持。行为怪异的 var 所造成的各种问题,已经让 JavaScript 社区为之苦恼了很多年。随着这两个新关键字的出现,新的有助于提升代码质量的最佳实践也逐渐显现。

1、不使用 var

有了 letconst,大多数开发者会发现自己不再需要 var 了。限制自己只使用 letconst 有助于提升代码质量,因为变量有了明确的作用域、声明位置,以及不变的值。

2、const 优先,let 次之

使用 const 声明可以让浏览器运行时强制保持变量不变,也可以让静态代码分析工具提前发现不 合法的赋值操作。因此,很多开发者认为应该优先使用 const 来声明变量,只在提前知道未来会有修改时,再使用 let。这样可以让开发者更有信心地推断某些变量的值永远不会变,同时也能迅速发现因意外赋值导致的非预期行为。