zoukankan      html  css  js  c++  java
  • ES6之"let"能替代"var"吗?

    译者按: 使用let的确会比var安全很多。

    原文: Why You Shouldn’t Use ‘var’ Anymore

    译者: Fundebug

    为了保证可读性,本文采用意译而非直译。

    我已经使用ES2015(ES6)的语法编写JavaScript程序很久了,并且喜欢上它提供的新特性带来的优雅和简洁。我最习惯的就是不再使用var,而是let/const。我想当然的以为let仅仅是var的替代者,而事实上let还为我们提供了更加精细的作用域。

    我大多数时候使用的变量都是用const来声明,因为如果尝试对使用const声明的变量进行修改,将会报错。这可以避免不小心将一个不该修改的常量值修改。但是,我们还是需要可以声明可以被修改的变量,比如在循环里面的计数器,我们需要不断地对改变了加1。可是为什么我们使用let而不是var呢?

    最简单的答案就是let提供块作用域(block-scoping),这会比var提供的以函数为作用域有更加精细化的控制。为了便于理解,我来用一个经典的前端工程师面试的问题来描述两者的区别。

    问题: 在下面的例子中,请说出控制台的打印结果。

    var callbacks = [];
    (function() {
    for (var i = 0; i < 5; i++) {
    callbacks.push( function() { return i; } );
    }
    })();
    console.log(callbacks.map( function(cb) { return cb(); } ));

    我们将for循环执行五次,每次将一个函数push到callbacks数组中。最后callbacks数组里面的每一个函数的执行结果打印出来。
    一个新手工程师经过深思熟虑可能会回答[0, 1 , 2, 3, 4], 然而却掉入了JavaScript的”hoisting陷阱”。

    只有当你理解了hoisting, 才能给出正确的答案[5, 5, 5, 5, 5]

    var callbacks = [];
    (function() {
    var i;
    for (i = 0; i < 5; i++) {
    callbacks.push( function() { return i; } );
    }
    })();
    console.log(callbacks.map( function(cb) { return cb(); } ));

    注意上面的代码,JavaScript将变量提升到函数定义的顶部,经过整个for循环,callbacks里面存储的5个函数指向的同一个变量i的值已经是5。所以最终打印出来的值都为5。

    在以前要通过各种奇淫技巧来解决这个问题,并成功返回[0, 1, 2, 3, 4], 现在我们有了let,就可以很简单解决问题:

    var callbacks = [];
    (function() {
    for (let i = 0; i < 5; i++) {
    callbacks.push( function() { return i; } );
    }
    })();
    console.log(callbacks.map( function(cb) { return cb(); } ));

    因为let拥有块作用域,所以使用let声明的变量i不会被提升到函数顶部,i的作用域在for循环, 就会每次循环有独立的值。

    那我们是不是应该不要使用var了呢?如果你想要一个变量拥有函数作用域,var还是很有用的。

    读者提到的两个问题:

    • const声明的变量不是完全不可更改。比如:

      const myNotQuiteImmutableObject = {
      thisCanBeChanged: "not immutable"
      };
      myNotQuiteImmutableObject.thisCanBeChanged = "see I changed it.";

      但是,使用const声明可以阻止一些基本的更改,比如:

      const immutableString = "you can't change me";
      immutableString = "D'OH!"; // error

      如果你想要完全的不可更改,可以使用Facebook提供的Immutable库。

    • 老版本的浏览器不支持let。不仅如此,而且有些最新的浏览器也还没有支持let。我们可以使用Babel来避免这个问题,Babel允许你使用所有最新的JavaScript功能,然后将其翻译到甚至IE8都能支持的代码。

    关于Fundebug

    Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了7亿+错误事件,得到了Google、360、金山软件、百姓网等众多知名用户的认可。欢迎免费试用!

  • 相关阅读:
    LeetCode 515. 在每个树行中找最大值(Find Largest Value in Each Tree Row)
    LeetCode 114. 二叉树展开为链表(Flatten Binary Tree to Linked List)
    LeetCode 199. 二叉树的右视图(Binary Tree Right Side View)
    LeetCode 1022. 从根到叶的二进制数之和(Sum of Root To Leaf Binary Numbers)
    LeetCode 897. 递增顺序查找树(Increasing Order Search Tree)
    LeetCode 617. 合并二叉树(Merge Two Binary Trees)
    LeetCode 206. 反转链表(Reverse Linked List) 16
    LeetCode 104. 二叉树的最大深度(Maximum Depth of Binary Tree)
    LeetCode 110. 平衡二叉树(Balanced Binary Tree) 15
    LeetCode 108. 将有序数组转换为二叉搜索树(Convert Sorted Array to Binary Search Tree) 14
  • 原文地址:https://www.cnblogs.com/fundebug/p/6812842.html
Copyright © 2011-2022 走看看