ES6新特性之var、let、const详解

一、ES6新特性之var、let、const详解

作用域控制着变量和参数的可见性和生命周期。
JS中作用域有:全局作用域、函数作用域。没有块级作用域的概念。ECMAScript 6(简称ES6)中新增了块级作用域。
块级作用域由 { } 包括,if语句和for语句里面的{ }也属于块作用域。

var、let、const

  1. var定义的变量在全局范围内都有效,没有块的概念,可以跨块访问,不能跨函数访问。
    let定义的变量只在块级作用域内有效,不能跨块访问,也不能跨函数访问。
    const声明只读常量,只在块级作用域内有效,且声明时必须初始化(即必须赋值),后期值不可变,否则报错。
//var 
var a=1;
if(true){
    
    
	var b=2;
	for(i=0;i<1;i++){
    
    
		console.log(a);
		console.log(b);
	}
} 
var c=function(){
    
    
	var d=3;
}();
var e=function(){
    
    
console.log(d);//Uncaught ReferenceError: d is not defined
}();

//let
{
    
    
	let i1=1;
	console.log(i1);
	{
    
    
		let i2=1;
	}
	{
    
    
		console.log(i2);//Uncaught ReferenceError: i2 is not defined
		var fun1=function(){
    
    
			let i3=3;
		}();
		var fun2=function(){
    
    
			console.log(i3);//Uncaught ReferenceError: i3 is not defined
		}();
	}
}

2.var有变量提升, let、const都无变量提升

//若在定义一个变量之前使用该变量则会抛出ReferenceError错误,而var则会将变量视为undefined
console.log(p);//Uncaught ReferenceError: p is not defined
p=3;//Uncaught ReferenceError: Cannot access 'p' before initialization
let p;

console.log(r);//Uncaught ReferenceError: r is not defined
r=2;//Uncaught TypeError: Assignment to constant variable.
const r=1;

//下面看var 的变量提升
//例1:
console.log(q);//undefined (var声明的变量有变量提升,在js的预处理阶段,将var q;声明提升到最前面,此时暂时还未赋值,所以打印出来的结果为undefined )
var q=2;

//例2:
s=1;
console.log(s);
var s=2;
  1. var可重复声明同一变量,let、const都不可重复声明同一变量
var c=2;
var c=3;
console.log(c);//3

let b;
let b;//Uncaught SyntaxError: Identifier 'b' has already been declared

const a=1;
const a=1;//Uncaught SyntaxError: Identifier 'a' has already been declared
  1. 对于复合类型的变量,变量名不指向数据,而是指向数据所在的地址。const命令只是保证变量名指向的地址不变,并不保证该地址的数据不变
const a=[];
a.push('javascript');
console.log(a);//['javascript']
a=['java'];//Uncaught TypeError: Assignment to constant variable.

补充一、块级作用域

ES6的 let命令和const命令引入了的块级作用域的概念,块级作用域的优点:

  1. 避免内层变量覆盖外层变量
  2. 避免用来计数的循环变量泄露为全局变量
  3. 允许在块级作用域之中声明函数

ES5规定,函数只能在顶层作用域和函数作用域之外声明,不能在块级作用域中声明

if(true){
    
    
function func(){
    
    }
}
try{
    
    
function func(){
    
    }
}catch{
    
    
}
//上面两种函数声明在es5中都是非法的,但是浏览器没有遵守这一规定,还是支持在块级作用域中声明函数,因此以上两种情况实际都能运行,不会报错;但是在严格模式下,还是会报错;
'use strict'
if(true){
    
    
function func(){
    
    }//报错
} 

//ES6引入了块级作用域,明确允许在块级作用域中声明函数
'use strict'
if(true){
    
    
function func(){
    
    }//不报错
} 
//ES6还规定,在块级作用域中,函数声明的行为类似于let,在块级作用域之外不可引用;
//函数声明会提升到函数作用域头部;

//注意ES6的块级作用域允许函数只在使用大括号的情况下成立,如果未使用大括号,会报错
'use strict'
if(true){
    
    
function func1(){
    
    }//不报错
}
if(true)
function func2(){
    
    }//不报错
  1. ES6允许块级作用域的任意嵌套,外层作用域无法读取内层作用域的变量
{
    
    {
    
    {
    
    {
    
    {
    
    
{
    
    let i=1;}
console.log(i);//Uncaught ReferenceError: i is not defined
}}}}}
  1. 内层作用域可以定义外层作用域的同名变量,而不受影响
  2. 使立即执行函数不再需要,精简代码(直接用块级作用域{}代替)
//立即执行函数
(function(){
    
    
    var i=5;
})();
//块级作用域
{
    
    
let i=5;
}

补充二、JavaScript为什么对没有声明的变量赋值不会报错?

1.L/R查询

L就是左侧,R就是右侧。
来看var a = 2,js引擎会对a进行LHS(赋值操作的左侧)。另一个就是RHS(赋值操作右侧)

RHS查询就是简单的查找某个变量的值,找到还好,找不到就抛出异常
LHS查询则是试图找到变量的容器本身,从而可以对其进行赋值,找不到就会隐式的把它创建在全局作用域。

2.对于var a = 2,JavaScript引擎会在其作用域中对其进行编译,在这个过程中,会被分成两个步骤

1.首先,var a 在其作用域中声明新变量,这会在最开始阶段,也就是代码执行前
2.接下来,a = 2会查询(LHS)变量a,对其赋值
LHS和RHS都会在当前作用域中开始找,直到全局作用域中,无论找没找到都会停止
不成功的RHS会抛出异常(ReferenceError)
不成功的LHS会自动隐式地创建一个 全局变量

猜你喜欢

转载自blog.csdn.net/Maybe_ss/article/details/115502340