0

请注意以下事项:

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则不再绑定到(而是绑定到全局对象) 。我真的不明白为什么 Chrome 没有给出错误,至少 Firefox 似乎给出了某种错误。barray_map

如何检测是否传递了这样的函数array_map以避免此类错误

我希望有先进的反射技术可用于追踪函数的起源。例如b.push.constructorFunction,但这不是我要找的。

4

3 回答 3

2

我不确定你期望那里发生什么。Array.prototype.map需要一个函数作为第二个参数,它为每次迭代返回一个值。

仅传入一个函数引用(您在第二个示例中所做的)并不能告诉该函数它必须做什么。所以你有点期待.map()应用一些黑魔法并使用正确的参数调用传入的方法,这显然是做不到的。

我完全不明白您编写了自己的映射函数。但是,您的问题是您正在失去该功能的范围。.push()只有当你在Array / Objectlike上调用它时xxx.push()this被调用函数中的 才会正确引用目标对象。一旦您刚刚通过了引用,this它将指向全局/windowundefined将不再工作。

所以解决这个问题,你可以这样称呼它

array_map([1, 2, 3], b.push.bind(b));

这也将应用 ES5 功能。您无法在array_map(). 函数就是函数,最好的方法是检测传入的方法是否是本机方法,但我不建议这样做。

于 2012-08-20T12:57:57.823 回答
1

问题是,Javascript 没有“方法”之类的东西——一个专门绑定到某个对象的函数。在您的第一个示例中,您传递了一个调用a.push. this绑定到a这里是因为你直接在 a 上调​​用它。

在您的第二个代码中,您只需传递push没有上下文的函数b-this将绑定到执行上下文,即 gloabl 对象。

您需要绑定函数的上下文,如下所示:

array_map([1, 2, 3], b.push.bind(b));

或 jQuery 的proxy(). 目前我找不到另一个简单的解决方案,而是直接在第三个参数中交出上下文:function array_map(array, callback, context)

于 2012-08-20T13:09:23.817 回答
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);
于 2012-08-20T13:17:32.843 回答