ES5之前只有全局作用域和函数作用域,没有块级作用域,就会用闭包解决这个问题。
Es6的let可以将变量绑定到任意的作用域上({..}内部)。使得for循环的循环语句部分是个父级作用域,循环体内部是个单独的子作用域。if语句和for语句里面的{ }也属于块级作用域。
var 存在变量提升,在变量声明之前就访问变量会使用默认值 undefined,而 let,const(后面会提及)声明的变量却不存在变量提升
let不允许在相同作用域内,重复声明同一个变量。
var闭包:
function count() {
var arr = [];
for (var i=1; i<=3; i++) {
arr.push(function () {
return i * i;
});
}
return arr;
}
var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
f1(); // 16
f2(); // 16
f3(); // 16
let闭包:
function count() {
let arr = [];
for (let i = 1;i<=3;i++){
arr.push(function () {
return i*i;
})
}
return arr
}
let result = count()
let f1 = result[0]
let f2 = result[1]
let f3 = result[2]
console.log('result1',f1()) //1
console.log('result2',f2()) //4
console.log('result3',f3()) //9
数据类型的时候分析
注:复合类型const变量保存的是引用。因为复合类型(如数组和对象)的常量不指向数据,而是指向数据(heap)所在的地址(stack),所以通过 const 声明的复合类型只能保证其地址引用不变,但不能保证其数据不变。所以将一个对象声明为常量必须非常小心。
简单数据类型(数值,字符串,布尔值):值保存在变量指向的那个内存地址,因此等同于常量。
复合类型的数据(对象和数组):变量指向的是内存地址,保存的是一个指针,const只能保存这个指针地址是固定的,至于他指向的数据结构是不是可变的,就完全不能控制了。
闭包的应用
1:闭包就是携带状态(完全隐藏起来)的函数。
2:把多参函数变为单参函数,pow(x,n)
function make_pow(n){
return function (x) {
return Math.pow(x,n)
}
}
let pow2 = make_pow(2)
let pow3 = make_pow(3)
console.log('pow2',pow2)
console.log('pow3()',pow3(3))