--- title: Object.create() slug: Web/JavaScript/Reference/Global_Objects/Object/create translation_of: Web/JavaScript/Reference/Global_Objects/Object/create ---
Object.create()
指定其原型物件與屬性,創建一個新物件。
Object.create(proto[, propertiesObject])
proto
propertiesObject
enumerable
特性 ) 對應其屬性名稱,根據其屬性敘述元 (property descriptors) 加進新創建的物件。這些屬性對應到 {{jsxref("Object.defineProperties()")}} 的第二個參數。具有指定原型物件與屬性的新物件。
如果 proto
參數不是 {{jsxref("null")}} 或一個物件,將會拋出 {{jsxref("TypeError")}} 例外。
Object.create()
實現類別繼承下方是如何使用 Object.create()
去實現類別繼承的示範,此為 JavaScript 支援的單一繼承.。
// Shape - 父類別 function Shape() { this.x = 0; this.y = 0; } // 父類別的方法 Shape.prototype.move = function(x, y) { this.x += x; this.y += y; console.info('Shape moved.'); }; // Rectangle - 子類別 function Rectangle() { Shape.call(this); // call super constructor. } // 子類別擴展(extends)父類別 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.'
也可像 mixin 繼承多個物件。
function MyClass() { SuperClass.call(this); OtherSuperClass.call(this); } // 繼承一個父類別 MyClass.prototype = Object.create(SuperClass.prototype); // mixin另一個父類別 Object.assign(MyClass.prototype, OtherSuperClass.prototype); // 重新指定建構式 MyClass.prototype.constructor = MyClass; MyClass.prototype.myMethod = function() { // do a thing };
Object.assign 複製 OtherSuperClass 原型上的所有屬性到 MyClass 的原型上,使所有 MyClass 的實例都能使用。Object.assign 為 ES2015 標準且有 polyfill。如需支援較舊的瀏覽器,可使用第三方套件實現如 jQuery.extend() 或 _.assign() 。
propertiesObject
參數的使用var o; // 建立以null為原型的物件 o = Object.create(null); o = {}; // 等同於: 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 為數值屬性 foo: { writable: true, configurable: true, value: 'hello' }, // bar 為 getter-and-setter 訪問屬性 bar: { configurable: false, get: function() { return 10; }, set: function(value) { console.log('Setting `o.bar` to', value); } /* with ES5 Accessors our code can look like this get function() { return 10; }, set function(value) { console.log('setting `o.bar` to', value); } */ } }); function Constructor() {} o = new Constructor(); // 等同於: o = Object.create(Constructor.prototype); // Of course, if there is actual initialization code in the // Constructor function, the Object.create() cannot reflect it // 創建一個新物件,指定原型是全新的空物件,並加入值為 42 的屬性'p' o = Object.create({}, { p: { value: 42 } }); // 屬性敘述元 writable, enumerable , configurable 未定義,預設皆為 false 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 } });
此 polyfill 涵蓋了主要的使用情境:指定一個原型創建一個新的物件,第二個參數為選用。
要注意的是在 ES5 的Object.create
中, [[Prototype]]
可以為 null
,但在ECMAScript 5 以前的版本,polyfill 會因為繼承限制( limitation inherent )而不支援此情形。
if (typeof Object.create !== "function") {
Object.create = function (proto, propertiesObject) {
if (!(proto === null || typeof proto === "object" || typeof proto === "function")) {
throw TypeError('Argument must be an object, or null');
}
var temp = new Object();
temp.__proto__ = proto;
if(typeof propertiesObject === "object")
Object.defineProperties(temp, propertiesObject);
return temp;
};
}