译者按: 使用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、金山软件、百姓网等众多知名用户的认可。欢迎免费试用!

版权声明:
转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/05/04/why-you-should-not-use-var/

ES6之"let"能替代"var"吗?的更多相关文章

  1. [ES6系列-04]再也不乱“哇”了:用 let 与 const 替代 var

    [原创]码路工人 Coder-Power 大家好,这里是码路工人有力量,我是码路工人,你们是力量. github-pages 博客园cnblogs 今天的内容是,关于 JavaScript 中定义变量 ...

  2. ES6新增关键字let与var的区别

    最近看了很多文章,偶然间看到ES6中新增了一个关键字 let ,它具有与 var 关键字相似的功能.一开始使用它时,发现它让我对之前一些习以为常的东西产生了怀疑. 下面先让我们看看它和 var 之间用 ...

  3. ES6 新增声明变量的 var let const 的区别详解

    var 如果使用关键字 var 声明一个变量,那么这个变量就属于当前的函数作用域,如果声明是发生在任何函数外的顶层声明,那么这个变量就属于全局作用域. let 1.let 声明的变量具有块作用域的特征 ...

  4. li点击弹出序号

    <body> <ul> <li>test1</li> <li>test2</li> <li>test3</li ...

  5. JavaScript 再谈闭包

    之前有整理过一版关于闭包的概念,但感觉思路不是很清晰,是临时想起一些例子来讲的,今天再次来讲一下闭包. 闭包: 函数嵌套函数,内部函数可以引用外部函数的参数和变量 function aaa(a){ v ...

  6. 10个常见的JavaScript BUG

    译者按: 安全起见,在开发中我基本不用==. 原文: 10 COMMON JAVASCRIPT BUGS AND HOW TO AVOID THEM 译者: Fundebug 为了保证可读性,本文采用 ...

  7. JavaScript中8个常见的陷阱

    译者按: 漫漫编程路,总有一些坑让你泪流满面. 原文: Who said javascript was easy ? 译者: Fundebug 为了保证可读性,本文采用意译而非直译.另外,本文版权归原 ...

  8. JavaScript常用,继承,原生JavaScript实现classList

    原文链接:http://caibaojian.com/8-javascript-attention.html 基于 Class 的组件最佳实践(Class Based Components) 基于 C ...

  9. 用纯JS实现,点击一个列表时,输出对应的索引(不能用JQuery哦)

    你运行一下代码会发现,无论你点击哪个列表,控制台都是输出10.这是因为var声明的变量是函数作用域的,而不是块级作用域的.也就是说,for循环10次,每次都是改变同一个i,所以它的值会从0一直加到10 ...

随机推荐

  1. 基于ELK的数据分析实践——满满的干货送给你

    很多人刚刚接触ELK都不知道如何使用它们来做分析,经常会碰到下面的问题: 安装完ELK不知从哪下手 拿到数据样本不知道怎么分解数据 导入到elasticsearch中奇怪为什么搜不出来 搜到结果后,不 ...

  2. Android开发之启动模式的深入理解

    standard(标准模式): 当用ApplicationContext去启动standard模式时会报错,是因为非Activity类型的Context没有所谓的任务栈, 所以需要为待启动的Activ ...

  3. 【G】开源的分布式部署解决方案文档 - 使用手册

    G.系列导航 [G]开源的分布式部署解决方案 - 导航 已知问题 导航没有联动 因为权限只是做了基础的登录校验,考虑到后面导航要跟权限关联上暂时是写死的. 只有部分界面使用了Vue.js 因为刚开始没 ...

  4. 微信小程序-实战巩固(二)

    刚刚写了小程序入门没几天,小程序就开放个人开发者资格,感觉为我而来啊 \(≧▽≦)/.迫不及待的去注册,准备将之前的处女作传上去体验一把,结果卡在了服务器配置上:免费的果然不靠谱/(ㄒoㄒ)/~~,后 ...

  5. 性能测试分享:MYSQL死锁

    poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821478,咨询电话010-845052 ...

  6. Python可视化学习(2):Matplotlib快速绘图基础

    Matplotlib将大部分的绘图对象都封装成为对象,故理论上所有的图表元素(如Line2D, Text,Label等)都是对象,都可以将其在图表中提取出来并配置实例的属性.同时,Matplotlib ...

  7. Java ---自定义标签(二)

    上篇文章的最后,我们自定义了一个带属性的标签,并使用它完成了一个简单的案例.其实到这我们已经可以看出来,前端jsp页面只需要写一个类似html语法的标签,就可以完成将集合中的数据取出来并展示这么相对复 ...

  8. Redis基础学习(四)—Redis的持久化

    一.概述      Redis的强大性能很大程度上都是因为数据时存在内存中的,然而当Redis重启时,所有存储在内存中的数据将会丢失,所以我们要将内存中的数据持久化. Redis支持两种数据持久化的方 ...

  9. 实现高效的GPRS驱动程序

    1. 引言 用过几款GPRS模块,也从淘宝上买过多个GPRS模块,一般的都会送一个驱动程序和使用demo,但是代码质量都较低. 回头看了下几年前使用的GPRS代码,从今天的角度来看,也就是买模块赠送一 ...

  10. c#FTP操作类,包含上传,下载,删除,获取FTP文件列表文件夹等Hhelp类

    有些时间没发表文章了,之前用到过,这是我总结出来关于ftp相关操作一些方法,网上也有很多,但是没有那么全面,我的这些仅供参考和借鉴,希望能够帮助到大家,代码和相关引用我都复制粘贴出来了,希望大家喜欢 ...