new
作用
new运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
实现
new的四个步骤:
- 创建一个新对象
- 链接到构造函数原型
- 绑定this
- 返回新对象
// 定义一个函数,第一个参数是构造函数,后面的其他参数通过...args放到args中
function myNew (fun, ...args) {
// 对应步骤1
var obj = {}
// 对应步骤2
// 将obj.__proto__指向构造函数fun的原型,就能使obj访问到构造函数原型上的属性
obj.__proto__ = fun.prototype
// 对应步骤3,通过apply绑定thi
var res = fun.apply(obj, args)
// 对应步骤4
// 返回新对象,这里判断res是否为object,以此保证返回的是个对象
return res instanceof Object ? res : obj
}
注: 关于apply的实现在这里apply、call、bind的原理与实现
Object.create()
作用
Object.create()创建一个新对象并使用现有的对象来提供新创建的对象的__proto__。
实现
Object.create()接收两个参数:proto(必需)和propertiesObject(可选),
其中proto是新创建对象的原型对象,propertiesObject是一个对象,用来描述新对象的属性,其描述字段如下图:
function myCreate (proto, propertiesObject) {
// 判断proto是否是object或者function,如果不是的话就直接抛出TypeError错误
if (typeof proto !== 'object' && typeof proto !== 'function') {
throw new TypeError('Object prototype may only be an Object or null')
}
// 这里当propertiesObject为null时需要报错
if (propertiesObject === null) {
throw new TypeError('Cannot convert undefined or null to object')
} else {
// 创建一个空对象,并将其原型变成传入的参数一
var obj = {}
obj.__proto__ = proto
// 这里当propertiesObject为undefined时就不执行
if (propertiesObject !== undefined) {
// 使用Object.defineProperties()为新对象添加属性
Object.defineProperties(obj, propertiesObject)
}
return obj
}
}
注意点: 如果传入propertiesObject是null或者非原始包装对象,就抛出TypeError错误。
非原始包装对象:类似new String('111')
小问题
new Object()和Object.create(null)所创建的对象有何不同?
new Object()创建的对象有__proto__属性,而Object.create(null)创建的对象没有任何属性