首先咱们要知道new
操做符具体作了些什么?数组
__proto__
指向函数的原型prototype
this
指向该对象return
或return
了基本类型,则将新对象做为返回值若是对于原型还不是很了解的话建议先看看:JavaScript温故而知新——原型和原型链bash
先来实现前三点的效果:闭包
function new2() {
// 新建一个对象
var obj = new Object(),
// 取得第一个参数,即传入的构造函数。
// 这里 shift 会修改原数组,所以 arguments 会被去掉第一个参数
Constructor = [].shift.call(arguments);
// 将 obj 的原型指向构造函数,这样 obj 就能够访问到构造函数原型中的属性了
obj.__proto__ = Constructor.prototype;
// 使用 apply ,改变构造函数 this 的指向到新建的对象,这样 obj 就能够的访问到构造函数中的属性了
Constructor.apply(obj, arguments);
return obj;
};
复制代码
咱们能够作个测试app
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayName = function() {
console.log('I am' + this.name);
}
var person = new2(Person, 'xiao', '18')
console.log(person.name) // xiao
console.log(person.age) // 18
person.sayName(); // I am xiao
复制代码
实现返回值的效果函数
假如构造函数是有返回值,而且返回值是一个对象:post
function Person(name, age) {
this.skill = 'eat';
this.age = age;
return {
name: name,
habit: 'sleep'
}
}
var person = new Person('xiao', '18')
console.log(person.name) // xiao
console.log(person.habit) // sleep
console.log(person.skill) // undefined
console.log(person.age) // undefined
复制代码
能够看到实例person
中只能访问返回的对象中的属性,说明此时new
的返回值为构造函数Person
return 出来的对象。测试
假如构造函数的返回值是一个基本类型的值:ui
function Person(name, age) {
this.skill = 'eat';
this.age = age;
return 'hello world'
}
var person = new Person('xiao', '18')
console.log(person.name) // undefined
console.log(person.habit) // undefined
console.log(person.skill) // eat
console.log(person.age) // 18
复制代码
能够看到实例person
能够正常访问构造函数中的属性,说明此时new
的返回值为新建立的原型指向构造函数的对象。this
按照上面的结论来完整实现咱们的new2
:spa
function objectFactory() {
var obj = new Object(),
Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
var ret = Constructor.apply(obj, arguments);
// 判断构造函数返回值是否为对象,是的话返回这个对象,不是则正常返回
return typeof ret === 'object' ? ret : obj;
};
复制代码
结尾
系列文章: