深入理解es6块级作用域的使用

一.var 声明与变量提升机制

在JavaScript中使用var定义一个变量,无论是定义在全局作用域函数函数的局部作用域中,都会被提升到其作用域的顶部,这也是JavaScript定义变量的一个令人困惑的地方。由于es5没有像其它类C语言一样的块级作用域,因此es6增加了let定义变量,用来创建块级作用域。

我们来看一个var定义变量的示例:

function setName(){ if(condition){ var name = 'loho'; console.log(name); }else{ console.log(name); } } var student = 'eveningwater'; setName();

以上代码可以理解成如下:

var student; function setName(){ var name; if(condition){ name = 'loho'; console.log(name);//loho }else{ console.log(name);//undefined } } student = 'eveningwater'; setName();

二.块级声明

块级声明意在指定一个块级作用域,使得块级作用域中所定义的变量无法再全局被访问到,块级作用域也被称为词法作用域。

块级作用域存在于两个地方:

函数内部。

指定代码块中。(即"{"和"}"之间的区域)

1.let 声明

let声明同var声明用法一致,唯一的区别在于,let声明将变量限制在一个块内,这样就形成了一个块级作用域,因此也就不会存在变量的提升了。

例如前面的示例,我们可以写成如下:

let stundent = 'eveningwater'; function setName(){ if(condition){ let name = 'loho'; console.log(name);//loho }else{ //如果条件为false执行到这里 console.log(name);//不返回值 } } setName();

2.禁止重声明

在使用let定义变量之前如果已经声明了相同的变量,就会报错。因此不能重复声明变量。如以下示例:

var name = 'eveningwater'; //报错,重复声明 let name = 'loho';

当然这两个变量必须是在同一个作用域中,如果是不同作用域中,则不会报错。但有可能会遮蔽第一次声明的变量。如以下示例:

var name = 'eveningwater'; if(condition){ //不会报错 let name = 'loho'; }

3.const声明

使用const标识符所声明的变量必须要初始化,因此这个声明的就是一个常量。如下例:

const;//正确 const name;//错误,未初始化

const声明同let声明一样,也是创建了一个块级作用域,在这个块级作用域之外是无法访问到所声明的变量的。换句话说,就是const所声明的变量不会有变量提升机制。如下例:

if(condition){ const name = 'eveningwater'; console.log(name);//'eveningwater' } //错误 console.log(name);

同样的const也不能重复声明,如下例:

var name = 'eveningwater'; //错误,不能重复声明 const name = 'loho';

但也可以在不同作用域中重复声明,如下例:

var name = 'eveningwater'; if(condition){ const name = 'loho'; console.log(name);//loho,屏蔽全局定义的变量 }

尽管const声明与let声明有太多相似的地方,但const声明也有一处与let声明不同,那就是const声明的变量不能被赋值,无论是在非严格模式下还是在严格模式下,都不能对const声明的变量进行赋值。如下例:

const name = 'eveningwater'; //错误 name = 'loho';

不过,如果定义的是一个对象,可以对对象的值进行修改,如下例:

const student = { name:'eveningwater' } student.name = 'loho';//没问题 //错误,相当于赋值修改对象 student = { name:'loho' }

4.临时死区

前面提到let和const声明的变量都不会提升到作用域的顶部,因此在使用这两个标识符声明之前访问会报错,即使是typeof操作符也会触发引用错误。如下例:

console.log(typeof name);//报错 const name = 'eveningwater';

由于第一行代码就报错了,因此后续的声明变量语句不会执行,此时就出现了JavaScript社区所谓的"临时死区"(temporal dead zone).虽然这里示例是const声明,但let声明也是一样的。

但如果在const或let声明的变量的作用域之外使用typeof操作符监测却不会报错,只不过会返回undefined。如下例:

console.log(typeof name);//undefined if(condition){ let name = 'eveningwater'; }

5.循环中的块级作用域绑定

我们在使用var声明变量的时候,总会遇到这样的情况,如下:

for(var i = 0;i < 100;i++){ //执行某些操作 } //这里也能访问到变量i console.log(i);//100

我们可以使用let声明将变量i限制在循环中,此时再在循环作用域之外访问变量i就会报错了,因为let声明已经为循环创建了一个块级作用域。如下:

for(let i = 0;i < 100;i++){ //执行某些操作 } //报错 console.log(i);

6.循环中的创建函数

在使用var声明变量的循环中,创建一个函数非常的困难,如下例:

var func = []; for(var i = 0;i < 5;i++){ func.push(function(){ console.log(i); }) } func.forEach(function(func){ func(); });

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/4a2f6a7ef2bbcbbdc5c0c18db2eb73cf.html