Object.create()

**Object.create()** 静态方法创建一个新对象,使用现有对象作为新创建对象的原型。

试一试

语法

js
Object.create(proto)
Object.create(proto, propertiesObject)

参数

proto

应作为新创建对象原型的对象。

propertiesObject 可选

如果指定且不为 undefined,则其 可枚举自身属性 指定要添加到新创建对象的属性描述符,以及相应的属性名称。这些属性对应于 Object.defineProperties() 的第二个参数。

返回值

具有指定原型对象和属性的新对象。

异常

TypeError

如果 proto 既不是 null 也不是 Object,则抛出此异常。

示例

使用 Object.create() 实现经典继承

以下是如何使用 Object.create() 实现经典继承的示例。这适用于单一继承,这是 JavaScript 支持的全部继承方式。

js
// Shape - superclass
function Shape() {
  this.x = 0;
  this.y = 0;
}

// superclass method
Shape.prototype.move = function (x, y) {
  this.x += x;
  this.y += y;
  console.info("Shape moved.");
};

// Rectangle - subclass
function Rectangle() {
  Shape.call(this); // call super constructor.
}

// subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype, {
  // If you don't set Rectangle.prototype.constructor to Rectangle,
  // it will take the prototype.constructor of Shape (parent).
  // To avoid that, we set the prototype.constructor to Rectangle (child).
  constructor: {
    value: Rectangle,
    enumerable: false,
    writable: true,
    configurable: true,
  },
});

const rect = new Rectangle();

console.log("Is rect an instance of Rectangle?", rect instanceof Rectangle); // true
console.log("Is rect an instance of Shape?", rect instanceof Shape); // true
rect.move(1, 1); // Logs 'Shape moved.'

请注意,使用 create() 时需要注意一些问题,例如重新添加 constructor 属性以确保正确的语义。尽管人们认为 Object.create() 的性能优于使用 Object.setPrototypeOf() 修改原型,但如果尚未创建任何实例且尚未优化属性访问,则差异实际上可以忽略不计。在现代代码中,无论如何都应优先使用 class 语法。

使用 Object.create() 的 propertiesObject 参数

Object.create() 允许对对象创建过程进行微调控制。事实上,对象初始化器语法Object.create() 的语法糖。使用 Object.create(),我们可以创建具有指定原型和一些属性的对象。请注意,第二个参数将键映射到属性描述符——这意味着您还可以控制每个属性的可枚举性、可配置性等,而这在对象初始化器中是无法做到的。

js
o = {};
// Is equivalent to:
o = Object.create(Object.prototype);

o = Object.create(Object.prototype, {
  // foo is a regular data property
  foo: {
    writable: true,
    configurable: true,
    value: "hello",
  },
  // bar is an accessor property
  bar: {
    configurable: false,
    get() {
      return 10;
    },
    set(value) {
      console.log("Setting `o.bar` to", value);
    },
  },
});

// Create a new object whose prototype is a new, empty
// object and add a single property 'p', with value 42.
o = Object.create({}, { p: { value: 42 } });

使用 Object.create(),我们可以创建原型为 null 的对象。对象初始化器中的等效语法是 __proto__ 键。

js
o = Object.create(null);
// Is equivalent to:
o = { __proto__: null };

默认情况下,属性不可写不可枚举不可配置

js
o.p = 24; // throws in strict mode
o.p; // 42

o.q = 12;
for (const prop in o) {
  console.log(prop);
}
// 'q'

delete o.p;
// false; throws in strict mode

要指定与初始化器中属性具有相同属性的属性,请显式指定 writableenumerableconfigurable

js
o2 = Object.create(
  {},
  {
    p: {
      value: 42,
      writable: true,
      enumerable: true,
      configurable: true,
    },
  },
);
// This is not equivalent to:
// o2 = Object.create({ p: 42 })
// which will create an object with prototype { p: 42 }

您可以使用 Object.create() 模拟 new 运算符的行为。

js
function Constructor() {}
o = new Constructor();
// Is equivalent to:
o = Object.create(Constructor.prototype);

当然,如果 Constructor 函数中存在实际的初始化代码,则 Object.create() 方法无法反映它。

规范

规范
ECMAScript 语言规范
# sec-object.create

浏览器兼容性

BCD 表格仅在启用 JavaScript 的浏览器中加载。

另请参阅