此文首發於 lijing0906.github.iojavascript
平時代碼中一定會使用對象,一般是用最直接的字面量方法建立var obj = {}
,最近在整理JS繼承方式時遇到Object.create()
也能夠建立對象,另外,也能夠用new Object()
關鍵字建立。 那這三種方式有差異嗎?java
var objA = {};
objA.name = 'a';
objA.sayName = function() {
console.log(`My name is ${this.name} !`);
}
// var objA = {
// name: 'a',
// sayName: function() {
// console.log(`My name is ${this.name} !`);
// }
// }
objA.sayName();
console.log(objA.__proto__ === Object.prototype); // true
console.log(objA instanceof Object); // true
複製代碼
var objB = new Object();
// var objB = Object();
objB.name = 'b';
objB.sayName = function() {
console.log(`My name is ${this.name} !`);
}
objB.sayName();
console.log(objB.__proto__ === Object.prototype); // true
console.log(objB instanceof Object); // true
複製代碼
在JS的指向問題中講new綁定時講了new
操做符其實作了如下四步:git
var obj = new Object(); // 建立一個空對象
obj.__proto__ = F.prototype; // obj的__proto__指向構造函數的prototype
var result = F.call(obj); // 把構造函數的this指向obj,並執行構造函數把結果賦值給result
if (typeof(result) === 'object') {
objB = result; // 構造函數F的執行結果是引用類型,就把這個引用類型的對象返回給objB
} else {
objB = obj; // 構造函數F的執行結果是值類型,就返回obj這個空對象給objB
}
複製代碼
這樣一比較,其實字面量建立和new關鍵字建立並無區別,建立的新對象的__proto__
都指向Object.prototype
,只是字面量建立更高效一些,少了__proto__
指向賦值和this
。github
Object.create()
方法建立一個新對象,使用現有的對象來提供新建立的對象的__proto__
。 MDN函數
const person = {
isHuman: false,
printIntroduction: function () {
console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
}
};
const me = Object.create(person); // me.__proto__ === person
me.name = "Matthew"; // name屬性被設置在新對象me上,而不是現有對象person上
me.isHuman = true; // 繼承的屬性能夠被重寫
me.printIntroduction(); // My name is Matthew. Am I human? true
複製代碼
Object.create(proto[, propertiesObject])post
proto
必填參數,是新對象的原型對象,如上面代碼裏新對象me
的__proto__
指向person
。注意,若是這個參數是null
,那新對象就不折不扣是個空對象,沒有繼承Object.prototype
上的任何屬性和方法,如hasOwnProperty()、toString()
等。var a = Object.create(null);
console.dir(a); // {}
console.log(a.__proto__); // undefined
console.log(a.__proto__ === Object.prototype); // false
console.log(a instanceof Object); // false 沒有繼承`Object.prototype`上的任何屬性和方法,因此原型鏈上不會出現Object
複製代碼
propertiesObject
是可選參數,指定要添加到新對象上的可枚舉的屬性(即其自定義的屬性和方法,可用hasOwnProperty()
獲取的,而不是原型對象上的)的描述符及相應的屬性名稱。var bb = Object.create(null, {
a: {
value: 2,
writable: true,
configurable: true
}
});
console.dir(bb); // {a: 2}
console.log(bb.__proto__); // undefined
console.log(bb.__proto__ === Object.prototype); // false
console.log(bb instanceof Object); // false 沒有繼承`Object.prototype`上的任何屬性和方法,因此原型鏈上不會出現Object
// ----------------------------------------------------------
var cc = Object.create({b: 1}, {
a: {
value: 3,
writable: true,
configurable: true
}
});
console.log(cc); // {a: 3}
console.log(cc.hasOwnProperty('a'), cc.hasOwnProperty('b')); // true false 說明第二個參數設置的是新對象自身可枚舉的屬性
console.log(cc.__proto__); // {b: 1} 新對象cc的__proto__指向{b: 1}
console.log(cc.__proto__ === Object.protorype); // false
console.log(cc instanceof Object); // true cc是對象,原型鏈上確定會出現Object
複製代碼
Object.create()
建立的對象的原型指向傳入的對象。跟字面量和new
關鍵字建立有區別。ui
Object.mycreate = function(proto, properties) {
function F() {};
F.prototype = proto;
if(properties) {
Object.defineProperties(F, properties);
}
return new F();
}
var hh = Object.mycreate({a: 11}, {mm: {value: 10}});
console.dir(hh);
複製代碼
new
關鍵字建立的對象是Object
的實例,原型指向Object.prototype
,繼承內置對象Object
Object.create(arg, pro)
建立的對象的原型取決於arg
,arg
爲null
,新對象是空對象,沒有原型,不繼承任何對象;arg
爲指定對象,新對象的原型指向指定對象,繼承指定對象