Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
语法
js
复制代码
// 返回一个新对象,带着指定的原型对象和属性。
Object.create(proto,[propertiesObject])
- proto:新创建对象的原型对象,必须为
null或者原始包装对象,否则会抛出异常 - propertiesObject:可选参数,需要是一个对象,该传入对象的自有可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)将为新创建的对象添加指定的属性值和对应的属性描述符
不传递propertiesObject
js
复制代码
const obj = {
name: 'nordon'
};
const newObj = Object.create(obj);
此时打印newObj只是一个{},传递的obj会当作newObj的原型,此时name属性属于newObj.prototype上的属性,并不是obj.name
传递propertiesObject
js
复制代码
const obj = {
name: "nordon",
};
const newObj = Object.create(obj, {
name: {
value: "wy",
writable: true,
configurable: true,
enumerable: true
},
age: {
value: 12,
writable: true,
configurable: true,
enumerable: true
},
});
此时newObj为
js
复制代码
{
name: 'wy',
age: 12
}
优势
为何要使用Object.create创建对象,而不直接使用对象字面量的形式或者使用Object创建对象呢?
js
复制代码
const obj = {
name: "nordon",
};
const newObj = Object.create(obj);
const nweObj2 = Object(obj);
将obj、newObj、newObj2依次打印
通过输出可以看到通过字面量和使用Object创建的对象是一致的,且其引用地址是一致的:obj === newObj2为true
通过Object.create创建的对象会在obj和newObj之间增加一层,这个时候引用地址是解耦的:obj === newObj为false,这样的好处可以保证新创建的对象和原有对象解耦,当我们操作newObj时并不会影响原有数据
应用
利用Object.create实现继承
js
复制代码
function Person(name) {
this.name = name;
this.permission = ["user", "salary", "vacation"];
}
Person.prototype.say = function () {
console.log(`${this.name} 说话了`);
};
function Staff(name, age) {
Person.call(this, name);
this.age = age;
}
Staff.prototype = Object.create(Person.prototype, {
constructor: {
// 若是不将Staff constructor指回到Staff, 此时的Staff实例zs.constructor则指向Person
value: Staff,
},
});
Staff.prototype.eat = function () {
console.log("吃东西啦~~~");
};
创建一个干净的对象,第一个参数传递null即可实现
js
复制代码
const obj = Object.create(null);
通过控制台输出可以看到obj非常干净
prototype上不会存在很多通过继承的属性和方法,非常的简洁
实现
js
复制代码
const create = function (proto) {
if (typeof proto !== "object" && typeof proto !== "function") {
// 类型校验
throw new TypeError("proto必须为对象或者函数");
} else if (proto === null) {
// null 特殊处理
throw new Error("在浏览器中暂不支持传递null");
}
// 创建一个构造函数
function F() {}
// 更改其 prototype
F.prototype = proto;
// 返回构造的实例, 这个时候返回的实例和传入的 proto中间多了一层 F
return new F();
};
通过实现一个简易版本的Object.create,可以更清晰的看到其和object创建对象的差异