ES6构造函数返回基类的实例

ES6 constructor returns instance of base class?

本文关键字:实例 基类 返回 构造函数 ES6      更新时间:2023-09-26

派生类的构造函数返回基类的一个实例。

以下代码解释了我的问题:

// Vector is defined by an external module (Unreal.js)
class TestB extends Vector {
    constructor() {
        super();
    }
    Log() {
        console.log("" + this);
    }
}
console.log(new TestB() instanceof TestB) // returns false !!! why ??? 
console.log(new TestB() instanceof Vector) // returns true...
class TestA extends Array {
    constructor() {
        super();
    }
    Log() {
        console.log("" + this);
    }
}
console.log(new TestA() instanceof TestA); // returns true, all is good

这怎么可能?

Vector的实现方式似乎与class不兼容。

以下是Vector可以做到这一点的一个方法示例:

function Vector() {
  var v = Object.create(Vector.prototype);
  return v;
}
class TestB extends Vector {
  constructor() {
    super();
  }
}
console.log(new TestB() instanceof TestB);  // false
console.log(new TestB() instanceof Vector); // true

这里的关键是,由于Vector返回的对象与new创建的对象不同,所以它的类型错误。关于构造函数函数,一个相对鲜为人知的事情是,如果它们返回非null对象引用,那么new Constructor的结果就是构造函数返回的对象,而不是创建的对象new

以下是那些浏览器支持class:的人的代码片段

function Vector() {
  var v = Object.create(Vector.prototype);
  return v;
}
class TestB extends Vector {
  constructor() {
    super();
  }
}
console.log(new TestB() instanceof TestB); // false
console.log(new TestB() instanceof Vector); // true

以及Babel的REPL上为那些浏览器没有的人提供的实时副本。

令我惊讶的是,Babel和Chrome都允许我使用class Vector并从constructor返回一个值;我还没有从规范中弄清楚它是否真的有效:

class Vector {
  constructor() {
    var v = Object.create(Vector.prototype);
    return v;
  }
}
class TestB extends Vector {
  constructor() {
    super();
  }
}
console.log(new TestB() instanceof TestB); // false
console.log(new TestB() instanceof Vector); // true

为了解决这个问题,您可能需要使用每实例破解,比如将TestB.prototype的所有方法复制到实例上。理想情况下,与其进行黑客攻击,不如尝试通过聚合(也称为"组合",例如,通过将Vector实例作为类实例的属性)而不是继承来使用Vector,因为它不是为继承而设置的。

我不知道这个问题的确切原因,但黑客proto解决了这个问题。:)

class TestB extends Vector {
    constructor() {
        super();
        this.__proto__ = TestB.prototype;
    }
    Log() {
        console.log("" + this);
    }
}