文档章节

ES6之块级作用域

帅的人连bug都讨厌
 帅的人连bug都讨厌
发布于 2017/06/28 16:30
字数 1086
阅读 10
收藏 1

 

 

一、前言

在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

© 著作权归作者所有

帅的人连bug都讨厌
粉丝 3
博文 53
码字总数 40134
作品 0
杭州
程序员
私信 提问
ES6 let和const详解

前言 本人这是第一次写文章,记录一下平常在学习中的一些收获和感言,这些笔记如果存在错误的地方发情告知改正,不胜感激,本人文采不行,轻喷,谢谢。 1. let命令 作用域 ES6 新增了let命令...

九当家丶
2018/12/18
0
0
let和const命令

let命令 基本用法 ES6新增了命令,用来声明变量。它的用法类似于,但是所声明的变量,只在命令所在的代码块内有效。 { let a = 10; var b = 1;}a // ReferenceError: a is not defined.b // ...

易帝加盟热火了
2015/12/25
41
0
ECMAScript 6 let和const命令

自从nodejs升级到4.0后,已经开始支持ECMAScript 6了。。。 刚开始看阮一峰的ES6 入门教程,发现变量声明多了两个属性,let和const。相对于原来单一的var,变得越来越像java了,引入了块级作用...

mosaic101
2015/12/09
48
0
es6新特性---let const

想要学习更多,推荐看阮大神的http://es6.ruanyifeng.com/#docs/let 在学习之前得知道作用域 ES5 中作用域有:全局作用域、函数作用域。没有块作用域的概念。 ES6 中新增了块级作用域。块作用...

小丑鱼888
2018/08/01
0
0
《es6 标准入门》知识整理(1) - let 和 const

let 基本用法 es6 的 let 所声明的变量,只在 let 命令所在的代码块内有效。for循环的计数器,就很适合用let命令: 因为计数器 i 只在 for 循环体内有效,在循环体外引用就会报错。 for循环有...

IrisHuang
04/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

基础工具类

package com.atguigu.util;import java.sql.Connection;import java.sql.SQLException;import java.util.Properties;import javax.sql.DataSource;import com.alibaba.druid......

architect刘源源
今天
43
0
P30 Pro劲敌!DxO官宣新机:排行榜又要变

5月26日晚间,DxOMark官方推特预告,将在5月27日公布一款新机型的DxOMark评分,猜猜是哪款? 网友猜想的机型有:红米K20、谷歌Pixel 3a、索尼Xperia 1、诺基亚9 PureView等。 DxOMark即将公布...

linux-tao
昨天
15
0
Ubuntu18.04.2窗口过小不能自适应(二次转载)

解决Ubuntu在虚拟机窗口不能自适应 2018年09月06日 16:20:08 起不了名儿 阅读数 855 此博文转载:https://blog.csdn.net/nuddlle/article/details/77994080(原地址) 试了很多办法这个好用 ...

tahiti_aa
昨天
2
0
死磕 java同步系列之CountDownLatch源码解析

问题 (1)CountDownLatch是什么? (2)CountDownLatch具有哪些特性? (3)CountDownLatch通常运用在什么场景中? (4)CountDownLatch的初始次数是否可以调整? 简介 CountDownLatch,可以...

彤哥读源码
昨天
6
0
Nginx提供下载apk服务

有时候我们可能需要提供文件或者其他apk下载链接,通过 nginx 配置可以很简单地实现。 server {    listen 80;    server_name download.xxx.com;    root app;    locati...

Jack088
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部