Got "TypeError: Cannot convert undefined or null to object" in Function.prototype

Got "TypeError: Cannot convert undefined or null to object" in Function.prototype

出于学习目的,我写了一段(无意义的)代码如下:

Function.prototype.invoke = function(...args) {
    return this(...args);
}
const foo = (a, b) => a + b;
console.log(foo.invoke(1, 2)); // 3, all right!

const arr = [];
arr.push.invoke(1,2); // TypeError: Cannot convert undefined or null to object
console.log(arr);

这里我在Function的原型上定义了一个名为invoke的方法,它用来通过foo.invoke(args)调用一个函数(而不是传统的方式foo(args)).我想知道为什么 foo 可以运行而 arr.push 不能。

据我所知,这是 this 问题的结果。 this 在我的 invoke 方法中是 push,但是 thisthispush 的调用者)是 window,这不是一个类似数组的对象(?)。但是为什么错误是Cannot convert undefined or null to object呢?

这个错误到底是什么原因?有什么办法可以纠正吗?

arr.pushArray.prototype.push 的功能相同,Array.prototype.push 需要一个 调用上下文 来识别参数是哪个数组将被推到。有

arr.push(1, 2);

调用上下文(调用函数时出现在 . 之前的内容)是 arr。但是你的 invoke 没有调用上下文:

return this(...args);

出于同样的原因,您不能 call push on undefined:

Array.prototype.push.call(undefined, 1, 2);

如果你想 "invoke" 一个需要调用上下文的函数,可以将 this 值作为第一个参数传递并使用 .call:

Function.prototype.invoke = function(thisVal, ...args) {
    return this.apply(thisVal, args);
}
const foo = (a, b) => a + b;
console.log(foo.invoke(undefined, 1, 2)); // 3, all right!

const arr = [];
arr.push.invoke(arr, 1,2);
console.log(arr);

您还可以在调用 invoke:

之前 bind arr.pusharr

Function.prototype.invoke = function(...args) {
    return this(...args);
}
const foo = (a, b) => a + b;
console.log(foo.invoke(1, 2)); // 3, all right!

const arr = [];
arr.push.bind(arr).invoke(1,2);
console.log(arr);