zoukankan      html  css  js  c++  java
  • 闭包和let块级作用域

    还是先从一个题目开始:

    写一个隔1s输出数组的一项的函数。

    如果可以用ES6语法,则可以这么写:

    function print (arr) {
        for (let i = 0; i < arr.length; i++) {
            setTimeout(() => {
                console.log(arr[i])
            }, 1000 * i);
        }
    }
    

    但是如果把这里的let改成var,则输出就会变成一连串的undefined

    有同学很快想到了这是闭包啊,因为setTimeout把函数加入到microqueue中,所以等到setTimeout的函数体执行时,i已经走完了for循环,变成了arr.lengtharr[arr.length]显然是undefined。

    简单修改一下,变成ES5的语法。

    function print (arr) {
        for (var i = 0; i < arr.length; i++) {
            (function (index) {
                setTimeout(() => {
                    console.log(arr[index])
                }, 1000 * index);
            })(i);    
        }
    }
    

    其实就是利用闭包是向父级作用域寻找值的特性,给i包装一层作用域,把i存起来。

    闭包概念还请翻看之前的一篇blog-闭包和类

    到这里闭包的理解应该差不多了,而今天的关键点在于——

    let做了什么?

    阮一峰老师的《ECMAScript 6》入门里给出[定义](http://es6.ruanyifeng.com/#docs/let

    ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。

    他提到了let的几个特性:

    1. 只存在于块级作用域中

    2. 不存在变量提升

    3. 暂时性死区

    4. 不允许重复声明

    这里我不再赘述,大家可以仔细阅读一下阮一峰老师的书。

    我更感兴趣的是,在ES5的语法中,如何模拟let这种块级作用域的效果。这个时候,应该让babel出场了。

    打开这个链接:可以看到转换后的代码。

    "use strict";
    
    function print(arr) {
      var _loop = function _loop(i) {
        setTimeout(function () {
          console.log(arr[i]);
        }, 1000 * i);
      };
    
      for (var i = 0; i < arr.length; i++) {
        _loop(i);
      }
    }
    

    其实可以对比发现,babel转换后的代码和我们上面写的ES5实现其实是一样的。

    大概就是通过对let绑定的块级作用域加一个函数,把let声明的参数,通过函数传入,达到块级作用域的效果。

    大家可以在babel试一下let的其他特性,转移出的ES5语法并不能实现有的特性,比如暂时性死区。

    完,感谢阅读。

  • 相关阅读:
    VMware虚拟机安装红帽系统无法上网解决办法(转)
    二维指针的malloc内存分配(转)
    c语言中如何通过二级指针来操作二维数组
    如何把一个二维数组的地址赋给一个二维指针?
    二维数组及二维指针的传递及一些思考(转)
    js怎么让时间函数的秒数在页面上显示是变化的
    jquery 实现各种统计图网址
    WEB的相关知识总结
    JS同名方法,
    web components思想如何应用于实际项目
  • 原文地址:https://www.cnblogs.com/liuyongjia/p/10623665.html
Copyright © 2011-2022 走看看