繁体   English   中英

如何从JS类的构造函数中调用函数

[英]How to call function from the constructor of a JS class

我正在创建一个矩阵类(用于反应应用程序),我想用这种方式定义:

class Matrix extends Object {
    constructor(r, c) {
        super();
        this.rows = new Array(r);
        for (var i=0; i<r; i++) {
            this.rows[i] = new Array(c);
        }
        this.assign((v,i,j) => (i===j)? 1:0);   // ERROR HERE
    }
    assign(f) {
        for (var i=0; i<this.rows.length; i++) {
            for (var j=0; j<this.rows[i].length; j++) {
                this.rows[i][j] = f(this.rows[i][j], i, j);
            }
        }
    }
    // and so on

这可以通过webpack编译好,但是在运行时,我在chrome控制台中收到错误,说_this.assign不是一个函数

我可以这样工作:

constructor(r, c) {
    super();
    this.rows = new Array(r);
    for (var i=0; i<r; i++) {
        this.rows[i] = new Array(c);
    }
    this.assign = function(f) {
        for (var i=0; i<r; i++) {
            for (var j=0; j<r; j++) {
                this.rows[i][j] = f(this.rows[i][j], i, j);
            }
        }
    };
    this.assign((v,i,j) => (i===j)? 1:0);
}

但这是错的,对吧? 我不应该在构造函数中定义所有对象的函数,对吧? 在同一个文件中,我定义了反应类,如:

class MatrixComponent extends React.Component { ... }

那些能够调用函数而不在构造函数中定义它们。 我错过了什么?

删除extends Objectsuper()调用似乎对我有用。

class Matrix { // extends Object {
    constructor(r, c) {
        // super();
        this.assign();
    }
    assign() {
    }
}

每个类已经在其原型链中具有Object,因此您不会通过扩展Object获得任何东西。 extends Object是隐式的,因此将其删除。


似乎处理extends Object是Babel中的一个错误。 Chromium浏览器的内置es6引擎处理代码很好,因为它已在此修复: https ://bugs.chromium.org/p/v8/issues/detail?id = 3886

但看起来Babel的转换es5已被打破。

在Chrome中使用es6


为了解释这种行为,让我们看一下来自babel的转换后的es5。

鉴于此es6:

class OtherClass {}

class OtherClassExtender extends OtherClass {
    constructor(r, c) {
        super();
        this.assign();
    }
    assign() {
    }
}

class ObjectExtender extends Object {
    constructor(r, c) {
        super();
        this.assign();
    }
    assign() {
    }
}

new OtherClassExtender(1, 2);
new ObjectExtender(1, 2);

我们将只收集已转换的es5的片段。 我删除了很多代码。 这不是完整的转换来源:

function _possibleConstructorReturn(self, call) {
  if (!self) {
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  }
  if (call && (typeof call === "object" || typeof call === "function")) {
    return call;
  } else {
    return self;
  }
}

var OtherClass = function OtherClass() {};

var OtherClassExtender = function (_OtherClass) {    
    function OtherClassExtender(r, c) {
        var _this = _possibleConstructorReturn(this, _OtherClass.call(this));
        _this.assign();
        return _this;
    }
    OtherClassExtender.prototype.assign = function assign() {};
    return OtherClassExtender;
}(OtherClass);

var ObjectExtender = function (_Object) {
    function ObjectExtender(r, c) {
        var _this2 = _possibleConstructorReturn(this, _Object.call(this));
        _this2.assign();
        return _this2;
    }
    ObjectExtender.prototype.assign = function assign() {};
    return ObjectExtender;
}(Object);

new OtherClassExtender(1, 2);
new ObjectExtender(1, 2);

_possibleConstructorReturn基本上是super ,其中Babel保留了类的超类的引用,因此方法调用可以正确地遍历继承层次结构。 它基本上说“超级类已经定义了方法,所以让我们看一下方法(比如assign )”。 Object本身添加到该层次结构中没有任何意义,因为Javascript中的任何对象都将从Object继承方法。

通过逐步执行转换后的代码, _possibleConstructorReturn(OtherClassExtender, OtherClass)表示typeof call undefined因此返回OtherClassExtender

_possibleConstructorReturn(ObjectExtender, Object)表示typeof callobject因此它返回Object

对象实例没有assign方法。 assignObject类的一个类方法,它不存在于(new Object).assign例如。

通过反复试验,我发现扩展null vs Object ,修复了问题:

class Matrix extends null { ... }

我想这是一个答案,但我对于为什么以及我试图这样做有什么不对而感到困惑。 我很乐意用正确的方式标记一个更好的答案 :这真的解释了这些东西是如何工作的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM