概述
- ES5及以前版本的JavaScript采用var声明变量,且不支持块级作用域
- JavaScript中,变量实际创造的位置取决于如何声明该变量
- ES6新增了两个关键字 let 和 const用于控制作用域。
let命令
- 基本用法类似于var,但所声明的变量只在let命令所在的代码块有效
var count = 10;
let count = 20;
console.log(count); //报错
let声明的变量仅在其代码块有效
- 基本用法,for循环的计数器很适合使用let命令
for(var i = 0;i<10;i++){
console.log(i);//0-9
}
console.log(i);//10
for(let i = 0;i<10;i++){
console.log(i);//0-9
}
console.log(i);//没有显示值
var a=[];
for(var i = 0;i<10;i++){
a[i] = function(){
console.log(i);//10
}
}
a[6]();
将var改为let,结果如下:
var a=[];
for(let i = 0;i<10;i++){
a[i] = function(){
console.log(i);//6
}
}
a[6]();
for(let i = 0;i<3;i++){
let i = 'abc';
console.log(i);//abc abc abc
}
for循环在设置循环变量的部分是一个父作用域,循环体内部又是一个独立的子作用域。
- 变量提升
function getValue(c){
if(c){
var ;
value = 'blue';
return value;
}else{
return null;
}
}
function getValue(c){
var value;
if(c){
value = 'blue';
return value;
}else{
return null;
}
}
//JS引擎调整
var声明的变量无论其实际声明位置所在何处,都会被视为声明于所在函数的(或全局)的顶部,这就是变量提升
- 暂时性死区
var temp = 123;
if(true){
temp = 'abc';
let temp;
}
ES6明确规定,如果区块中存在let 和 const 命令,则这个区块对这些命令声明的变量从一开始就形成封闭作用域。在这个代码块内,使用let命令声明变量之前,该变量是不可用的,这个区域被称为暂时性死区。
- 不允许重复声明
function fn(){
let a = 10;
let a =1;
//报错
}
function fn(){
let a = 10;
var a = 1;
//报错
}
function fn(){
var a = 10;
let a = 1;
//报错
}
function fn(){
var a = 10;
var a = 1;
//没有报错
}
作用域
-
变量或者函数起作用的区域
-
全局作用域
-
浏览器的顶级对象为window,Node为global
(var定义的变量会关联到顶层对象,let和const不会) -
块作用域 由{}界定的代码块区域,let const 声明的变量具备可访问作用域 作用域链,从当前作用域向上查找
-
ES5:立即执行匿名函数(IIDE)来替代块作用域
const命令
- 声明一个只读的常量,一旦声明,其值不能改变且必须立即初始化
除此之外,与let用法一致。
// An highlighted block
const foo = {y:10};
foo.x = 100;
console.log(foo.x);
foo = {n:1000};//报错
当常量保存的不是一个值,而是一个地址的时候,该常量所引用的对象是可以更改成员的,只是不能更改该常量保存的地址。
顶层对象
- 浏览器的顶层对象为window,Node的为global。
- var定义的变量会关联到顶层对象中,let和const不会
小结
-
ES6一方面新增了let和const命令所声明的全局变量不属于顶层对象属性,另一方面也允许var和function命令声明的全局变量依旧是顶层对象的属性。
-
ES6为ES5提供了良好的兼容性
-
由于let和const能提供更好的作用域识别,建议尽量采用let声明变量,const声明常量。