javascript中的闭包
什么是闭包?
闭包是指有权访问另一个函数作用域中变量的函数。创建闭包的常见方式是在一个函数内部创建另一个函数。
function createClosureFunction(propertyName) {
return function (obj1, obj2) {
var v1 = obj1[propertyName];
var v2 = obj2[propertyName];
if (v1 < v2) {
return -1;
} else if (v1 > v2) {
return 1;
} else {
return 0;
}
}
}
上述v1
和v2
的值通过访问外部函数中的变量propertyName
来获取。即使这个内部函数被返回了,而且还是在其他地方被调用了。但它仍然可以访问变量propertyName
。之所以还能够访问这个变量,是因为内部函数的作用域链中包含createClosureFunction()
的作用域。
当匿名函数从createClosureFunction
中被返回后,它的作用域链被初始化为包含createClosureFunction()
函数的活动对象和全局变量。
那么如下的这个经典的闭包问题就好解释了。
function createFunctions() {
var result = new Array();
for (var i = 0; i < 10; i++) {
result[i] = function () {
return i;
}
}
return result;
}
这个函数返回一个函数数组。从表面上看,似乎每个函数应该返回自己的索引值,即0的位置返回0,1的位置返回1,以此类推。实际上,每个函数都返回的是10。为什么会出现这样的情况?这是因为每个函数的作用域链中都保存着createFunctions()
函数的活动对象,所以他们引用的都是同一个变量i
。当createFunctions()
函数返回后,变量i
的值是10,此时每个函数都引用着保存变量i
的同一个变量对象,所以在每个函数内部i
的值都是10。
解决这个问题可以使用如下方式,通过匿名函数传递参数的方式来进行修改,因为函数参数是按值传递的,所以会将每次的变量i
的值传递给匿名函数的参数num
中去。
function createFunctions() {
var result = new Array();
for (var i = 0; i < 10; i++) {
result[i] = function (num) {
return num;
}(i);
}
return result;
}
另一个需要注意的是闭包中的this
对象。
由于匿名函数的执行环境具有全局性,因此this
对象通常指向window
。
var name = 'window'
var obj = {
name: 'zhangsan',
sayName: function () {
return function() {
return this.name;
}
}
}
console.log(obj.sayName()()); //window
解决这个问题,就是将外部作用域中的this
对象保存在一个闭包可以访问到的变量中就可以了。
var name = 'window'
var obj = {
name: 'zhangsan',
sayName: function () {
var that = this;
return function() {
return that.name;
}
}
}
console.log(obj.sayName()()); //zhangsan
如果您觉得本文对您有用,欢迎捐赠或留言~
- 本博客所有文章除特别声明外,均可转载和分享,转载请注明出处!
- 本文地址:https://www.leevii.com/?p=936