Object.create()
详解
Object.create() 方法能够创建一个新对象,并让已有的对象为新对象提供__proto__
语法: Object.create(proto, [propertiesObject])
- proto: 新创建对象的原型对象,该对象的属性会继承给被创建的对象
- prototiesObject(可选): 创建的对象的自身定义的可枚举属性, 例如num: { value: 10 }
、obj:{ value: false }
。如果设置了get和set, 那么不能再设置value和writable中任意一个,否则会报错Invalid property descriptor. Cannot both specify accessors and a value or writable attribute
异常: 如果propertiesObject参数是null
或非原始包装对象
,则抛出一个 TypeError
异常。
返回值: 新的对象,新对象的[[Prototype]]
即传入的__proto__
参数
使用:
const oldObj = {
name: 'test',
child: {
name: 'create'
}
}
const newObj = Object.create(oldObj, {
'keyName':{
value: '初始化赋值',
writable: true, // 是否可修改
configurable: true, // 是否可删除
enumerable: true, // 是否是否可以用for...in...枚举
/* 如果设置get和set, 那么不能再设置value和writable中任意一个 */
get: function(){/**/}, // getter
set: function(value){/**/} // setter
}
})
显然我们可以使用这个API实现继承。
并且,当我们使用Object.create(null)创建对象,会得到一个非常干净的对象,没有任何的属性,不用担心自主定义方法时会覆盖原型链上的同名方法
手写
通过上面的详解,我们差不多明白了Object.create()
的内部思路,那么手写就很简单了
方法一
Object.prototype.myCreate = function(proto, propertiesObject=undefined){
if( typeof proto!== 'object' && typeof proto!=='function' ){
throw new TypeError(`The passed in prototype must be an object or null: ${proto}`)
}
if( propertiesObject === null ){
throw new TypeError(`Cannot convert undefined or null to object`)
}
const newObj = {}
Object.setPrototypeOf(newObj, proto) // 使用Object.setPrototypeOf()方法设置原型
if( typeof propertiesObject != 'undefined' ){
Object.defineProperties(newObj, propertiesObject)
}
return newObj
}
检验:
方法二:
我们使用构造函数来实现一下
Object.prototype.myCreate = function(proto, propertiesObject=undefined){
if( typeof proto!== 'object' && typeof proto!=='function' ){
throw new TypeError(`The passed in prototype must be an object or null: ${proto}`)
}
if( propertiesObject === null ){
throw new TypeError(`Cannot convert undefined or null to object`)
}
function fn(){};
fn.prototype = proto;
fn.prototype.constructor = fn
if( typeof propertiesObject != undefined ){
Object.defineProperties(fn, propertiesObject)
}
return new fn()
}
检验: