方法介绍
Object.create() 方法用于创建一个新对象,使用现有的对象来作为新创建对象的原型(prototype)。
用法:
Object.create(proto,[propertiesObject])
- proto:新创建对象的原型对象。
- propertiesObject (可选):如果该参数被指定且不为 undefined,则该传入对象的自有可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)将为新创建的对象添加指定的属性值和对应的属性描述符。这些属性对应于 Object.defineProperties() 的第二个参数。
Object.defineProperties()方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。
Object.defineProperties()使用示例:
let obj1 = { a: 2, b: 3 }
Object.defineProperties(obj1, {
a: {
enumerable: false, // 数据、存储描述符号
configurable: false, // 数据描述符
writable: false, // 数据描述符
value: 'xxx' // 数据描述符号
get: function(){}, // 储存描述符
set: function(){} // 储存描述符
}
})
有关Object.defineProperties()的具体细节请看我的这篇文章:戳我传送
Object.create 返回值:一个新对象,带着指定的原型对象及其属性。
使用Object.create(null)的原因
很多框架源码作者使用它来初始化一个新的对象,难道是最佳实践?
通过Object.create(null)创建出来的对象,没有任何属性,显示No properties。我们可以将其当成一个干净的 map 来使用,自主定义 toString,hasOwnProperty等方法,并且不必担心将原型链上的同名方法被覆盖。
注意:{...}创建的对象,使用for in遍历对象的时候,会遍历原型链上的属性,带来性能上的损耗。使用Object.create(null)则不必再对其进行遍历了。
框架源码对性能的要求极高,哪怕是一点点,都值得关注。
开始手写
// 第一个参数传递null时,返回的实例原型为null
// 第一个参数类型只能是object、function或者null,否则报错。
// 第二个参数类型,不能是null,否则报错
// 第二个参数如果不为 undefined ,需要将其挂载到实例的 Object.defineProperties 上。
Object.mjy_create = function(proto, defineProperties) {
if ( typeof proto !== 'object' && typeof proto !== 'function' ) {
throw new TypeError(`Object prototype may only be an Object or null: ${proto}`)
}
if ( defineProperties === null ) {
throw new TypeError('Cannot convert undefined or null to object')
}
// 定义新对象
const obj = {}
// 设置原型
// obj.__proto__ = proto // 不建议这么做了
// 通常,应该使用 Object.setPrototypeOf() 方法来设置对象的原型。
// 因为 Object.prototype.__proto__ 访问器已被弃用。
Object.setPrototypeOf(obj, proto) // 建议使用setPrototypeOf设置原型
if ( defineProperties !== undefined ) {
Object.defineProperties(obj, defineProperties)
}
return obj
}
let obj1={b:2}
let obj2 = Object.mjy_create(obj1, { a: { enumerable: false } })
console.log(obj2)//{}
let obj2_ = Object.mjy_create(obj1, { a: { enumerable: true } })
console.log(obj2_)//{ a: undefined }
let obj3 = Object.create('222', undefined) // TypeError: Object prototype may only be an Object or null: 222
let obj4 = Object.create(obj1, null) // TypeError: Cannot convert undefined or null to object
console.log(obj2.a) // undefined