ES6标准入门----总结一

1.let命令
下面的代码如果使用var,最后将输出10.

var a=[];
for(var i=0;i<10;i++){
   
	a[i]=function(){
   
		console.log(i);
	}
}
a[6](0);//10

上面的代码中,变量i是var声明的,在全局范围内都有效,所以全局只有一个变量i。每一次循环,变量i的值都会发生改变。而循环内被赋给数组a的函数内部的console.log(i)中的i指向全局的i。也就是说,所有数组a的成员中的i指向的都是同一个i,导致运行时输出的是最后一轮i的值,也就是10.
如果使用let,声明的变量仅在块级作用域中有效,最后将输出6.

var a=[];
for(let i=0;i<10;i++){
   
	a[i]=function(){
   
		console.log(i);
	};
}
a[6]();//6

上面的代码中,变量i是let声明的,当前的i只在本轮循环中有效。所以每一次循环的i其实都是一个新的变量,于是最后输出的是6.JS引擎内部会记住上一次循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
另外,for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

for(let i=0;i<3;i++){
   
	let i='abc';
	console.log(i);
}
//'abc'
//'abc'
//'abc'

正确运行以上代码将输出三次abc。这表明,函数内部的变量i与循环变量i不在同一个作用域,而是有各自单独的作用域。

2.块级作用域
ES5只有全局作用域和函数作用域,没有块级作用域,这导致很多场景不合理。
第一种场景,内层变量可能会覆盖外层变量。

var tmp=new Date();

function f(){
   
	console.log(tmp);
	if(false){
   
		var tmp='hello world';
	}
}

f();//undefined

以上代码的原意是,if代码块的外部使用外层的tmp变量,内部使用内层的tmp变量。但是,函数f执行后,输出的结果为undefined,原因在于变量提升导致内层的tmp变量覆盖了外层的tmp变量。
第二种场景,用来计数的循环变量泄漏为全局变量。

var s='hello';
for(var i=0;i<s.length;i++){
   
	console.log(s[i]);
}

console.log(i);//5

上面的代码中,变量i只用来控制循环,但循环结束后,它并没有消失,而是泄漏成了全局变量。

let实际上为JS新增了块级作用域。

function f1(){
   
	let n=5;
	if(true){
   
		let n=10;
	}
	console.log(n);//15
}

上面的函数有两个代码块,都声明了变量n,运行后输出5,这表示外层代码块不受内层代码块的影响。如果使用var定义变量n,最后输出的值就是10.

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

//情况一
if(true){
   
	function f(){
   }
}

//情况二
try{
   
	function f(){
   }
}catch(e){
   
	//...
}

上面两种函数声明在ES5中都是非法的。但是,浏览器没有遵守这个规定,为了兼容以前的旧代码,还是支持在块级作用域之中声明函数,因此上面两种情况实际上都能运行,并不会报错。
ES6引入了块级作用域,明确允许在块级作用域之中声明函数。ES6规定,在块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。

function f(){
   console.log('I am outside!');}

(function(){
   
	if(false){
   
		//重复声明一次函数f
		function f(){
   console.log('I am inside!');}
	}
	f();
})();

以上代码在ES5中运行会得到"I am inside!",因为在if内声明的函数f会被提升到函数头部,实际运行的代码如下。

//ES5环境
function f(){
   console.log('I am outside!');}

(function(){
   
	function f(){
   console.log('I am inside!');}
	if(false){
   }{
   }
	f();
}());

而在ES6中运行就完全不一样了,理论上会得到"I am outside!"。因为块级作用域中声明的函数类似于let,对作用域之外没有影响。但是,如果真的在ES6浏览器中运行上面的代码,是会报错的。
原来,如果改变了块级作用域内声明的函数的处理规则,显然会对旧代码产生很大影响。为了减轻因此产生的不兼容问题,ES6中规定,浏览器的实现可以不遵守上面的规定,而有自己的行为方式,具体如下:

允许在块级作用域中声明函数;
函数声明类似于var,即会提升到全局作用域的头部;
同时,函数声明还会提升到所在的块级作用域的头部。

注意:上面3条规则只对ES6的浏览器实现有效,其他环境的实现不用遵守,依旧将块级作用域的声明当做let处理即可。
根据这3条规则,在浏览器的ES6环境中,块级作用域内声明函数的行为类似于var声明变量。

//浏览器的ES6环境
function f(){
   console.log('I am outside!');}

(function (){
   
	if(false){
   
		//重复声明一次函数f
		function f(){
   console.log('I am inside!');}
	}
	f();
}());
//Uncaught TypeError:f is not a function

上面的代码在符合ES6的浏览器中都会报错,因为实际运行的是以下代码。

//浏览器的ES6环境
function f(){
   console.log
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值