ES6之let声明的实现

xiaoxiao2021-02-28  59

在说到let的实现方式之前,先看以下为什么会有let

let使用的较多的情况一般是循环事件中的闭包,例如: `use strict` var a = [] for(var i = 0;i<5;i++){ a[i] = function(){ console.log(i) } } for (var k of a){ k(); }

这是一道较为简单的题目,稍微懂点JS基础的都知道,这里console.log打印出来的是 5 个 5

那么要使打印出来的是我们想要的i 呢?如下: var a = [] for(let i = 0;i<5;i++){ a[i] = function(){ console.log(i) } } for (var k of a){ k(); }

使用let可以很轻松的达到这个效果

那为什么let可以很轻松的达到呢,如果不使用let那可以用什么别的方法吗?如下: `use strict` var a = [] for(var i = 0;i<5;i++){ _loop(i) } function _loop(i){ a[i] = function(){ console.log(i) } } for (var k of a){ k(); }

这是使用babel将上面let方法polyfill的版本,用以支持不支持ES6语法的浏览器。可以发现,是使用了一个函数将i的值存储下来达到块级作用域的目的。这样临时的变量i就得以保存下来。以下是几钟达到let效果的polyfill版本:

使用 try catch方法 `use strict` var a = [] for(var i = 0;i<5;i++){ try{ throw i }catch (e){ a[e] = function(){ console.log(e) } } } for (var k of a){ k(); } 使用自执行函数的方法 `use strict` var a = [] for(var i = 0;i<5;i++){ (function(i){ a[i] = function(){ console.log(i); } })(i) } for (var k of a){ k(); } 使用map函数 `use strict` var a = [] for(var i = 0;i<5;i++){ [i].map((value)=>{ a[value] = function(){ console.log(value) } }) } for (var k of a){ k(); }

可以发现,在这些方法里,除了try catch以外都是使用函数的作用域来保存i的值

以上的介绍都是在循环中使用的实例,那么在非循环中使用又是怎样的实现方法呢?我们来看一个经典的面试题: var name = 'World!'; (function () { if (typeof name === 'undefined') { var name = 'Jack'; console.log('Goodbye ' + name); }else{ console.log('Hello ' + name); } })()

答案是Goodbye Jack。首先JS引擎拿到这段代码会先进行变量提升,实际上的顺序应该是这样的

`use strict` var name; name = 'World!'; (function () { var name if (typeof name === 'undefined') { name = 'Jack'; console.log('Goodbye ' + name); }else{ console.log('Hello ' + name); } })();

外面的name实际上没有什么作用,主要是if里面的这个name。在某些编程语言里面,if实际上也是一个块级作用域,在块级作用域里面声明的变量,外面是不可以使用的。但是在JS里面,除了函数具备这个功能外再没有块级作用域了。所以在if里面声明的name会被提升到函数最顶部先行执行,然后判断name是不是undefined类型,因为没有赋值所以答案是true。所以name = Jack所以打印出Goodbye Jack。

那如果题目换成下面这样又是什么结果呢

`use strict` var name = 'World!'; (function () { if (typeof name === 'undefined') { let name = 'Jack'; console.log('Goodbye ' + name); }else{ console.log('Hello ' + name); } })()

因为使用的是let声明,没有变量提升。所以if判断里的name引用的是全局变量name,所以答案是Hello World

简单的polyfill版本

`use strict` var name = 'World!'; (function () { if (typeof name === 'undefined') { (function(){ var name = 'Jack'; console.log('Goodbye ' + name); })() }else{ console.log('Hello ' + name); } })()

可以看到,let的出现简化了大量的JS操作。特有的作用域弥补的JS块级作用域的短板。针对let的polyfill也多是使用函数的作用域来完成,由此可见函数对于JS的重要性。

转载请注明原文地址: https://www.6miu.com/read-2631136.html

最新回复(0)