JavaScript深刻理解對象方法——Object.create()

Object.create()

Object.create() 方法會使用指定的原型對象及其屬性去建立一個新的對象。segmentfault

語法

Object.create(proto[, propertiesObject])
  • proto
    新建立對象的原型對象。
  • propertiesObject
    可選。若是沒有指定爲 undefined,則是要添加到新建立對象的可枚舉屬性(即其自身定義的屬性,而不是其原型鏈上的枚舉屬性)對象的屬性描述符以及相應的屬性名稱。這些屬性對應Object.defineProperties()的第二個參數。

返回值

在指定原型對象上添加新屬性後的對象。瀏覽器

例外

若是propertiesObject參數不是 null 或一個對象,則拋出一個 TypeError 異常。函數

例子

Object.create實現類式繼承

下面的例子演示瞭如何使用Object.create()來實現類式繼承。這是一個全部版本JavaScript都支持的單繼承。this

// 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.'

若是你但願能繼承到多個對象,則能夠使用混入的方式。prototype

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 a thing
};

Object.assign 會把 OtherSuperClass原型上的函數拷貝到 MyClass原型上,使 MyClass 的全部實例均可用 OtherSuperClass 的方法。Object.assign 是在 ES2015 引入的,且可用 polyfilled。要支持舊瀏覽器的話,可用使用 jQuery.extend() 或者 _.assign()。code

使用 Object.createpropertyObject參數

var o;

// 建立一個原型爲null的空對象
o = Object.create(null);


o = {};
// 以字面量方式建立的空對象就至關於:
o = Object.create(Object.prototype);


o = Object.create(Object.prototype, {
  // foo會成爲所建立對象的數據屬性
  foo: { 
    writable:true,
    configurable:true,
    value: "hello" 
  },
  // bar會成爲所建立對象的訪問器屬性
  bar: {
    configurable: false,
    get: function() { return 10 },
    set: function(value) {
      console.log("Setting `o.bar` to", value);
    }
  }
});


function Constructor(){}
o = new Constructor();
// 上面的一句就至關於:
o = Object.create(Constructor.prototype);
// 固然,若是在Constructor函數中有一些初始化代碼,Object.create不能執行那些代碼


// 建立一個以另外一個空對象爲原型,且擁有一個屬性p的對象
o = Object.create({}, { p: { value: 42 } })

// 省略了的屬性特性默認爲false,因此屬性p是不可寫,不可枚舉,不可配置的:
o.p = 24
o.p
//42

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

delete o.p
//false

//建立一個可寫的,可枚舉的,可配置的屬性p
o2 = Object.create({}, {
  p: {
    value: 42, 
    writable: true,
    enumerable: true,
    configurable: true 
  } 
});

Polyfill

這個 polyfill 涵蓋了主要的應用場景,它建立一個已經選擇了原型的新對象,但沒有把第二個參數考慮在內。對象

請注意,儘管在 ES5 中 Object.create支持設置爲[[Prototype]]null,但由於那些ECMAScript5之前版本限制,此 polyfill 沒法支持該特性。繼承

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;
    };
}
相關文章
相關標籤/搜索