首页 > 解决方案 > 如何编写扩展 Array 类的正确构造函数

问题描述

设想

我有以下代码:

const composeMatrix = (nRow, nCol, filler) => Array(nRow).fill(Array(nCol).fill(filler));

class Matrix extends Array {
    constructor({ nRows = 3, nCols = 3, filler = 0 } = {}) {
        super(...composeMatrix(nRows, nCols, filler));
    }
    makeTranspose() {
        const mat = this;
        const column = mat[0];
        return column.map((_, i) => {
            return mat.map((row) => row[i]);
        });
    }
}

我正在实例化一个这样的新的Matrix

const mat = new Matrix({ nRows: 4, filler: 1 });

登录mat到控制台给了我预期的结果,

Matrix(4) [ 
  [ 1, 1, 1 ], 
  [ 1, 1, 1 ], 
  [ 1, 1, 1 ],
  [ 1, 1, 1 ]
]

问题

现在,当我调用makeTranspose该类的方法时,它返回给我:

[ 
  Matrix(4) [ 1, 1, 1, 1 ], 
  Matrix(4) [ 1, 1, 1, 1 ],
  Matrix(4) [ 1, 1, 1, 1 ] 
]

预期输出:

Matrix(3) [
  [ 1, 1, 1, 1 ], 
  [ 1, 1, 1, 1 ], 
  [ 1, 1, 1, 1 ]
]

我想的是, map 函数每次遍历数组时都会调用这个子类的构造函数,数组又调用super,然后调用composeMatrix函数并生成一个新的 Matrix 。

我怎样才能解决这个问题?

标签: javascriptarraysclassoopconstructor

解决方案


矩阵不是数组。你最好使用组合而不是继承

Array.create = (length, mapping) =>
    Array.from({ length }, (value, index) => mapping(index));

class Matrix {
    constructor(rows, cols, data) {
        this.rows = rows;
        this.cols = cols;
        this.data = data;
    }

    static create(rows, cols, mapping) {
        const data = Array.create(rows, row =>
            Array.create(cols, col => mapping(row, col)));
        return new Matrix(rows, cols, data);
    }

    transpose() {
        const { rows, cols, data } = this;
        return Matrix.create(cols, rows, (row, col) => data[col][row]);
    }
}

const mat = Matrix.create(4, 3, (row, col) => 1);

console.log(mat.transpose());

使用函数式编程风格。

const array = (length, mapping) =>
    Array.from({ length }, (value, index) => mapping(index));

const Matrix = (rows, cols, data) => ({ rows, cols, data });

const matrix = (rows, cols, mapping) =>
    Matrix(rows, cols, array(rows, row =>
        array(cols, col => mapping(row, col))));

const transpose = ({ rows, cols, data }) =>
    matrix(cols, rows, (row, col) => data[col][row]);

const mat = matrix(4, 3, (row, col) => 1);

console.log(transpose(mat));


推荐阅读