JavaScript中var、let、const浅析
基本使用
- 在ES5,声明变量采用的都是var关键字,从ES6开始,新增了let、const用于声明变量和常量
var关键字
- ES5中声明变量的一种方式
var name;
var age;
let关键词
- ES6中用于声明变量
- 不允许重复声明变量
let name;
let age;
const关键字
- ES6中用于初始化常量
- 保存的数据一旦被赋值,就不能被修改
- 如果赋值的是引用类型,那么可以通过引用找到对应的对象,修改对象的内容
- 不能重复声明
//const如果只声明未赋值:SyntaxError: Missing initializer in const declaration
const id = 9999;
const obj = {
name: 'byj',
age: 18,
};
//报错:TypeError: Assignment to constant variable.
obj = {
name: 'abc',
};
//引用数据类型是可以修改对象的内容
console.log(obj);//{ name: 'byj', age: 18 }
obj.name = 'abc';
console.log(obj); //{ name: 'abc', age: 18 }
作用域提升
作用域提升就要提到var和let、const之间的区别
- var声明变量存在作用域提升
- let声明变量,在声明之前访问就会报错
- let和const同理,不另外做对比
console.log(name);
var name = 'byj'; //undefined
console.log(naem);
let name = 'byj'; //ReferenceError: Cannot access 'name' before initialization
关于let有一个细节:
ECMA262对let和const的描述:这些变量会被创建在包含他们的词法环境被实例化时,但是是不可以访问它们的,直到词法绑定被求值。
可以理解为在执行上下文的词法环境创建出来的时候,变量事实上已经被创建了,只是这个变量是不能被访问的。let相对于var就是变量已经创建,但是不能被访问。
个人观点:var存在作用域提升,但是let和const没有进行作用域提升但是会在解析阶段被创建出来
window对象添加属性
通过var声明的变量,会被保存在window上面
var age = 18;
console.log(window);
//Window
GetParams: ƒ (func)
age: 18
alert: ƒ alert()
atob: ƒ atob()
······
使用let、const是不会给window上添加任何属性的。但是会保存到VariableMap中
块级作用域
var foo = 'foo';
// 这里是全局作用域
function bar() {
// 这里是bar的函数作用域
function baz() {
// 这里是baz的函数作用域
}
}
// 通过var声明不存在块级作用域
// 这就导致一个问题,外部变量竟然可以访问内部初始化的变量
{
var foo = 'foo';
}
console.log(foo);//foo
{
let foo = 'foo';
}
console.log(foo); // ReferenceError: foo is not defined
let是有块级作用域,在访问上是有一定限制
如果要访问作用域内容的变量,可以采用闭包
function bar() {
let foo = 'foo';
return function baz() {
console.log(foo);
};
}
const fn = bar();
fn(); //foo
注意:函数也有块级作用域,但是外面依然可以访问,因为引擎会对函数的声明进行特殊的处理,允许像var那样进行提升。
暂时性死区
表达的意思就是:使用let或const声明的变量,在声明之前变量是不可以访问的
console.log(name);
let name = 'byj';//ReferenceError: Cannot access 'name' before initialization
var、let和const选择
在任何情况下都不推荐使用var
- var所表现出来的特殊性:比如作用域提升、window全局对象、没有块级作用域等都是一些
历史遗留问题; - var其实是JavaScript在设计之初的一种语言缺陷;
- 完全可以使用let或const替代;
用let和const
- 推荐使用const,这样可以保证数据的安全性不会被随意的篡改,可读性高并且具备一定的性能优势;
- 只有当我们明确知道一个变量后续会需要被重新赋值时,这个时候再使用let;
- 这种在很多其他语言里面也都是一种约定俗成的规范,尽量我们也遵守这种规范;
nst替代;
用let和const
- 推荐使用const,这样可以保证数据的安全性不会被随意的篡改,可读性高并且具备一定的性能优势;
- 只有当我们明确知道一个变量后续会需要被重新赋值时,这个时候再使用let;
- 这种在很多其他语言里面也都是一种约定俗成的规范,尽量我们也遵守这种规范;