Object.create()

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

¥The Object.create() static method creates a new object, using an existing object as the prototype of the newly created object.

Try it

语法

¥Syntax

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

参数

¥Parameters

proto

该对象应该是新创建对象的原型。

propertiesObject Optional

如果指定但未指定 undefined,则为一个对象,其 可枚举自己的属性 指定要添加到新创建的对象的属性描述符,并具有相应的属性名称。这些属性对应于 Object.defineProperties() 的第二个参数。

返回值

¥Return value

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

¥A new object with the specified prototype object and properties.

例外情况

¥Exceptions

TypeError

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

示例

¥Examples

使用 Object.create() 进行经典继承

¥Classical inheritance with Object.create()

下面是一个如何使用 Object.create() 实现经典继承的例子。这是针对单一继承的,这是 JavaScript 支持的全部。

¥Below is an example of how to use Object.create() to achieve classical inheritance. This is for a single inheritance, which is all that JavaScript supports.

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 语法。

¥Note that there are caveats to watch out for using create(), such as re-adding the constructor property to ensure proper semantics. Although Object.create() is believed to have better performance than mutating the prototype with Object.setPrototypeOf(), the difference is in fact negligible if no instances have been created and property accesses haven't been optimized yet. In modern code, the class syntax should be preferred in any case.

将 propertiesObject 参数与 Object.create()一起使用

¥Using propertiesObject argument with Object.create()

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

¥Object.create() allows fine-tuned control over the object creation process. The object initializer syntax is, in fact, a syntax sugar of Object.create(). With Object.create(), we can create objects with a designated prototype and also some properties. Note that the second parameter maps keys to property descriptors — this means you can control each property's enumerability, configurability, etc. as well, which you can't do in object initializers.

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__ 键。

¥With Object.create(), we can create an object with null as prototype. The equivalent syntax in object initializers would be the __proto__ key.

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

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

¥By default properties are not writable, enumerable or configurable.

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

¥To specify a property with the same attributes as in an initializer, explicitly specify writable, enumerable and configurable.

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 运算符的行为。

¥You can use Object.create() to mimic the behavior of the new operator.

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

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

¥Of course, if there is actual initialization code in the Constructor function, the Object.create() method cannot reflect it.

规范

Specification
ECMAScript Language Specification
# sec-object.create

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看