资讯专栏INFORMATION COLUMN

ES6之"let"能替代"var"吗?

lewinlee / 835人阅读

摘要:我们将循环执行五次,每次将一个函数到数组中。只有当你理解了,才能给出正确的答案。读者提到的两个问题声明的变量不是完全不可更改。不仅如此,而且有些最新的浏览器也还没有支持。

译者按: 使用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的JavaScript技术交流群: 622902485

版权声明:
转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/201...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82923.html

相关文章

  • 用原生js写一个&quot;多动症&quot;的简历

    摘要:用原生写一个多动症的简历预览地址源码地址最近在知乎上看到方应杭用写了一个会动的简历,觉得挺好玩的,研究一下其实现思路,决定试试用原生来实现。 用原生js写一个多动症的简历 预览地址源码地址 最近在知乎上看到@方应杭用vue写了一个会动的简历,觉得挺好玩的,研究一下其实现思路,决定试试用原生js来实现。 showImg(https://segmentfault.com/img/remot...

    Y3G 评论0 收藏0
  • 汇总有关JS对象的创建与继承

      之前也有和大家讲过有关JS的对象创建和对象继承,本篇文章主要为大家做个汇总和梳理。  JS中其实就是原型链继承和构造函数继承的毛病,还有就是工厂、构造、原型设计模式与JS继承。 JS高级程序设计4:class继承的重点,不只是简简单单的语法而已。  对象创建  不难发现,每一篇都离不开工厂、构造、原型这3种设计模式中的至少其一!  那JS为什么非要用到这种3种设计模式了呢??  我们先从对...

    3403771864 评论0 收藏0
  • 解析ES6变量赋值和基本数据类型

      let和const  let和const两者并不存在变量提升  这里要说明的是变量一定要在声明后使用,否则报错。  vara=[];   for(vari=0;i<10;i++){   a[i]=function(){   console.log(i);   };   }   a[6]();//10  变量i是var声明的,我们要知道这里在全局范围内都有效。我们要知道在每一次循环中,新的...

    3403771864 评论0 收藏0
  • JavaScript进阶函数和对象知识点详解

      在过往学习的JavaScript都是在基础,现在为大家介绍更为深入的JavaScript知识。  JavaScript函数  JavaScript函数和Java函数是有一部分相似的,所以学习起来也会相对简单  基本构造  1.直接构造  //function代表函数标志,name为函数名称,参数可有可无   functionname(参数){   //...   return;   }  2....

    3403771864 评论0 收藏0

发表评论

0条评论

lewinlee

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<