前面的话

  尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用其他类型的作用域单元甚至可以实现维护起来更加优秀、简洁的代码,比如块作用域。随着ES6的推广,块作用域也将用得越来越广泛。本文是深入理解javascript作用域系列第四篇——块作用域

let

for (var i= 0; i<10; i++) {
console.log(i);
}

  上面这段是很熟悉的循环代码,通常是因为只想在for循环内部的上下文中使用变量i,但实际上i可以在全局作用域中访问,污染了整个作用域

for (var i= 0; i<10; i++) {
console.log(i);
}
console.log(i);//

  ES6改变了现状,引入了新的let关键字,提供了除var以外的另一种变量声明方式。let关键字可以将变量绑定到所在的任意作用域中(通常是{...}内部),实现块作用域

{
let i = 1;
};
console.log(i);//ReferenceError: i is not defined

  块级作用域实际上可以替代立即执行匿名函数(IIFE)

(function(){
var i = 1;
})();
console.log(i);//ReferenceError: i is not defined

  如果将文章最开始那段for循环的代码中变量i用let声明,将会避免作用域污染问题

for (let i= 0; i<10; i++) {
console.log(i);
}
console.log(i);////ReferenceError: i is not defined

  for循环头部的let不仅将i绑定到了for循环的块中,事实上它将其重新绑定到了循环的每一个迭代中,确保使用上一个循环迭代结束时的值重新进行赋值

//与上一段代码等价
{
let j;
for (j=0; j<10; j++) {
let i = j; //每个迭代重新绑定
console.log( i );
}
}

循环

  下面代码中,由于闭包只能取得包含函数中的任何变量的最后一个值,所以控制台输出5,而不是0

var a = [];
for(var i = 0; i < 5; i++){
a[i] = function(){
return i;
}
}
console.log(a[0]());//

  当然,可以通过函数传参,来保存每次循环的值

var a = [];
for(var i = 0; i < 5; i++){
a[i] = (function(j){
return function(){
return j;
}
})(i);
}
console.log(a[0]());//

  而使用let则更方便,由于let循环有一个重新赋值的过程,相当于保存了每一次循环时的值

var a = [];
for(let i = 0; i < 5; i++){
a[i] = function(){
return i;
}
}
console.log(a[0]());//

重复声明

  let不允许在相同作用域内,重复声明同一个变量

{
let a = 10;
var a = 1;//SyntaxError: Unexpected identifier
}
{
let a = 10;
let a = 1;//SyntaxError: Unexpected identifier
}

提升

  使用let进行的声明不会在块作用域中进行提升

{
console.log(i);//ReferenceError: i is not defined
let i = 1;
};

const

  除了let以外,ES6还引入了const,同样可以用来创建块作用域变量,但其值是固定的(常量)。之后任何试图修改值的操作都会引起错误

if (true) {
var a = 2;
const b = 3;
a = 3;
b = 4;// TypeError: Assignment to constant variable
}
console.log( a ); //
console.log( b ); // ReferenceError: b is not defined

  const声明的常量,也与let一样不可重复声明

const message = "Goodbye!";
const message = "Goodbye!";//SyntaxError: Identifier 'message' has already been declared

try

  try-catch语句的一个常见用途是创建块级作用域,其中声明的变量仅仅在catch内部有效

{
let a = 2;
console.log(a); //
}
console.log(a); //ReferenceError: a is not defined

  在ES6之前的环境中,可以使用try-catch语句达到上面代码的类似效果

try{
throw 2;
}catch(a){
console.log( a ); //
}
console.log( a ); //ReferenceError: a is not defined
//或者
try{
throw undefined;
}catch(a){
a = 2;
console.log( a ); //
}
console.log( a ); //ReferenceError: a is not defined

深入理解javascript作用域系列第四篇——块作用域的更多相关文章

  1. 深入理解javascript函数系列第四篇——ES6函数扩展

    × 目录 [1]参数默认值 [2]rest参数 [3]扩展运算符[4]箭头函数 前面的话 ES6标准关于函数扩展部分,主要涉及以下四个方面:参数默认值.rest参数.扩展运算符和箭头函数 参数默认值 ...

  2. 深入理解javascript作用域系列第四篇

    前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用其他类型的作用域单元甚至可以实现维护起来更加优秀.简洁的 ...

  3. 深入理解javascript函数系列第三篇——属性和方法

    × 目录 [1]属性 [2]方法 前面的话 函数是javascript中的特殊的对象,可以拥有属性和方法,就像普通的对象拥有属性和方法一样.甚至可以用Function()构造函数来创建新的函数对象.本 ...

  4. 深入理解javascript函数系列第三篇

    前面的话 函数是javascript中特殊的对象,可以拥有属性和方法,就像普通的对象拥有属性和方法一样.甚至可以用Function()构造函数来创建新的函数对象.本文是深入理解javascript函数 ...

  5. javascript面向对象系列第四篇——选项卡的实现

    前面的话 面向对象的应用并非只是读几本书那么容易,需要有大量的工程实践做基础才能真正理解并学会使用它.本文将用面向对象的技术来制作一个简单的选项卡 图示说明 由图示结果看到,这是一个非常简单的选项卡. ...

  6. javascript面向对象系列第四篇——OOP中的常见概念

    前面的话 面向对象描述了一种代码的组织结构形式——一种在软件中对真实世界中问题领域的建模方法.本文将从理论层面,介绍javascript面向对象程序程序(OOP)中一些常见的概念 对象 所谓对象,本质 ...

  7. 深入理解javascript对象系列第三篇——神秘的属性描述符

    × 目录 [1]类型 [2]方法 [3]详述[4]状态 前面的话 对于操作系统中的文件,我们可以驾轻就熟将其设置为只读.隐藏.系统文件或普通文件.于对象来说,属性描述符提供类似的功能,用来描述对象的值 ...

  8. javascript运动系列第四篇——抖动

    × 目录 [1]原理介绍 [2]代码实现 [3]实例应用 前面的话 在运动系列中,前面分别介绍了匀速运动.变速运动和曲线运动.下面介绍一种特殊的运动形式——抖动 原理介绍 抖动其实是往复运动的一种特殊 ...

  9. javascript动画系列第四篇——拖拽改变元素大小

    × 目录 [1]原理简介 [2]范围圈定 [3]大小改变[4]代码优化 前面的话 拖拽可以让元素移动,也可以改变元素大小.本文将详细介绍拖拽改变元素大小的效果实现 原理简介 拖拽让元素移动,是改变定位 ...

随机推荐

  1. 河南省第五届ACM程序设计大赛

    D:   遥 控 器 #include<cstdio> #include<cstring> #include<iostream> #include<algor ...

  2. 决策树 -- C4.5算法

    C4.5是另一个分类决策树算法,是基于ID3算法的改进,改进点如下: 1.分离信息   解释:数据集通过条件属性A的分离信息,其实和ID3中的熵:   2.信息增益率   解释:Gain(A)为获的A ...

  3. wrHDL编译中软核代码初始化及编译耗时长的问题

    问题的提出整个WR的ISE工程比较大,编译时间很长,导致开发效率低.通过分析发现,ISE在综合的时候大量的时间都花在了初始化DPRAM上.调研发现Xilinx提供了BMM文件和DATA2MEM工具,可 ...

  4. 2.使用JDK开发webService

    使用jdk开发webService需要注意:jdk版本必须1.6以及1.6以上! 以下webService的组成部分: server端和client端,通过服务器端(server)webService ...

  5. 改变html中鼠标形状

    要修改的属性是: style=”cursor:default” 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 pointer:是手型. crosshair:是十字 ...

  6. javascript event兼容性随笔

    一.前言 function ConvertEvent(e, element) { var event = e || window.event; var resultEvent = { event: e ...

  7. javascript position兼容性随笔

    一.Javascript源码 if (!window.jasen.core.Position) { window.jasen.core.Position = {}; } function Size(w ...

  8. 用nifi executescript 生成3小时间隔字符串

    import java.io from datetime import datetime from org.apache.commons.io import IOUtils from java.nio ...

  9. vc编译 zlib 1.2.8

    最近用到gzip关的算法,于是想起了zlib这个库,于是将其下载下来编译. 首先,在官网上下载源码包:http://zlib.net/zlib-1.2.8.tar.gz 解压之后,打开vc 命令工具: ...

  10. 介绍Oedis - Redis OH/RM

    作死造轮子 Oedis是近段时间为了解决日志型数据如何与Entity Framework的查询整合的问题写的一个Redis的OH /RM.虽然Redis出来蛮久了,各路高手也都提出了实践方案,但是或许 ...