在ECMAScript6(如下简称ES6)以前,ECMAScript的做用域只有两种:node
一、 全局做用域;闭包
二、 函数做用域。ide
正是由于有这两种做用域,因此在JavaScript中出现一术语--“变量提高(hoisting)”。函数
以下:spa
function func(){ console.log(test); var test = 1; }; func();
在node环境执行上述代码,结果为:3d
之因此为’undefined’,缘由就在于‘变量提高’,在进入func函数时,将全部经过var声明的变量置前并赋予undefined的值。code
但,ES6的到来,为咱们提供了‘块级做用域’。且‘块级做用域’并不影响var声明的变量。blog
What?‘块级做用域’又不影响var声明的变量?!!ip
是的,var声明的变量的性质和原来同样,仍是具备‘变量提高’的特性。而‘块级做用域’经过新增命令let和const来体现。作用域
下面,咱们透过新增的let和const命令,协同感觉下ES6的块级做用域。
注:因为let和const属于ES6,因此都必须使用严格模式,不然会报错。
以下:
let test;
在node环境下,执行代码:
2、let命令 |
什么是let呢?
let和var差很少,都是用来声明变量的。区别就在于:
一、 let声明的变量只在所处于的块级有效;
二、 let没有‘变量提高’的特性,而是‘暂时性死区(temporal dead zone)’特性。
下面将一一讲解。
1、let声明的变量只在块级有效。
以下:
'use strict'; function func(args){ if(true){ //let声明i let i = 6; //在if内打印i值 console.log('inside: ' + i); } //在if外,再次打印i值 console.log('outside: ' + i); }; func();
在node环境中执行上述代码,结果以下:
经过demo,咱们能够清楚的看见,在第二次(if外)打印i值时,是报错的。
这由于let声明的变量i是属于if内的块级做用域;而不是像var同样。
2、let没有‘变量提高’的特性,而却有‘暂时性死区(temporal dead zone)’的特性。
以下:
'use strict'; function func(){ //在let声明前,打印i console.log(i); let i; }; func();
在node环境下执行上述代码,结果以下:
在let声明变量前,使用该变量,它是会报错的,而不是像var那样会‘变量提高’。
其实说let没有‘变量提高’的特性,不太对。或者说它提高了,可是ES6规定了在let声明变量前不能使用该变量。
以下:
'use strict'; var test = 1; function func(){ //打印test的值 console.log(test); let test = 2; }; func();
在node环境下执行上述代码,结果以下:
若是let声明的变量没有变量提高,应该打印’1’(func函数外的test);而他却报错,说明它是提高了的,只是规定了不能在其声明以前使用而已。咱们称这特性叫“暂时性死区(temporal dead zone)”。且这一特性,仅对遵循‘块级做用域’的命令有效(let、const)。
关于let,最后再经过一个经典案例,体验下。
以下:
var arr = []; for(var i = 0; i < 2; i++){ arr[i] = function(){ console.log(i); }; }; arr[1]();
arr[1]()会输出2,缘由是var声明的变量会变量提高,且当执行arr[1]函数时,i取自于父函数的i,而此时i已经变为2了,因此就会打印2咯。
之前的经常使用作法是,利用闭包特性。以下:
var arr = []; for(var i = 0; i < 2; i++){ arr[i] = (function(i){ return function(){ console.log(i); }; }(i)); }; arr[1]();
又或者属性方式:
var arr = []; for(var i = 0; i < 2; i++){ (arr[i] = function self(){ console.log(self.x); }).x = i; }; arr[1]();
如今有了let,它声明的变量做用域为块级,因此,咱们也能够利用let来达到一样的效果。
以下:
'use strict'; var arr = []; for(let i = 0; i < 2; i++){ arr[i] = function(){ console.log(i); }; }; arr[1]();
在node环境下,执行上述代码结果以下:
3、const命令 |
const命令与let命令同样,声明的变量,其做用域都是块级。
因此const遵循的规则与let相差无二,只是,const是用来声明恒定变量的。
且,用const声明恒定变量,声明的同时就必须赋值,不然会报错。
以下:
'use strict'; function func(){ const PI; PI = 3.14; console.log(PI); }; func();
在node环境下,执行上述代码结果以下:
正确的方式为,声明就得赋值。
如:
const PI = 3.14