new的使用
如下所示,可以使用new来创建一个自定义构造函数的实例对象,在对象中可以使用构造函数原型上的方法以及构造函数中的属性:
function Person(name,age){
this.name = name
this.age = age
// 返回非对象类型不会对new造成影响
// return this.name + this.age
}
Person.prototype.say = function(){
console.log('我是'+this.name+',今年'+this.age+'岁')
}
var obj = new Person('xxx',20)
console.log(obj)
obj.say()
分析可以得出,使用new创建对象时主要经过了以下几步:
1、创建一个新的空对象,如obj
2、对象obj会继承构造函数Person的原型(obj.proto === Person.prototype),以便使用构造函数上的方法(obj.say())
3、将构造函数Person的this指向对象obj,即可以将构造函数上的属性添加到对象上
4、如果构造函数Person没有返回对象,则返回新创建的对象
因此可以按步骤手写出new方法:
// 手写new方法
function myNew(constructor){
// 首先判断传入的第一个参数是否是函数
if(Object.prototype.toString.call(constructor) !== '[object Function]')
throw new Error('error in params')
// 然后获取到传入的其他参数(除去第一个)
let args = Array.from(arguments).slice(1)
// 创建一个空对象,让其继承构造函数的原型
let newObj = Object.create(constructor.prototype)
// 这种写法等价于:
// let newObj = {}
// newObj.__proto__ = constructor.prototype
// 执行构造函数,让this指向newObject,使其具有构造函数的属性
let result = constructor.apply(newObj,args)
// 判断result的类型,如果是object或者function则直接返回
let resultType = Object.prototype.toString.call(result)
let isObject = (resultType === '[object Object]')
let isFunction = (resultType === '[object Function]')
if(isObject || isFunction){
return result
}
else{
// 否则返回新创建的对象
return newObj
}
}
// 测试一下
let obj = myNew(Person,'xxx',20)
console.log(obj)
obj.say()
其中的关键点是:
1、使用Object.create()创建对象
2、使用apply方法改变this的指向
3、使用Object.prototype.toString,call()来判断结果的类型