检测未绑定的本机函数,如“Array.push”

Detect unbound native functions like `Array.push`?

本文关键字:Array push 函数 绑定 本机 检测      更新时间:2023-09-26

观察以下内容:

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

确实理解为什么会发生这种情况,即:如果您直接将其传递给array_mappush不再绑定到b(而是全局对象(。我真的不明白为什么Chrome没有给出错误,至少Firefox似乎给出了某种错误。

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

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

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

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

我完全不明白你写了自己的映射函数。但是,您的问题是您正在失去该.push()函数的范围。只有当你像xxx.push()一样在Array / Object上调用它时,被调用函数中的this才会正确引用目标对象。一旦你刚刚传递了引用,this要么指向全局/window要么指向undefined,并且不再工作。

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

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

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

通常,这些类型的函数将允许您设置回调的上下文。

如果您将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);

问题是,Javascript没有像"方法"这样的东西 - 一个专门绑定到某个对象的函数。在第一个示例中,您传递了一个调用 a.push 的函数。 this 必须在此处a,因为您直接在 a 上调用它。

在第二个代码中,您只需传递函数push而不b上下文 - this将绑定到作为全局对象的执行上下文。

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

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

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