JavaScript闭包
闭包是指有权访问另一个函数作用域中的变量的函数
function compare(prop) {
return function (obj1, obj2) {
let val1 = obj1[prop];
let val2 = obj2[prop];
if (val1 < val2) return -1;
else if (val1 === val2) return 0;
else return 1;
};
}
var obj1 = {
age: 20,
name:'obj1'
};
var obj2 = {
age: 2,
name:'obj2'
};
var array = [obj1, obj2];
array.sort(compare('age'));
console.log(array); //[ { age: 2, name: 'obj2' }, { age: 20, name: 'obj1' } ]
我们在compare函数内部创建了一个匿名函数,由于匿名函数位于compare内部,所以可以访问compare的参数prop,这样就通过闭包访问了别的函数中的变量,延长了变量的生命周期。
需要注意的是,闭包保存的是所外层函数中的变量对象,而不是变量本身的值
function createFuncs() {
var res = [];
for (var i = 0; i < 10; i++) {
res[i] = function () {
return i;
};
}
return res;
}
console.log(createFuncs()[0]());//10
console.log(createFuncs()[2]());//10
console.log(createFuncs()[9]());//10
如上所示,如果想用这种方式保存每次循环中i的值是错误的做法。因为所创建的匿名函数的作用链中都保存着createFuncs函数的活动对象,所以他们每次引用的都是用一个变量i,即res中保存的函数中都只能返回i的最后一个值,10。
解决的这种问题的方法也很简单:
function createFuncs() {
var res = [];
for (var i = 0; i < 10; i++) {
res[i] = function (num) {
return function(){
return num;
};
}(i);
}
return res;
}
console.log(func()[0]());//0
console.log(func()[2]());//2
console.log(func()[9]());//9
如上所示,我们没有直接把闭包的值赋给数组,而是定义一个匿名函数接收即将返回的值,并执行它。我们知道JavaScript中函数参数是值传递的,所以传递给匿名函数的参数会被复制一个副本,并返回出来。
模拟块级作用域
由于JavaScript没有会计作用域的概念,这意味着只要是在函数内部,无论是否在语句块中生命的变量,出了语句块依然可以访问的到。
function foo(){ for(var i = 0; i < 10; i++){} console.log(i);//10 }
如上代码,出了for循环依然可以访问变量i
由于JavaScript的最小作用域就是函数内部,所以我们可以借助匿名函数来模拟块级作用域。如下所示:
function foo(){ function(){ var i = 0 ; } console.log(i);//Unexpected token }