在vue和vuex源码中看到有使用Object.create(null) 创建对象的代码,有点疑惑为什么要使用Object.create(null),而不是{}?这两种方式创建的对象有什么区别?
一、Object.create(null) 和 {} 的区别
var obj1 = {};
console.log(obj1); // {}
console.log(Object.getPrototypeOf(obj1)); // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
console.log(Object.getPrototypeOf(obj1) === Object.prototype); // true
var obj2 = Object.create(null);
console.log(obj2); // {}
console.log(Object.getPrototypeOf(obj2)); // null
console.log(obj2.__proto__); // undefined
从运行结果可以看到这两种方式创建的对象,虽然形式上都是{},但是它们各自的原型对象却是不一样的。
使用字面量形式赋值,相当于var obj1 = new Object(),原型指向Object.prototype,会继承Object的属性和方法。例如:toString方法等。
使用Object.create(null)创建的对象,其原型指向null。null作为原型链的顶端,没有也不会继承任何属性和方法。
二、Object.create()
Object.create()方法会创建一个新对象,可以指定新对象的原型,且可以选择性的指定对象的属性。
1、语法
Object.create(proto, [propertiesObject]);
proto:新创建对象的原型对象。
propertiesObject:可选。新创建对象的可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)。
2、示例
var _proto = {
getName: function (){
console.log('this is _proto');
}
}
var obj = Object.create(_proto, {
name: {value: 'obj'},
age: {value: 23}
});
这里用Object.create()方法创建了一个对象,创建的对象如下图所示:创建了一个对象,该对象的属性和__proto__都通过Object.create()的参数来设置。
3、应用
Object.create() 更常见的是在面向对象中做继承。这里只贴出来代码,不做详细分析了。不清楚的可以了解下面向对象的继承。
var People = function (name){
this.name = name;
};
People.prototype.sayName = function (){
console.log(this.name);
}
function Person(name, age){
this.age = age;
People.call(this, name); // 使用call,实现了People属性的继承
};
// 使用Object.create()方法,实现People原型方法的继承,并且修改了constructor指向
Person.prototype = Object.create(People.prototype, {
constructor: {
configurable: true,
enumerable: true,
value: Person,
writable: true
}
});
Person.prototype.sayAge = function (){
console.log(this.age);
}
var p1 = new Person('person1', 25);
p1.sayName(); //'person1'
p1.sayAge(); //25
三、总结
在vue中之所以用Object.create()方法创建对象,我个人认为,可能有这几种考虑:
1、使用Object.create(null)创建的对象,是一个完全空白的对象,不会继承任何属性和方法,在后续使用中不需要考虑命名冲突的问题。
2、重写对象的原型方法或者给对象添加新方法,能够保证后续调用时代码风格的统一。