如何创建一个不使用ES6类从Object.prototype继承的类?

时间:2016-03-11 04:52:32

标签: javascript class null prototype ecmascript-6

我可以使用较旧的语法创建一个不从Object.prototype继承的类。



function Shape(x, y, width, height) {
  this.x = x,
  this.y = y,
  this.width = width,
  this.height = height;
}

Shape.prototype = Object.create(null, {
  constructor: {
    configurable: true,
    writable: true,
    value: Shape
  },
  move: {
    configurable: true,
    writable: true,
    value: function (x, y) {
      this.x += x,
      this.y += y;
    }
  }
});

var rect = new Shape(0, 0, 4, 2);
console.log(Object.getPrototypeOf(rect) === Shape.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(rect)) !== Object.prototype); //inheritance




我怎样才能使用ES6课程?



class Shape {
  constructor(x, y, width, height) {
    this.x = x,
    this.y = y,
    this.width = width,
    this.height = height;
  }

  move(x, y) {
    this.x += x,
    this.y += y;
  }
}

var rect = new Shape(0, 0, 4, 2);
console.log(Object.getPrototypeOf(rect) === Shape.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(rect)) === Object.prototype); // inheritance




2 个答案:

答案 0 :(得分:6)

您可以使用extends null

请注意,类本身仍将继承自Function.prototype,而不是null。所以你将能够在类上使用函数方法。

但请注意,在使用extends子句时,您必须先调用this,然后再调用super,或者不要使用this并返回最后的一个对象。

在这种情况下,您无法使用this初始化super,因为Function.prototype不是构造函数。因此,您必须使用Object.create来创建将成为实例的对象。

class Shape extends null {
  constructor(x, y) {
    // Use `that` instead of `this`, and return it at the end
    var that = Object.create(new.target.prototype);
    that.x = x;
    that.y = y;
    return that;
  }
  move(x, y) {
    this.x += x;
    this.y += y;
  }
}
var rect = new Shape(0, 0);
console.log(rect);
console.log(Object.getPrototypeOf(rect) === Shape.prototype);
console.log(Object.getPrototypeOf(Shape.prototype) === null);
console.log(Object.getPrototypeOf(Shape) === Function.prototype);

new.target将是正在实例化的函数。这可以是Shape本身,也可以是扩展它的另一个函数。这对于允许Shape可扩展非常有用。

class Shape extends null {
  constructor(x, y) {
    // Use `that` instead of `this`, and return it at the end
    var that = Object.create(new.target.prototype);
    that.x = x;
    that.y = y;
    return that;
  }
  move(x, y) {
    this.x += x;
    this.y += y;
  }
}
class BestShape extends Shape {
  constructor(...args) {
    super(...args);
    this.best = true;
  }
}
var rect = new BestShape(0, 0);
console.log(rect);
console.log(Object.getPrototypeOf(rect) === BestShape.prototype);
console.log(Object.getPrototypeOf(BestShape.prototype) === Shape.prototype);
console.log(Object.getPrototypeOf(Shape.prototype) === null);
console.log(Object.getPrototypeOf(BestShape) === Shape);
console.log(Object.getPrototypeOf(Shape) === Function.prototype);

如果您不想避免在构造函数中使用this,另一种方法是扩展prototypenull的函数。缺点是您的类将继承该函数,而不是直接来自Function.prototype

function NullClass() {}
NullClass.prototype = null;

class Shape extends NullClass {
  constructor(x, y) {
    super();
    this.x = x;
    this.y = y;
  }
  move(x, y) {
    this.x += x;
    this.y += y;
  }
}
var rect = new Shape(0, 0);
console.log(rect);
console.log(Object.getPrototypeOf(rect) === Shape.prototype);
console.log(Object.getPrototypeOf(Shape.prototype) === null);
console.log(Object.getPrototypeOf(Shape) === NullClass);
console.log(Object.getPrototypeOf(NullClass) === Function.prototype);

如果您不想重复使用NullClass,可以将其定义为内联

class Shape extends Object.assign(function(){},{prototype:null}) { /* ... */ }

答案 1 :(得分:3)

您必须手动将Shape.prototype的原型设置为null

class Shape {
  constructor(x, y, width, height) {
    this.x = x,
    this.y = y,
    this.width = width,
    this.height = height;
  }
    
  move(x, y) {
    this.x += x,
    this.y += y;
  }
}

// This is the key line.
Object.setPrototypeOf(Shape.prototype, null);

const rect = new Shape(0, 0, 4, 2);
console.log(Object.getPrototypeOf(rect) === Shape.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(rect)) !== Object.prototype);