请注意以下事项:
function array_map(array, callback) {
for (var i = 0; i < array.length; i += 1) {
callback(array[i]);
}
}
var a = [], b = [];
array_map([1, 2, 3], function (x) { a.push(x); });
// just gives a = [1, 2, 3] as expected
// but why does this not work: ?
array_map([1, 2, 3], b.push);
// Chrome: a = [], Firefox: can't convert undefined to object
我执行了解为什么会发生这种情况,即:push
如果将其传递给{{1},则不再绑定到b
(但对全局对象)直接我真的不明白为什么Chrome不会出错,至少Firefox似乎会出现某种错误。
如何检测此类函数是否传递给array_map
以避免这些错误?
我希望有先进的反射技术来跟踪函数的来源。例如array_map
给出了b.push.constructor
,但这不是我想要的。
答案 0 :(得分:2)
我不确定你期望会发生什么。 Array.prototype.map
需要一个函数作为第二个参数,它会为每次迭代返回 new 值。
仅传入函数引用(在第二个示例中执行)并不会告诉函数它无论如何都要执行。所以你有点期待 .map()
应用一些黑魔法并使用正确的参数调用传入的方法,显然,这是不可能的。
我完全不知道你编写了自己的映射函数。但是,您的问题是您正在丢失该.push()
函数的范围。只有当您在Array / Object
xxx.push()
上调用它时,被调用函数中的this
才能正确引用目标对象。在您完成参考后,this
将指向全局 / window
或undefined
,并且将不再有效。
所以解决这个问题你可以称之为
array_map([1, 2, 3], b.push.bind(b));
也适用于ES5功能。您无法在array_map()
内真正检测到它。函数是一个函数,你最好的方法是检测传入的方法是否是本机的,但我不建议这样做。
答案 1 :(得分:1)
问题是,Javascript没有“方法”这样的东西 - 一个专门绑定到某个对象的函数。在第一个示例中,您传递了一个调用a.push
的函数。 this
绑定到a
,因为您直接在。
在第二个代码中,您只需传递函数push
,而不会将b
- this
的上下文绑定到执行上下文,这是gloabl对象。
您需要绑定函数的上下文,如下所示:
array_map([1, 2, 3], b.push.bind(b));
或jQuery的proxy()
。我目前找不到另一个简单的解决方案,而是直接在第三个参数中移交上下文:function array_map(array, callback, context)
答案 2 :(得分:1)
通常这些类型的函数允许您设置回调的上下文。
如果更改array_map函数以接受上下文,那么它将像这样工作。
function array_map(array, callback, context) {
for (var i = 0; i < array.length; i += 1) {
callback.call(context, array[i]);
}
}
var b = [];
// now the push method is called from the b context
array_map([1, 2, 3], b.push, b);