JavaScript目前有三个关键字来声明变量,即var, let, const。 在ES6之前只有一种方法 var 来申明变量,ES6后新添了 let 和 const 声明变量。
Var (global and function scope):
- 全局作用域,会在window上添加属性
- 可以再次声明
- 可以重新赋值
- 在函数内定义时,作用域是函数内部,在函数外定义时,作用域为全局
- 在任何变量被执行前,会对var进行变量提升(hosting),初始值为
undefined
变量提升(hosting):意味着可以在定义一个变量在未声明前
// 全局作用域
var name = "John Doe";
function logName() {
console.log(name);
};
logName(); // John Doe
// Window {window: Window, self: Window, document: document, name: 'John Doe', location: Location, …}
// 在函数内定义时,作用域是函数内部
function logName() {
var name = "John Doe";
var id = 1;
console.log(name);
};
function logId() {
console.log(id);
}
logId(); // ReferenceError: id is not defined
// 在执行logId函数的时候,id没有在logId函数内定义
// 所以在全局变量中寻找id变量,也没有
// 所以是undefined
// 在函数外定义时,作用域为全局
var name = "John Doe";
if (true) {
var name = "Daniel Joan";
}
console.log(name); // Daniel Joan
// 当在{}大括号中定义var时
// name的值会被重写,指向"Daniel Joan"
// 变量提升
function logName() {
console.log(name);
var name = "John Doe";
};
logName();
// undefined
let (block scope) 和 const (block scope):
- 只有块级作用域,window无法访问
- 不可以再次声明
- 在变量声明之前,变量都是不可以访问的
- 不存在变量提升(解析阶段会被创建出来,但不能被访问)
二者的区别是:
需要重新分配变量的时候使用 let,例如:循环
不需要重新分配变量的时候使用 const,是constant(常数)的缩写 但是可以改变const对象的属性
let name = "John";
if(true){
let name = "Jane";
console.log(name);
}
console.log(name);
// Jane
// John
// 这两个name变量是不同的变量,因为有着不同的作用域
function fn() {
if(true){
let name = "Jane";
console.log(name);
}
console.log(name); // let是块级作用域,name在if代码块中定义
}
fn()
// Jane
// ReferenceError: name is not defined
let 和 const是块级作用域
{
const x = 2;
console.log(x); // 2
}
console.log(x); // ReferenceError: x is not defined
{
let x = 2;
console.log(x); // 2
}
console.log(x);
let和const皆不可以再次声明
let name = "John";
let name = "Jane";
// SyntaxError: Identifier 'name' has already been declared
let name = "John";
name = "Jane";
// let可以重新赋值
const name = "John";
const name = "Jane";
// SyntaxError: Identifier 'name' has already been declared
const name = "John";
name = "Jane"; // TypeError: Assignment to constant variable.
// const重新赋值不被允许
const不可以再次赋值,可以通过改变const对象的属性进行赋值
const fullName = {
firstName: "John",
lastName: "Doe"
}
fullName.firstName = "Ellen"
console.log(fullName) // { firstName: 'Ellen', lastName: 'Doe' }
- 实际开发如何选择
首先排除var在let和const之间做选择,建议优先使用const,尤其是在全局环境,不应该设置变量,只应设置常量。
在导入库(Libraries)的时候使用const
一个是const可以提醒阅读程序的人,这个变量不应该改变;另一个是const比较符合函数式编程思想,运算不改变值,只是新建值,而且这样也有利于将来的分布式运算;最后一个原因是 JavaScript 编译器会对const进行优化,所以多使用const,有利于提高程序的运行效率,也就是说let和const的本质区别,其实是编译器内部的处理不同.