什么是new?
new运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象类型之一
举个例子说明下:
function Otaku(name, age) {
this.name = name
this.age = age
this.habit = 'Games'
}
Otaku.prototype.strength = 60
Otaku.prototype.sayYourName = function() {
console.log('I am' + this.name)
}
var person = new Otaku('Kevin', 18)
console.log(person.name) // 'Kevin'
console.log(person.age) // 18
console.log(person.habit) // 'Games'
person.sayYourName() // I am Kevin
从上面的例子中,实例person可以:
- 访问到Otaku构造函数中的属性
- 访问到Otaku.prototype中的属性
ps: new一个对象的过长
- 创建一个空对象
- 设置新对象的constructor属性为构造函数,设置新对象__proto__属性指向构造函数的prototype对象
- 使用新对象调用函数,函数中的this被指向到新对象的实例
- 将初始化完毕的新对象地址,保存到等号左边的变量中
初步实现
因为new是关键字,所有我们写一个函数来模拟new的实现。
分析:
- 因为new的结果是一个新对象,所以在模拟的时候,我们也要建立一个新对象,假设这个对象为obj,因为obj会具有Otaku构造函数的属性,我们可以用Otaku.apply(obj, arguments)来给obj添加新的属性。
- 实例的__proto__属性会指向构造函数的prototype,正是因为建立起这样的关系,实例可以访问原型上的属性
第一版模拟:
function objectFactory() {
var obj = new Object()
var Constructor = [].shift.call(arguments)
obj.__proto__ = Constructor.prototype
Constructor.apply(obj, arguments)
return obj
}
这一版中:
- 利用new Object()的方式新建了obj
- 取出第一个参数,就是我们传入的构造函数。此外因为shirt会修改原数组,所以arguments会被去除第一个参数
- 将obj的原型指向构造函数,这样obj就可以访问到构造函数原型中的属性
- 使用apply,改变构造函数this的指向到新建的对象,这样obj就可以访问到构造函数中的属性
- 返回obj
返回效果的实现
假如构造函数有返回值,且返回值是一个对象的时候
function Otaku(name, age) {
this.name = name
this.age = age
this.habit = 'Games'
return {
name: 'Kevin1',
habit: 'Games1'
}
}
var person = new Otaku('Kevin', 18)
console.log(person.name) // 'Kevin1'
console.log(person.age) // undefined
console.log(person.habit) // 'Games1'
从上面的例子中可以看到,实例person只能访问返回的对象中的属性。
如返回值是一个基本类型的值:
function Otaku(name, age) {
this.name = name
this.age = age
this.habit = 'Games'
return 'Otaku Factory'
}
var person = new Otaku('Kevin', 18)
console.log(person.name) // 'Kevin'
console.log(person.age) // 18
console.log(person.habit) // 'Games'
如返回的是基本类型,尽管构造函数是有返回值的,但是也相当于没有返回值进行处理。
最终代码实现
function objectFactory() {
var obj = new Object()
var Constructor = [].shift.call(arguments)
if(typeof Constructor !== 'function') {
throw new Error('first argument must be a factory function')
}
obj.__proto__ = Constructor.prototype
var ret = Constructor.apply(obj, arguments)
return typeof ret === 'object' ? ret : obj
}
网友评论