我试图扩展Array.prototype一些新的方法/属性,以下是我在第一次尝试中所做的,最终得到了TypeError:
// 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\nRun 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\nRun Code Online (Sandbox Code Playgroud)\n有谁知道这两种方法之间有什么区别,最重要的是为什么第一次尝试失败?
\n在您的第一个代码中,当您使用 时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)