object.create(proto, propertiesObject)
object.create()
是使用指定的原型proto
對象及其屬性propertiesObject
去創建一個新的對象。(mdn)
-
proto
是必填參數,就是新創建出來的對象的原型 (新對象的__proto__
屬性指向的對象),值得注意的是當proto
為null
的時候創建的新對象完全是一個空對象,沒有原型(圖一),也就是沒有繼承Object.prototype
上的方法。(如hasOwnProperty()
toString()
等)圖1 -
propertiesObject
是可選參數,作用就是給新對象添加新屬性以及描述器(圖2),具體可參考 Object.defineProperties() - mdn 的第二個參數。需要注意的是新添加的屬性是新對象自身具有的屬性也就是通過hasOwnProperty()
方法可以獲取到的屬性,而不是添加在原型對象里。(圖3)
圖2
圖3
具體三個步驟就是:
- 創建一個對象
- 繼承指定父對象
- 為新對象擴展新屬性
自己實現一個Object.create()
:
Object.myCreate = function (obj, properties) {
var F = function () {}
F.prototype = obj
if (properties) {
Object.defineProperties(F, properties)
}
return new F()
}
Object.myCreate({}, {a: {value: 1}}) // {a: 1}
new Object()
-
new
運算符是創建一個自定義對象或者具有構造函數的內置對象的實例mdn - 使用
new
運算符會創建一個新的對象,它繼承自構造函數的prototype
,也就是說它的__proto__
屬性會指向構造函數的prototype
-
new Object()
也就是具有構造函數的內置Object的實例,新創建的對象的__proto__
屬性會指向Object的prototype
擴展:實例復現new的構造過程:
var objectFactory = function () {
var obj = new Object() // 從Object.prototype上克隆一個空對象 此時 __proto__ 指向Object.prototype
var Constructor = [].shift.call(arguments) //取得構造器
obj.__proto__ = Constructor.prototype // 指向構造器的prototype
var ret = Constructor.apply(obj, arguments)
return typeof ret === 'object' ? ret : obj
}
function Person (name) {
this.name = name
}
Person.prototype.getName = function () {
return this.name
}
var a = objectFactory(Person, 'nancy')
console.log(a.name) // nancy
console.log(a.getName) //nancy
console.log(Object.getPrototypeOf(a) === Person.protoType) //true
總結區別
-
Object.cerate()
必須接收一個對象參數,創建的新對象的原型指向接收的參數對象,new Object() 創建的新對象的原型指向的是 Object.prototype. (表述有點啰嗦,簡潔點說就是前者繼承指定對象, 后者繼承內置對象Object) - 可以通過
Object.create(null)
創建一個干凈的對象,也就是沒有原型,而new Object()
創建的對象是 Object的實例,原型永遠指向Object.prototype
.