Object.assign() 导致 TypeError: this.map 不是函数

loc*_*wei 5 javascript

我试图扩展Array.prototype一些新的方法/属性,以下是我在第一次尝试中所做的,最终得到了TypeError

\n
// Array.prototype + .max(), .maxRowLength (by Object.assign)\nObject.assign(Array.prototype, {\n\n    // max something in the array\n    max(mapf = (x) => x) {\n        // -----------------------------------------\n        return Math.max(...this.map(x => mapf(x)));\n        //                 ^^^^^^^^\n        // \xe2\x9b\x94 TypeError: this.map is not a function\n        // -----------------------------------------\n    },\n\n    // max row length of 2D array\n    // assuming an element of the 2D array is called a "row"\n    get maxRowLength() {\n        return this.max(row => row.length);\n    },\n});\n\n// matrix (2D array)\nlet m = [[1, 2, 3, 4], [1, 2], [1, 2, 3]];\n\nm.max(row => row.length)    // didn't work, can't even run.\nm.maxRowLength\n
Run Code Online (Sandbox Code Playgroud)\n

我不明白为什么会发生这种情况,所以我继续第二次尝试,这次采用了不同的方法,并且它成功运行,没有任何问题:

\n
// Array.prototype + .max()\nArray.prototype.max = function(f = x => x){\n    return Math.max(...this.map(x => f(x)));\n};\n\n// Array.prototype + .maxRowLength (by Object.defineProperty)\nObject.defineProperty(Array.prototype, 'maxRowLength', {\n    get: function(){ return this.max(row => row.length) }\n});\n\n// matrix (2D array)\nlet m = [[1, 2, 3, 4], [1, 2], [1, 2, 3]];    // 3 "rows"\n\nm.max(row => row.length)    // 4 \xe2\x9c\x85\nm.maxRowLength              // 4 \xe2\x9c\x85\n
Run Code Online (Sandbox Code Playgroud)\n

有谁知道这两种方法之间有什么区别,最重要的是为什么第一次尝试失败?

\n

Cer*_*nce 4

在您的第一个代码中,当您使用 时Object.assign,第一个之后的参数将调用其 getter:

Object.assign(
  {},
  { get foo() { console.log('getter invoked'); } }
);
Run Code Online (Sandbox Code Playgroud)

因此,在您get maxRowLength声明数组之前,您的 就立即运行m- 当调用 getter 时,它会调用this.max,此时,this是您传递给 的第二个参数Object.assign,即该对象 - 它不有一个.map方法,导致错误。

这是另一个更简单的代码示例,用于显示发生的情况:

const objectToAssign = {
    max() {
        // `this` is the object here
        console.log(this === objectToAssign);
    },
    get maxRowLength() {
        return this.max();
    },
};
Object.assign(Array.prototype, objectToAssign);
Run Code Online (Sandbox Code Playgroud)