2011-12-23 92 views
5

我定义为阵列中的两个功能:如何在内部函数中调用外部“this”?

Array.prototype.remove = function(obj) { 
    var i = this.length; 
    while (i--) { 
     if (this[i] === obj) { 
      this.removeAt(i); 
     } 
    } 
}; 
Array.prototype.removeAll = function(array2) { 
    array2.forEach(function(item) { 
     this.remove(item); // remove not found!! 
    }); 
} 

但在removeAll功能,它报告function remove is not found。我这样修复:

Array.prototype.removeAll = function(array2) { 
    var outer = this; 
    array2.forEach(function(item) { 
     outer.remove(item); 
    }); 
} 

但它很丑。有没有更好的办法?

+0

我不认为这是非常难看的,而且很有效。你的foreach中的'this'变成迭代中的项目,所以我没有看到太多的解决方法。 – Paddy 2011-12-23 09:29:02

回答

6

通过一个不同的变量传递this,你所做的是惯用的方法。没有什么丑陋的。 (通常称为变量thatself虽然)

1

Function.bind和类似的。

array2.forEach((function(item) { 
    this.remove(item); 
}).bind(this)); 

这不是技术上是相同的,因为之前的“内部这种”现阴影/丢失(并创建一个新的包装功能),但它很好地工作在某些情况下。

在大多数情况下,我更喜欢标准var self = this ...

快乐编码。

+0

据我所知'Function.bind'是ECMAScript 5,它只支持最新的浏览器(不支持IE8,FF3.6,FF3.6,Safari 4,Safari 5,Safari 5.1和Opera 10.50 - 11.50) – 2011-12-23 09:40:54

+0

@StefanGehrig你是正确的,因此“和类似的”:-)很容易实现这样的功能,MDC文档提供了这样一个例子。相同的功能可以在许多框架中找到。 – 2011-12-23 09:44:00

+0

只是想注意这个重要的细节... ;-) – 2011-12-23 12:36:28

2

通过将下一个参数传递给forEach这将回调函数中的this的上下文在您的情况下,this引用窗口对象。

Array.prototype.removeAll = function(array2) { 

    array2.forEach(function(item) { 
     this.remove(item); 
    },this); 
} 
+0

非常好,我不知道。 – 2011-12-23 09:35:51

+3

请注意,ie8和更早版本不支持此功能。 – 2011-12-23 09:47:53

2

使用绑定(如果你需要支持旧的浏览器,并且不希望延长Function.prototype)是简单地包裹你的回调在immidate功能和饲料this作为这样一个论点一种替代方案:

Array.prototype.removeAll = function(array2) { 
    array2.forEach(function(outer){ 
    return function(item) { 
     outer.remove(item); 
    };}(this)); 
} 

,或者你可以写一个简单的咖喱效用函数,并使用类似这样的

function curry() { 
    var fn = Array.prototype.shift.call(arguments), 
     args = Array.prototype.slice.call(arguments); 
    return function curryed() { 
    return fn.apply(this, args.concat(Array.prototype.slice.call(arguments))); 
    }; 
}; 



Array.prototype.removeAll = function(array2) { 
    array2.forEach(curry(function(item) { 
     outer.remove(item); 
    },this)); 
} 

如果你不介意扩展Function.prototype您可以使用绑定,如其他人已经描述的那样,您可以在这里找到MDN上出色的兼容性扩展:https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind