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

时间:2021-01-23 18:55:22

I can create a class that does not inherit from Object.prototype using the older syntax.

我可以使用旧语法创建一个不从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

How can I do this using ES6 classes?

我怎样才能使用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 个解决方案

#1


6  

You can use extends null.

您可以使用extends null。

Note the class itself will still inherit from Function.prototype, not from null. So you will be able to use function methods on the class.

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

But be aware that, when using an extends clause, you must either initialize this before using it by calling super, or don't use this and return an object at the end.

但请注意,在使用extends子句时,必须先通过调用super来初始化它,或者不要使用它并在最后返回一个对象。

In this case you can't initialize this using super because Function.prototype is not a constructor. So you will have to use Object.create to create the object that will become the instance.

在这种情况下,您无法使用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 will be the function that is being instantiated. This can be Shape itself, or another function that extends it. This is useful to allow Shape to be extendable.

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);

If you don't want to avoid using this in your constructor, an alternative is extending a function whose prototype is null. The downside is that your class will inherit from that function, instead of directly from Function.prototype.

如果您不想避免在构造函数中使用它,则另一种方法是扩展其原型为null的函数。缺点是您的类将继承该函数,而不是直接从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);

If you don't want to reuse NullClass, you can define it inline

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

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

#2


3  

You will have to manually set Shape.prototype's prototype to null.

您必须手动将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);

#1


6  

You can use extends null.

您可以使用extends null。

Note the class itself will still inherit from Function.prototype, not from null. So you will be able to use function methods on the class.

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

But be aware that, when using an extends clause, you must either initialize this before using it by calling super, or don't use this and return an object at the end.

但请注意,在使用extends子句时,必须先通过调用super来初始化它,或者不要使用它并在最后返回一个对象。

In this case you can't initialize this using super because Function.prototype is not a constructor. So you will have to use Object.create to create the object that will become the instance.

在这种情况下,您无法使用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 will be the function that is being instantiated. This can be Shape itself, or another function that extends it. This is useful to allow Shape to be extendable.

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);

If you don't want to avoid using this in your constructor, an alternative is extending a function whose prototype is null. The downside is that your class will inherit from that function, instead of directly from Function.prototype.

如果您不想避免在构造函数中使用它,则另一种方法是扩展其原型为null的函数。缺点是您的类将继承该函数,而不是直接从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);

If you don't want to reuse NullClass, you can define it inline

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

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

#2


3  

You will have to manually set Shape.prototype's prototype to null.

您必须手动将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);