この翻訳は不完全です。英語から この記事を翻訳 してください。

Object.create() メソッドは、既存のオブジェクトを新しく生成されるオブジェクトのプロトタイプとして使用して、新しいオブジェクトを生成します。

構文

Object.create(proto[, propertiesObject])

引数

proto
新たに生成されるオブジェクトのプロトタイプになるべきオブジェクトです。
propertiesObject
省略可能。指定されていて、 undefined でない場合、それ自身が所有する一連の列挙可能なプロパティ ( own property — つまり、それ自身に定義されていて、プロトタイプチェインの中では列挙可能でないプロパティ) が、それらのプロパティ名を伴う一連のプロパティ記述子を指定し、新たに生成されるオブジェクトに追加されることになります。これらのプロパティは、 Object.defineProperties() の2番目の引数に対応するものです。

返値

指定したプロトタイプオブジェクトとプロパティを持つ新しいオブジェクトです。

例外

proto 引数が null かオブジェクトではない場合、 TypeError 例外が発生します。

Object.create() を用いた伝統的な継承

以下の例は、伝統的な継承をするための Object.create() の使用方法です。これは、すべての JavaScript が対応している単一継承です。

// 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);
Rectangle.prototype.constructor = Rectangle;

var 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); // Outputs, 'Shape moved.'

複数のオブジェクトから継承したい場合は、ミックスインが可能です。

function MyClass() {
  SuperClass.call(this);
  OtherSuperClass.call(this);
}

// inherit one class
MyClass.prototype = Object.create(SuperClass.prototype);
// mixin another
Object.assign(MyClass.prototype, OtherSuperClass.prototype);
// re-assign constructor
MyClass.prototype.constructor = MyClass;

MyClass.prototype.myMethod = function() {
  // do something
};

Object.assign() は OtherSuperClass プロトタイプから MyClass プロトタイプへプロパティをコピーし、 MyClass のすべてのインスタンスで利用できるようにします。 Object.assign() は ES2015 で導入され、ポリフィルを利用することができます。古いブラウザーへの対応が必要な場合は、 jQuery.extend() または _.assign() を利用することができます。

Object.create() と一緒に propertiesObject 引数の使用

var o;

// create an object with null as prototype
o = Object.create(null);


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


// Example where we create an object with a couple of
// sample properties. (Note that the second parameter
// maps keys to *property descriptors*.)
o = Object.create(Object.prototype, {
  // foo is a regular 'value property'
  foo: {
    writable: true,
    configurable: true,
    value: 'hello'
  },
  // bar is a getter-and-setter (accessor) property
  bar: {
    configurable: false,
    get: function() { return 10; },
    set: function(value) {
      console.log('Setting `o.bar` to', value);
    }
/* with ES2015 Accessors our code can look like this
    get() { return 10; },
    set(value) {
      console.log('Setting `o.bar` to', value);
    } */
  }
});


function Constructor() {}
o = new Constructor();
// is equivalent to:
o = Object.create(Constructor.prototype);
// Of course, if there is actual initialization code
// in the Constructor function, 
// the Object.create() cannot reflect it


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

// by default properties ARE NOT writable,
// enumerable or configurable:
o.p = 24;
o.p;
// 42

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

delete o.p;
// false

// to specify an ES3 property
o2 = Object.create({}, {
  p: {
    value: 42,
    writable: true,
    enumerable: true,
    configurable: true
  }
});

カスタムオブジェクトと Null オブジェクト

A new object created from a completely custom object (especially one created from the null object, which is basically a custom object with NO members) can behave in unexpected ways. This is especially true when debugging, since common object-property converting/detecting utility functions may generate errors, or simply lose information (especially if using silent error-traps that ignore errors). For example, here are two objects:

oco = Object.create( {} );   // create a normal object
ocn = Object.create( null ); // create a "null" object

> console.log(oco) // {} -- Seems normal
> console.log(ocn) // {} -- Seems normal here too, so far

oco.p = 1; // create a simple property on normal obj
ocn.p = 0; // create a simple property on "null" obj

> console.log(oco) // {p: 1} -- Still seems normal
> console.log(ocn) // {p: 0} -- Still seems normal here too. BUT WAIT...


As shown above, all seems normal so far. However, when attempting to actually use these objects, their differences quickly become apparent:

> "oco is: " + oco // shows "ocn is: [object Object]"

> "ocn is: " + ocn // throws error: Cannot convert object to primitive value


Testing just a few of the many most basic built-in functions shows the magnitude of the problem more clearly:

> alert(oco) // shows [object Object]
> alert(ocn) // throws error: Cannot convert object to primitive value

> oco.toString() // shows [object Object]
> ocn.toString() // throws error: ocn.toString is not a function

> oco.valueOf() // shows {}
> ocn.valueOf() // throws error: ocn.valueOf is not a function

> oco.hasOwnProperty("p") // shows "true"
> ocn.hasOwnProperty("p") // throws error: ocn.hasOwnProperty is not a function

> oco.constructor // shows "Object() { [native code] }"
> ocn.constructor // shows "undefined"


As said, these differences can make debugging even simple-seeming problems quickly go astray. For example:

A simple common debugging function:

// display top-level property name:value pairs of given object
function ShowProperties( b ){
  for( var i in b ){  console.log( i + ": " + b[i] + "\n" )  }
}


Not such simple results: (especially if silent error-trapping had hidden the error messages)

ob={}; ob.po=oco; ob.pn=ocn; // create a compound object using the test objects from above as property values

> ShowProperties( ob ) // display top-level properties
- po: [object Object]
- Error: Cannot convert object to primitive value

Note that only first property gets shown.


(But if same object is created simply in different order -- at least in some implementations...)

ob={}; ob.pn=ocn; ob.po=oco; // create same compound object again, but create same properties in different order

> ShowProperties( ob ) // display top-level properties
- Error: Cannot convert object to primitive value

Note that neither property gets shown.

Note that such a different order may arise statically via disparate fixed codings such as here, but also dynamically via whatever the order any such property-adding code-branches actually get executed at runtime as depends on inputs and/or random-variables. Then again, the actual iteration order is not guaranteed no matter what the order members are added.

Some NON-solutions

A good solution for the missing object-methods is not immediately apparent.

Adding the missing object-method directly from the standard-object does NOT work:

ocn = Object.create( null ); // create "null" object (same as before)

ocn.toString = Object.toString; // since new object lacks method then try assigning it directly from standard-object

> ocn.toString // shows "toString() { [native code] }" -- missing method seems to be there now
> ocn.toString == Object.toString // shows "true" -- method seems to be same as the standard object-method

> ocn.toString() // error: Function.prototype.toString requires that 'this' be a Function


Adding the missing object-method directly to new object's "prototype" does not work either, since new object does not have a real prototype (which is really the cause of ALL these problems) and one cannot be directly added:

ocn = Object.create( null ); // create "null" object (same as before)

ocn.prototype.toString = Object.toString; // Error: Cannot set property 'toString' of undefined

ocn.prototype = {};                       // try to create a prototype
ocn.prototype.toString = Object.toString; // since new object lacks method then try assigning it from standard-object  

> ocn.toString() // error: ocn.toString is not a function


Adding the missing object-method by using the standard-object as new object's prototype does not work either:

ocn = Object.create( null );        // create "null" object (same as before) 
Object.setPrototypeOf(ocn, Object); // set new object's prototype to the standard-object

> ocn.toString() // error: Function.prototype.toString requires that 'this' be a Function

Some OK solutions

Again, adding the missing object-method directly from the standard-object does NOT work. However, adding the generic method directly, DOES:

ocn = Object.create( null ); // create "null" object (same as before)

ocn.toString = toString; // since new object lacks method then assign it directly from generic version

> ocn.toString() // shows "[object Object]"
> "ocn is: " + ocn // shows "ocn is: [object Object]"


ob={}; ob.pn=ocn; ob.po=oco; // create a compound object (same as before)

> ShowProperties(ob) // display top-level properties
- po: [object Object]
- pn: [object Object]

However, setting the generic prototype as the new object's prototype works even better:

ocn = Object.create( null );                  // create "null" object (same as before)
Object.setPrototypeOf(ocn, Object.prototype); // set new object's prototype to the "generic" object (NOT standard-object)

(In addition to all the string-related functions shown above, this also adds:)

> ocn.valueOf() // shows {}
> ocn.hasOwnProperty("x") // shows "false"
> ocn.constructor // shows "Object() { [native code] }"

// ...and all the rest of the properties and methods of Object.prototype.

As shown, objects modified this way now look very much like ordinary objects.

Polyfill

このポリフィルは、プロトタイプは選択されたが第二引数を考慮しない状況向けに、新規オブジェクトを生成する主要な利用法に対応します。

実際の ES5 の Object.create では、[[Prototype]] として null を設定することがサポートされていますが、このポリフィルは ECMAScript5 以前のサポートをする制約上、null を使用できないことに注意してください。

 if (typeof Object.create !== "function") {
    Object.create = function (proto, propertiesObject) {
        if (typeof proto !== 'object' && typeof proto !== 'function') {
            throw new TypeError('Object prototype may only be an Object: ' + proto);
        } else if (proto === null) {
            throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument.");
        }

        if (typeof propertiesObject != 'undefined') {
            throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument.");
        }

        function F() {}
        F.prototype = proto;

        return new F();
    };
}

仕様書

仕様書 状態 備考
ECMAScript 5.1 (ECMA-262)
Object.create の定義
標準 初回定義。JavaScript 1.8.5 で実装。
ECMAScript 2015 (6th Edition, ECMA-262)
Object.create の定義
標準  
ECMAScript Latest Draft (ECMA-262)
Object.create の定義
ドラフト  

ブラウザーの対応

Update compatibility data on GitHub
デスクトップモバイルサーバー
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewAndroid 版 ChromeEdge MobileAndroid 版 FirefoxAndroid 版 OperaiOS 版 SafariSamsung InternetNode.js
基本対応Chrome 完全対応 5Edge 完全対応 ありFirefox 完全対応 4IE 完全対応 9Opera 完全対応 11.6Safari 完全対応 5WebView Android 完全対応 ありChrome Android 完全対応 ありEdge Mobile 完全対応 ありFirefox Android 完全対応 4Opera Android 完全対応 11.5Safari iOS 完全対応 ありSamsung Internet Android 完全対応 ありnodejs 完全対応 あり

凡例

完全対応  
完全対応

関連情報

ドキュメントのタグと貢献者

このページの貢献者: mfuji09, segayuu, tomouchi, YuichiNukiyama, teoli, mokeke, ethertank, yyss
最終更新者: mfuji09,