在开始本文以前咱们先来看一段代码javascript
for(var i=0;i<10;i++){ arr[i]=function(){ return i; } } console.log(arr[3]());//10
显然这段代码输出10,并无向咱们指望的返回3,缘由也很简单(js的变量提高)函数在调用时候访问的是一个全局做用域的i,此时for循环已经执行完毕,全局变量i=10;html
在ES5标准中,咱们要想返回指望的3,一般的作法也很简单,就是让数组中的每一个函数有单独的做用域,那么咱们只要构造一个当即执行函数便可(js中没有块级做用域,只区分函数做用域和全局做用域)就像下面这样:java
var array=[]; for(var i=0;i<10;i++){ array[i]=(function(i){ return function(){ return i; } })(i); } console.log(array[3]());//3
这样一来数组的每一个函数就处于一个当即执行函数的函数做用域中,该当即执行函数传入i,其实for循环执行了以下代码:webpack
array[0]=(function(i){ return function(){ return i; } })(0); array[1]=(function(i){ return function(){ return i; } })(1); array[2]=(function(i){ return function(){ return i; } })(2); ……
这样一来,数字组中每一个函数对应一个单独的函数做用域(当即执行函数的)这里共建立了10个函数做用域,这些函数做用域里的i值就是执行时候传入的0……9,当执行web
array[3]();时候函数访问的i值是其对应的当即执行函数做用域里的 i,而不是全局的i值,这样咱们就获得了预期的效果。数组
说获得这里咱们简单来讲一下闭包,闭包能够理解为一个闭包就是一个没有释放资源的栈区,栈区内的变量处于激活状态。上面的例子中for循环在执行时系统分配内存,js执行线程建立执行栈区,执行时候检测到当即执行函数里的变量i被内部函数引用,因此该栈区在内存中没有被释放,函数(数组元素)被调用时候根据做用链首先访问到的是上一级做用域(当即执行函数)的变量。闭包
这里再也不详细介绍闭包,若是想详细了解闭包请阅读《javascript高级程序设计》第7章函数
前面提到js中并无块级做用域,只区分全局做用域和函数做用域,在ES6中let实际是为js新增了块级做用域,例以下面代码不用创造函数做用域就可让每一个数组里的函数访问各自做用域里的值:oop
let arr=[]; for(let i=0;i<10;i++){ arr[i]=function(){ return i; } } console.log(arr[3]());//3
能够看到咱们并无像以前那样构造一个函数做用域就能实现咱们指望的效果,引入块级做用域以后更方便咱们书写和理解代码,上述代码中for循环以后的{}是块级做用域,每次循环时候每一个返回的函数引用的是其对应块做用域的变量,稍微改一下代码看着形象些:优化
let arr=[]; for(let i=0;i<10;i++){ let k=i; arr[k]=function(){ return k; } } console.log(arr[3]());//3
可见ES6引入块做用域以后咱们构造闭包函数更方便了。
这里很少叙述let和const的相关内容,若是以前没接触ES6的小伙伴建议阅读阮一峰老师的《ES6标准入门》。
在这里再提一点,不少人看完概念以后,第一印象都是:“const 是表示不可变的值,而 let 则是用来替换原来的 var 的。”不少时候把let当作是var的替代品,凡是声明变量就用let,你极可能写出下面代码:
// 定义常量 const REG_GET_INPUT = /^\d{1,3}$/; // 定义配置项 let config = { isDev : false, pubDir: './admin/' } let path = require('path'); let HtmlWebpackPlugin = require('html-webpack-plugin'); let CleanWebpackPlugin = require('clean-webpack-plugin');
const 的定义是不可从新赋值的值,与不可变的值(immutable value)不一样;const 定义的 Object,在定义以后仍能够修改其属性。
因此其实他的使用场景很广,包括常量、配置项以及引用的组件、定义的 “大部分” 中间变量等,都应该以cosnt作定义。反之就 let 而言,他的使用场景应该是相对较少的,咱们只会在 loop(for,while 循环)及少许必须重定义的变量上用到他。
猜测:就执行效率而言,const 因为不能够从新赋值的特性,因此能够作更多语法静态分析方面的优化,从而有更高的执行效率。
因此上面代码中,全部使用 let 的部分,其实都应该是用 const 的。