ES6之块级作用域

一、前言

在ECMAScript6(以下简称ES6)之前,ECMAScript的作用域只有两种:

  1、  全局作用域;

  2、  函数作用域。

正是因为有这两种作用域,所以在JavaScript中出现一术语--“变量提升(hoisting)”。

如下:

function func(){
    console.log(test);
    var test = 1;
};
func();

在node环境执行上述代码,结果为:

之所以为’undefined’,原因就在于‘变量提升’,在进入func函数时,将所有通过var声明的变量置前并赋予undefined的值。

但,ES6的到来,为我们提供了‘块级作用域’。且‘块级作用域’并不影响var声明的变量。

What?‘块级作用域’又不影响var声明的变量?!!

是的,var声明的变量的性质和原来一样,还是具有‘变量提升’的特性。而‘块级作用域’通过新增命令let和const来体现。

下面,我们透过新增的let和const命令,协同感受下ES6的块级作用域。

注:由于let和const属于ES6,所以都必须使用严格模式,否则会报错。

如下:

let test;

在node环境下,执行代码:

二、let命令

什么是let呢?

let和var差不多,都是用来声明变量的。区别就在于:

  1、  let声明的变量只在所处于的块级有效;

  2、  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环境下,执行上述代码结果如下:

三、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
时间: 2024-12-29 10:00:38

ES6之块级作用域的相关文章

ES6标准入门 第二章:块级作用域 以及 let和const命令

一.块级作用域 1.为什么需要块级作用域? ES5中只有全局作用域和函数作用域,带来很多不合理的场景. (1)内层变量可能会覆盖外层变量: var tem = new Date(); function f(){ console.log(tmp); if(false) { var tmp = "hello world"; } } f(); //undefined 变量提升导致了外层的内层的tmp变量覆盖了外层的tmp变量. (2)用来计数的循环变量泄露为全局变量: var s = &qu

let和ES6块级作用域

es6中的块级作用域 之前在看360的培训课程时,知道了{...}是个块级作用域,错误的认为{...}中声明的函数变量都不会被外界访问到,在看了你不知道的JS之后,发现并不是这样的.在块级作用域中使用let声明的变量外界无法访问到. eg: var foo = true; if (foo) { let bar = foo * 2; bar = something( bar ); console.log( bar ); } c onsole.log( bar ); // ReferenceErro

ES6块级作用域及新变量声明(let)

很多语言中都有块级作用域,但JS没有,它使用var声明变量,以function来划分作用域,大括号"{}" 却限定不了var的作用域.用var声明的变量具有变量提升(declaration hoisting)的效果. ES6里增加了一个let,可以在{}, if, for里声明.用法同var,但作用域限定在块级,let声明的变量不存在变量提升. 示例1: 块级作用域 if function getVal(boo) {     if (boo) {         var val = '

ES6——块级作用域

前面的话 过去,javascript缺乏块级作用域,var声明时的声明提升.属性变量等行为让人困惑.ES6的新语法可以帮助我们更好地控制作用域.本文将详细介绍ES6新引入的块级作用域绑定机制.let和const声明机制及最佳实践 var声明 [变量提升] var声明会发生”变量提升“现象,即变量可以在声明之前使用,值为undefined function getValue(condition){ if(condition){ var value = 'blue'; return value; }

ES6里关于作用域的拓展:块级作用域

过去,javascript缺乏块级作用域,var声明时的声明提升.属性变量等行为让人困惑.ES6的新语法可以帮助我们更好地控制作用域. 一.var声明 1.变量提升:var声明会发生"变量提升"现象,即变量可以在声明之前使用,值为undefined function getValue(condition){ if(condition){ var value = 'blue'; return value; }else{ //此处可访问变量value,值为undefined return

ES6 之 let和const、块级作用域

let let 声明的变量只在其所在的代码块内有用 不存在变量提升 只要在会计作用域中存在let命令,它所声明的变量就绑定这个区域 不允许重复声明 ES6块级作用域 外层代码不受内存代码块的影响 ES6规定,在块级作用域之中,函数声明类似于let 允许在块级作用域内声明函数 函数声明会提升到所在块级作用域的头部 const const声明一个只读常量,一旦声明,常量的值就不能改变 只在声明所在的块级作用域内有效 const声明的常量与let命令相同,只在声明所在的块级作用域内有效 const不存

ES6入门一:块级作用域(let&amp;const)、spread展开、rest收集

let声明 const声明 块级作用域 spread/rest 一.let声明与块作用域 在ES6之前,JavaScript中的作用域基本单元就是function.现在有了let就可以创建任意块的声明,也被称为作用域块.这意味者只需要“{}”就可以创建一个作用域.不再像var声明变量那样总归属于包含函数或全局.例如: 1 var a = 2; 2 { 3 let a = 3 4 console.log(a); //3 5 } 6 console.log(a); //2 在相关的资料中看到有介绍,

从零开始学ES6 -第一节(简介,块级作用域,let和const)

以下内容参考阮一峰老师的文章:http://es6.ruanyifeng.com/#docs/intro 一. ECMAScrpt 6简介 了解ES6转换器(bable,traceur) 申明变量的方法:var,let,const,function,import,class二. let和const命令 let命令 <!-- 声明的变量仅在块级作用域内有效 --> { let a=1; } a //报错 for(let i=0;i<10;i++){ } console.log(i) //报

12.24 ES6浅谈--块级作用域,let

第一部分:ES6新增了块级作用域,let关键字用于声明变量,相较于var而言,let关键字不存在声明提前. 1.ES6真正的出现了块级作用域,使用双花括号括住并在其中用let声明变量,会存在暂时性死区,在作用域外面使用变量会报错. 2.在循环中,如for循环,let命令相较于var命令会更好,原因在于所声明的变量不会提前到全局.那么在循环结束以后再调用该变量将无法访问. 3.如果是使用var的for循环,如 var a = []; for (var i = 0; i < 10; i++) { a