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
ES6之块级作用域的更多相关文章
- ES6(块级作用域)
我们都知道在javascript里是没有块级作用域的,而ES6添加了块级作用域,块级作用域能带来什么好处呢?为什么会添加这个功能呢?那就得了解ES5没有块级作用域时出现了哪些问题. ES5在没有块级作 ...
- ES6 - Note1:块级作用域与常量
在ES6以前,ES不支持块级作用域,只有全局作用域和函数作用域,所有变量的声明都存在变量声明提升. 1.let 关键字 声明一个块级变量,只在一个代码块中有效,如果在块外面访问便会报错,如下所示: { ...
- ES6的 let const 以及块级作用域
let声明变量 用法类似于var,但是所声明的变量只在let所在的代码块内有效. 1 . 在ES6环境下,let声明的变量不能在声明之前调用. 例: console.log(i); //会报错,这叫做 ...
- ES6 块级作用域
作用域包括:全局作用域,函数作用域,块级作用域. 为什么要用块级作用域: 1.内层变量可能会覆盖外层变量. var name = "kevin"; function call() ...
- ES6标准入门 第二章:块级作用域 以及 let和const命令
一.块级作用域 1.为什么需要块级作用域? ES5中只有全局作用域和函数作用域,带来很多不合理的场景. (1)内层变量可能会覆盖外层变量: var tem = new Date(); function ...
- ECMAScript6 入门教程 初学记录let命令 块级作用域
一.基本语法-let命令 (1)ES6新增了let命令,用来声明变量.所声明的变量,只在let命令所在的代码块内有效. 循环的计数器,就很合适使用let命令.计数器i只在for循环体内有效,在循环体外 ...
- js中的块级作用域
概述 函数是js中最常见的作用域单元, 声明在一个函数内部的变量或函数会在所处的作用域中隐藏起来, 这是有意为之的非常好的设计原则. 但是随着js的发展, 我们有了某个代码块(通常指{..}内部)隐藏 ...
- ES6-let、const和块级作用域
1.介绍 总的来说,ES6是在ES2015的基础上改变了一些书写方式,开放了更多API,这样做的目的最终还是为了贴合实际开发的需要.如果说一门编程语言的诞生是天才的构思和实现,那它的发展无疑就是不断填 ...
- 从函数作用域和块级作用域看javascript的作用域链
在ES6之前,javascript只有全局作用域和函数作用域.所谓作用域就是一个变量定义并能够被访问到的范围.也就是说如果一个变量定义在全局(window)上,那么在任何地方都能访问到这个变量,如果这 ...
随机推荐
- 论:开发者信仰之“天下IT是一家“(Java .NET篇)
比尔盖茨公认的IT界领军人物,打造了辉煌一时的PC时代. 2008年,史蒂夫鲍尔默接替了盖茨的工作,成为微软公司的总裁. 2013年他与微软做了最后的道别. 2013年以后,我才真正看到了微软的变化. ...
- 01.SQLServer性能优化之----强大的文件组----分盘存储
汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 文章内容皆自己的理解,如有不足之处欢迎指正~谢谢 前天有学弟问逆天:“逆天,有没有一种方 ...
- SQLSERVER走起 APP隆重推出
SQLSERVER走起 APP隆重推出 为方便大家查看本微信公众以前推送的文章,QQ群里面的某位SQLSERVER重度爱好者开发了<SQLSERVER走起>的APP 以供大家一起交流 网页 ...
- Android数据存储之Android 6.0运行时权限下文件存储的思考
前言: 在我们做App开发的过程中基本上都会用到文件存储,所以文件存储对于我们来说是相当熟悉了,不过自从Android 6.0发布之后,基于运行时权限机制访问外置sdcard是需要动态申请权限,所以以 ...
- 调用微信退款接口或发红包接口时出现System.Security.Cryptography.CryptographicException: 出现了内部错误 解决办法
我总结了一下出现证书无法加载的原因有以下三个 1.证书密码不正确,微信证书密码就是商户号 解决办法:请检查证书密码是不是和商户号一致 2.IIS设置错误,未加载用户配置文件 解决办法:找到网站使用的应 ...
- 从阿里巴巴笔试题看Java加载顺序
一.阿里巴巴笔试题: public class T implements Cloneable { public static int k = 0; public static T t1 = new T ...
- mount报错: you must specify the filesystem type
在linux mount /dev/vdb 到 /home 分区时报错: # mount /dev/vdb /homemount: you must specify the filesystem ty ...
- 数塔问题(DP算法)自底向上计算最大值
Input 输入数据首先包括一个整数C,表示测试实例的个数,每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数 ...
- 用Java代码实现拦截区域网数据包
起因: 吃饭的时间在想如果区域网内都是通过路由器上网,那如何实现拦截整个区域网的数据包,从而实现某种窥探欲. 思路: 正常是通过电脑网卡预先设置或分配的IP+网关对路由器进行通讯,比如访问百 ...
- .NET面试题系列[3] - C# 基础知识(1)
1 类型基础 面试出现频率:基本上肯定出现 重要程度:10/10,身家性命般重要.通常这也是各种招聘工作的第一个要求,即“熟悉C#”的一部分.连这部分都不清楚的人,可以说根本不知道自己每天都在干什么. ...