var和let的区别,使用闭包解决var的函数作用域问题
一、var和let的区别
var | let |
---|---|
函数作用域 | 块作用域 |
在函数内声明了var,整个函数内都是有效的,在for循环内定义了一个var变量,实际上其在for循环以外也是可以访问的 | let由于是块作用域,所以如果在块作用域内(for循环内)定义的变量,在其外面是不可被访问的 |
会默认成为window的一个属性 | 不会添加到window对象中 |
声明带有var关键字的变量会为该变量创建单个绑定(存储空间) | 使用 let 声明一个具有块级作用域的变量,则为每个循环迭代创建一个新的绑定 |
二、用var和let声明变量的实例
例1:用var进行声明
在for循环的头部声明带有var关键字的变量会为该变量创建单个绑定(存储空间)。
var array = [];
for (var i = 0; i < 3; i++) {
// 三个箭头函数体中的每个`'i'`都指向相同的绑定,
// 这就是为什么它们在循环结束时返回相同的值'3'。
array.push(() => i);
}
var newArray = array.map(el => el());
console.log(newArray); // [3, 3, 3]
- 误解作用域:认为存在块级作用域(x)
例2:用let进行声明
如果使用 let 声明一个具有块级作用域的变量,则为每个循环迭代创建一个新的绑定。
// 使用ES6块级作用域
var array = [];
for (let i = 0; i < 3; i++) {
// 这一次,每个'i'指的是一个新的的绑定,并保留当前的值。
// 因此,每个箭头函数返回一个不同的值。
array.push(() => i);
}
var newArray = array.map(el => el());
console.log(newArray); // [0, 1, 2]
例3:闭包
解决这个问题的另一种方法是使用闭包。
let array = [];
for (var i = 0; i < 3; i++) {
array[i] = (function(x) {
return function() {
return x;
};
})(i);
}
const newArray = array.map(el => el());
console.log(newArray); // [0, 1, 2]
三、扩展:闭包
1、特点:
- 闭包是一个函数,而且存在于另一个函数当中
- 闭包可以访问到父级函数的变量,且该变量不会销毁
- 缓存数据,延长作用域
//闭包的实现
function fn(){
var n = 1;
//将test这个函数返回
return function(){
n++;
console.log(n);
}
}
var resFn = fn();//将fn调用完成的返回值保存到变量resFn中
resFn();//2
resFn();//3
resFn();//4