let/const及块级作用域
本系列是在平时阅读、学习、实际项目中有关于es6中的新特性、用发的简单总结,目的是记录以备日后温习;本系列预计包含let/const、箭头函数、解构、常用新增方法、Symbol、Set&Map、Proxy、reflect、Class、Module、Iterator、Promise、Generator、async/await
let/const为我们带来了什么?
let
- 约束变量提升
(function foo() {
console.log(a);
let a = 1;
})(); // Uncaught ReferenceError: a is not defined总结下来就是一句: 在变量使用之前,必须先要声明,变量声明永远在使用之前。
- 带来了块级作用域

// es5
(function(){
if(false) {
var temp = 1;
}
console.log(temp); // undefined
})();</span><span style="color: #008000;">//</span><span style="color: #008000;"> es6</span>
(<span style="color: #0000ff;">function</span><span style="color: #000000;">(){
</span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">false</span><span style="color: #000000;">) {
let temp </span>= 1<span style="color: #000000;">;
}
console.log(temp); </span><span style="color: #008000;">//</span><span style="color: #008000;"> Uncaught ReferenceError: temp is not defined</span>
})();</pre>

从代码中我们可以很清晰看到es6的let的块级作用域,那么块级作用域有什么应用呢?举个例子:

var fnArr = [];
for(var i = 0; i < 5; i++) {
fnArr.push(function() {
console.log(i);
});
}
fnArr[0](); //
fnArr[1](); //
fnArr[2](); //
fnArr[3](); //
fnArr[4](); //
console.log(i); //
如果没有仔细分析,执行的结果是不是有些出乎意料呢? 是的,我们本意在for循环内部使用的变量i被泄露成了全局变量,而且在for循环的每一次循环,变量i并没有被重新声明,实际上数组fnArr中保存的每一个函数中引用的都是同一个变量i,所以才导致了现在的结果,那怎么让代码按照我们最初的想法运行呢?来看es5中常用的解法

var fnArr1 = [];
for(var i = 0; i < 5; i++) {
(function(j) {
fnArr1.push(function() {
console.log(j);
});
})(i)
}
fnArr1[0](); //
fnArr1[1](); //
fnArr1[2](); //
fnArr1[3](); //
fnArr1[4](); //
console.log(i); //
看起来是解决了,这里实际上用到了闭包的方法,fnArr1中每一项函数引用的j都是当前循环时i的一个副本,这样就解决了前面的问题,但是还有一个问题: 变量i仍然隐式得泄露到了全局

var fnArr1 = [];
for(let i = 0; i < 5; i++) {
fnArr1.push(function() {
console.log(i);
});
}
fnArr1[0](); //
fnArr1[1](); //
fnArr1[2](); //
fnArr1[3](); //
fnArr1[4](); //
console.log(i); // Uncaught ReferenceError: i is not defined
OK,问题解决了,仅仅是将’var‘替换成了let,这就是let带来的便利。
- 产生暂时性死区&禁止重复声明

// 什么是禁止重复声明呢? 先不给书面解释,来看一个es5中经常的写法
(function() {
var temp = 1;
var temp = 2;
var temp = function() {
return 1;
};
})();
上面这段代码执行没有任何问题,最终temp被赋值为一个函数

(function() {
let temp = 1;
var temp = 2; // Uncaught SyntaxError: Identifier 'temp' has already been declared
var temp = function() {
return 1;
};
})();
在第三行时就抛出了一个错误:temp已经被声明,是的,let声明过的变量,是不允许再次被声明的,再给几个例子巩固一下:

(function() {
var temp = 2;
var temp = function() {
return 1;
};
let temp = 1; // Uncaught SyntaxError: Identifier 'temp' has already been declared
})();(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() {
</span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">true</span><span style="color: #000000;">) {
let temp </span>= 1<span style="color: #000000;">;
</span><span style="color: #0000ff;">var</span> temp = 2; <span style="color: #008000;">//</span><span style="color: #008000;"> Uncaught SyntaxError: Identifier 'temp' has already been declared</span>
}
})();(function() {
if(true) {
let temp = 1;
function temp() { // Uncaught SyntaxError: Identifier 'temp' has already been declared
return 1;
}
}
})();
看出来了吗?只要是在let声明所在的作用域,就不允许再次声明同名变量(包括函数声明)
var foo = 1;
if(true) {
foo = 2; // Uncaught ReferenceError: foo is not defined
let foo;
}看到let的’霸道‘了吧?只要在let所在的作用域,同名的变量就会被let占有,不允许重复声明,同时也要遵守let的规则
- 全局变量不再作为window对象的属性
var foo = 1;
(function() {
bar = 2;
})();
window.foo; //
window.bar; //是的,es5中,全局变量(包括意外泄露的)都将自动被添加为window对象的属性
let foo = 1; window.foo; // undefined
一切尽在不言中。。。
const
- let所拥有的特性,const都有,同时const还有一条:const声明的变量必须进行初始化,并且不能再被重新赋值
const temp = 1;
temp = 2; // Uncaught TypeError: Assignment to constant variable.注意是不能被重新赋值,这样是比较准确的,其实const声明的变量是可以被修改的,当const声明的变量被初始化为复杂数据类型时,const声明的变量就是可变的,至于为什么,自己理解喽(变量标识符中保存的只是复杂数据类型内存地址而已。。。)
const temp = {};
temp.foo = 'aa'; // 这里没问题
temp = {foo: 'aa'}; // 这里就会抛出异常
for循环中的变量声明
前面在记录let块级作用域的时候,我们使用了一个for循环的例子,这里我们不妨试着解析一下for循环的执行过程

var fnArr = [];
for(var i = 0; i < 3; i++) {
fnArr.push(function() {
console.log(i);
});
}</span><span style="color: #008000;">//</span><span style="color: #008000;"> 伪代码</span>
<span style="color: #0000ff;">var</span><span style="color: #000000;"> fnArr;
fnArr </span>=<span style="color: #000000;"> [];
{
</span><span style="color: #0000ff;">var</span><span style="color: #000000;"> i;
i </span>= 0<span style="color: #000000;">; </span><span style="color: #0000ff;">if</span>(i < 3<span style="color: #000000;">) {
fnArr.push(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() {
console.log(i);
})
}
i</span>++<span style="color: #000000;">;
</span><span style="color: #0000ff;">if</span>(i < 3<span style="color: #000000;">) {
fnArr.push(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() {
console.log(i);
});
}
i</span>++<span style="color: #000000;">;
...
}</span></pre>
这里可惜清晰得看到所有的i都是一个i。。。那使用了let以后呢?

var fnArr = [];
for(let i = 0; i < 3; i++) {
fnArr.push(function() {
console.log(i);
});
}</span><span style="color: #008000;">//</span><span style="color: #008000;"> 伪代码</span>
<span style="color: #0000ff;">var</span><span style="color: #000000;"> fnArr;
fnArr </span>=<span style="color: #000000;"> [];
{
let i;
i </span>= 0<span style="color: #000000;">; </span><span style="color: #0000ff;">if</span>(i < 3<span style="color: #000000;">) {
let i </span>=<span style="color: #000000;"> i;
fnArr.push(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() {
console.log(i);
})
}
i</span>++<span style="color: #000000;">;
</span><span style="color: #0000ff;">if</span>(i < 3<span style="color: #000000;">) {
let i </span>=<span style="color: #000000;"> i;
fnArr.push(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() {
console.log(i);
});
}
i</span>++<span style="color: #000000;">;
...
}</span></pre>
是不是看出点名堂?其实我们完全可以这样理解,在每一次循环中都重新声明了i,并且被赋值为外层i的当前值。(注意啊,这里只是伪代码,便于理解,实际中let i = i是会抛出异常的)
转载来源:https://www.cnblogs.com/innooo/p/10438947.html
let/const及块级作用域的更多相关文章
- ES6的 let const 以及块级作用域
let声明变量 用法类似于var,但是所声明的变量只在let所在的代码块内有效. 1 . 在ES6环境下,let声明的变量不能在声明之前调用. 例: console.log(i); //会报错,这叫做 ...
- ES6系列之let/const及块级作用域
本系列是在平时阅读.学习.实际项目中有关于es6中的新特性.用发的简单总结,目的是记录以备日后温习:本系列预计包含let/const.箭头函数.解构.常用新增方法.Symbol.Set&Map ...
- ES6-let、const和块级作用域
1.介绍 总的来说,ES6是在ES2015的基础上改变了一些书写方式,开放了更多API,这样做的目的最终还是为了贴合实际开发的需要.如果说一门编程语言的诞生是天才的构思和实现,那它的发展无疑就是不断填 ...
- 开始学习es6(二) let 与 const 及 块级作用域
1.var JavaScript中,我们通常说的作用域是函数作用域,使用var声明的变量,无论是在代码的哪个地方声明的,都会提升到当前作用域的最顶部,这种行为叫做变量提升(Hoisting) cons ...
- ES6入门一:块级作用域(let&const)、spread展开、rest收集
let声明 const声明 块级作用域 spread/rest 一.let声明与块作用域 在ES6之前,JavaScript中的作用域基本单元就是function.现在有了let就可以创建任意块的声明 ...
- ES6 浅谈let与const 块级作用域之封闭空间(闭包)
ES6新增了 let const 命令,用来声明变量.它的用法类似于 var ,但是所声明的变量,只在 let const 命令所在的代码块内有效. var const 不允许重复声明 用处: 可 ...
- ES6 let const 声明变量 块级作用域
ES6 中除了使用 var 定义变量,还有let.const,定义变量. function getValue(condition){ console.log(typeof value2); // un ...
- 《浏览器工作原理与实践》<09>块级作用域:var缺陷以及为什么要引入let和const?
在前面我们已经讲解了 JavaScript 中变量提升的相关内容,正是由于 JavaScript 存在变量提升这种特性,从而导致了很多与直觉不符的代码,这也是 JavaScript 的一个重要设计缺陷 ...
- ES6标准入门 第二章:块级作用域 以及 let和const命令
一.块级作用域 1.为什么需要块级作用域? ES5中只有全局作用域和函数作用域,带来很多不合理的场景. (1)内层变量可能会覆盖外层变量: var tem = new Date(); function ...
随机推荐
- 第一个chrome extension
如今,chrome浏览器的使用如越来越流行,chrome extension往往能提供更多很丰富的功能.以前一直想了解这方面的东西,可是又担心很复杂.前段时间,在斗鱼看一个直播,想刷弹幕,但是每次自己 ...
- JavaScript高级笔记
# 今日内容: 1. JavaScript: 1. ECMAScript: 2. BOM: 3. DOM: 1. 事件 ...
- zTree根节点默认打开
1.在生成tree的json数据中,直接给出:open:true的属性; 2.treeObj.expandAll(true); 3.var zTree = $.fn.zTree.getZTreeObj ...
- Spark集成Kafka实时流计算Java案例
package com.test; import java.util.*; import org.apache.spark.SparkConf; import org.apache.spark.Tas ...
- nodejs http服务器简单搭建
var http = require('http') // 1. 创建 Server var server = http.createServer() // 2. 监听 request 请求事件,设置 ...
- 分布式锁的实现【基于ZooKeeper】
引言 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提 ...
- AOP技术介绍--(.Net平台AOP技术研究)
4.1.Net平台AOP技术概览 .Net平台与Java平台相比,由于它至今在服务端仍不具备与unix系统的兼容性,也不具备类似于Java平台下J2EE这样的企业级容器,使得.Net平台在大型的企业级 ...
- 00.斐波那契数列第n项
# 斐波那契数列第n项 # 1 1 2 3 5 8 def fib(n): if n <= 2: return 1 else: return fib(n-2)+fib(n-1) def fib2 ...
- 人脸对比微信小程序
https://cloud.tencent.com/document/product/867/17584 测试数据: 图片1: 图片2:
- 「THUPC 2017」机场 / Airport
https://loj.ac/problem/2403 题解 神仙题. 练习赛的时候想了个假建图. 正解太神仙了. 先把不合法情况判掉. 先对时间离散化,每个时间点开一个点. 然后把他们一次串起来,中 ...