Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/445.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在ES6中生成与调用实例相同类的对象_Javascript_Oop_Ecmascript 6 - Fatal编程技术网

Javascript 在ES6中生成与调用实例相同类的对象

Javascript 在ES6中生成与调用实例相同类的对象,javascript,oop,ecmascript-6,Javascript,Oop,Ecmascript 6,我有一个从Array扩展而来的类'Grid',其目的是实现一些用于双向数组的方法,它目前没有'constructor'函数。为了简洁起见,我只展示了有问题的函数:Grid.getPlane,它返回一个用参数构造的子网格 class Grid extends Array { //... getPlane(width, height, x, y) { let myPlane = new Grid; // calculations... return myPlane;

我有一个从Array扩展而来的类'Grid',其目的是实现一些用于双向数组的方法,它目前没有'constructor'函数。为了简洁起见,我只展示了有问题的函数:Grid.getPlane,它返回一个用参数构造的子网格

class Grid extends Array {
//...
    getPlane(width, height, x, y) {
    let myPlane = new Grid; 
    // calculations...
    return myPlane;
    }
//...
}
我还有另外一个类“地形”,从这个类扩展而来。这一个旨在为地形数据提供一些更具体的功能。预期的功能是,每当我调用类“Terrain”实例的“getPlane”函数时,返回的对象也属于“Terrain”类,因此我可以使用该类特有的函数。但正如您所预测的,我要么使用从“Grid”继承的函数声明,得到一个网格而不是地形,要么覆盖该函数,留下丑陋的重复代码:

class Terrain extends Grid {
//...
    getPlane(width, height, x, y) {
    let myPlane = new Terrain; 
    // calculations...
    return myPlane;
    }
//...
}
我试图在中使用Object.create,但:

let myPlane = Object.create(this.prototype)
返回未定义的。 及

给我一个名为“Terrain”的对象,它的行为不像数组。 Object.create是否有办法为我获取与“this”对象相同类的对象?或者以任何其他方式生成具有相同类的对象?

这是一种以下情况:

做得太多的方法 缺乏对超能力方法的呼唤 深度嵌套的层次结构是编写可维护系统的痛苦方式;乘以4000x,单位为JS 第一:

// assume
class A extends Array {
  doX (x) {
    console.log(`A.doX(${x})`);
    return new A();
  }
}

class B extends A {
  doX (x, y) {
    super.doX(x);
    console.log(`B.doX(${x}, ${y})`);
    return new B();
  }
}

class C extends B {
  doX (x, y, z) {
    super.doX(x, y);
    console.log(`C.doX(${x}, ${y}, ${z})`);
    return new C();
  }
}


const c = new C();
c.doX(1, 2, 3);
// "A.doX(1)"
// "B.doX(1, 2)"
// "C.doX(1, 2, 3)"
现在,我希望运行这段代码不会有任何问题。 不过,我要好好利用这段时间

为什么??因为我决定重载这个方法,以便同时考虑构造和逻辑

A类总是返回A,B类总是返回B,尽管超级调用实际上返回了一个完全不同的对象,一个新的A。 C返回一个新的C,尽管它已经创建了a和B,但没有对a的引用

那你是做什么的

有几点想法:

将对象的构造从对象中移出,然后将其传入 将数据对象与库分离 那么,让我们尝试构造分离

class Person {
  static make () { return new Person(); }
  setDetails (name, age) {
    this.name = name;
    this.age = age;
  }
  clone (cfg = this) {
    const person = Person.make();
    person.setDetails(cfg.name, cfg.age);
    return person;
  }
}

class Employee extends Person {
  static make () { return new Employee(); }
  setDetails (name, age, id) {
    super.setDetails(name, age);
    this.id = id;
  }
  clone (cfg = this) {
    const employee = Employee.make();
    employee.setDetails(cfg.name, cfg.age, cfg.id);
    return employee;
  }
}
您将注意到克隆方法不是继承的。他们专注于实例化。它们基本上是工厂,实际上是一个独立对象的领域,或者是一个静态方法,比如make | from | of | empty | unit

然后他们调用setDetails,这是一个实例方法,它基本上执行构造函数应该执行的操作,或者工厂应该执行的操作,并且具有继承的行为

说到干,继承是一种可怕的保持这种状态的方式。就从我所写的内容来看,有多少行专门用于覆盖构造函数clone、make或调用父级super,甚至只是担心扩展,仅仅因为

这让我想到了另一种模式:库、纯函数/方法和装饰

如果您不关心实际类型和原始JS,虽然在控制台中很有用,但不应该这样做,因为它在其他地方是无用的,那么您可以创建以数据为中心的对象。 结构,就像您在C、Go、Python等中看到的那样

然后,您就可以自由地编写您可能希望在库/服务上使用的所有可重用计算,这些库/服务用于这些结构或理想情况下用于这些结构的副本

class Vector {
  static make2D (x = 0, y = 0) {
    return { x, y };
  }
  static make3D (x = 0, y = 0, z = 0) {
    return { ...Vector.make2D(x, y), z };
  }
  static add2D (v1, v2) {
    return Vector.make2D(v1.x + v2.x, v1.y + v2.y);
  }
}


const vectors = [
  { x:  0, y:  1 },
  { x: 32, y:  8 },
  { x: 10, y: 12 },
  { x:  0, y:  0 },
];

const vectorSum = vectors.reduce(Vector.add2D, Vector.make2D());
vectorSum; // { x: 42, y: 21 }
如果您真的需要输入,那么您可以执行以下操作:

class Vector {
  add2D (
    {x: x1, y: y1},
    {x: x2, y: y2}
  ) {
    return Vector2D.of(x1 + x2, y1 + y2);
  }
}

class Vector2D {
  constructor (x, y) {
    return Object.assign(this, { x, y });
  }
  static of (x, y) { return new Vector2D(x, y); }
  static from ({ x, y }) { return Vector2D.of(x, y); }
  static empty () { return Vector2D.of(0, 0); }
}

const vector = vectors
  .map(Vector2D.from)
  .reduce(Vector.add2D, Vector2D.empty());

// Vector2D { x: 42, y: 21 }
你很难抱怨你的代码在那一点上不枯燥。你甚至可以把5D矢量输入到输入数据中,你就能得到正确的2D矢量

class Vector {
  add2D (
    {x: x1, y: y1},
    {x: x2, y: y2}
  ) {
    return Vector2D.of(x1 + x2, y1 + y2);
  }
}

class Vector2D {
  constructor (x, y) {
    return Object.assign(this, { x, y });
  }
  static of (x, y) { return new Vector2D(x, y); }
  static from ({ x, y }) { return Vector2D.of(x, y); }
  static empty () { return Vector2D.of(0, 0); }
}

const vector = vectors
  .map(Vector2D.from)
  .reduce(Vector.add2D, Vector2D.empty());

// Vector2D { x: 42, y: 21 }