JS块级作用域与函数作用域–ES6 let
今天在学习ES6时看到新增了块级作用域的概念,于是回顾一下ES5中的函数作用域加深印象
ES5没有块级作用域
ES5中没有块级作用域,只用函数作用域,来看下面一段代码
for (i = 0; i < 1; i++) {
var forVar = 'forVar';
}
console.log(forVar); //'forVar'在for循环中定义的变量forVar可以在for代码块外访问
function fn() {
var fnVar = 'fnVar';
}
console.log(fnVar);//fnVar is not defined,在fn()函数内部定义的变量fnVar不可以在fn()函数外访问
没有块级作用域导致的问题
循环变量泄漏为全局变量
来看使用闭包经常会遇到的一个现象
function test() {
var arr = new Array();
for (var i = 0; i < 6; i++) {
arr[i] = function() {
return i;//i只用来控制循环,循环结束后泄漏成了test函数的变量
}
}
return arr;
}
var arrObj = new test();
console.log(arrObj[0]());//6arrObj[0]访问的是test函数作用域下的变量i,test中i只用来控制循环,循环结束后泄漏成了test函数的变量
在上面的例子中由于没有块级作用域的概念变量i在循环后泄漏为test()函数中的变量,在返回的函数数组中的每一个函数引用的都是test()函数中的变量i
ES5模仿块级作用域
针对上面出现的情况,通常会通过创建匿名函数的方式实现想要的结果
function test() {
var arr = new Array();
for (var i = 0; i < 6; i++) {
arr[i] = function(j) {
return function (){
return j;
}
}(i)
}
return arr;
}
var arrObj = new test();
console.log(arrObj[0]());//0
在上面的代码中,使用了一个立即执行的匿名函数,在每一次循环中匿名函数中的变量j在函数执行结束后都会被销毁
ES6块级作用域
ES6新增了let命令用来进行变量声明,使用let命令声明的变量只在let命令所在代码块内有效
{
var kuaiVar = 'kuaiVar';
let kuaiLet = 'kuaiLet';
}
console.log(kuaiVar, kuaiLet); //kuaiVar,kuaiLet is not defined
for (i = 0; i < 1; i++) {
var forVar = 'forVar';
let forLet = 'forLet';
}
console.log(forVar, forLet); //forVar,forLet is not defined
function fn() {
var fnVar = 'fnVar';
let fnLet = 'fnLet';
}
console.log(fnVar, fnLet);//fnVar is not defined,fnLet is not defined
(function() {
for (i = 0; i < 1; i++) {
var fnForVar = 'fnForVar';
}
})();//使用匿名函数模仿块级作用域
console.log(fnForVar); //fnForVar is not defined
这时我们只需用let替换原来的var就可以避免循环变量泄漏为全局变量的问题
function test() {
var arr = new Array();
for (let i = 0; i < 6; i++) {
arr[i] = function() {
return i; //i只在for循环内有效,每次循环都会创建新的变量i
}
}
return arr;
}
var arrObj = new test();
console.log(arrObj[0]());//0
**注意:**本文参考了阮一峰的《ECMAScript 6 入门》还参考了《javaScript高级程序设计》,文章内容都是自己的理解,有不对的地方还请各位指出。