ES6之let声明的实现

4 篇文章 0 订阅
3 篇文章 0 订阅

在说到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的重要性。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值