https://blog.youkuaiyun.com/geek1231/article/details/120332364
(1)创建一个新的对象
(2)将构造函数的作用域赋给新的对象(因此this就指向了这个新对象) apply
(3)执行构造函数中的代码(为这个新对象添加属性) proto
(4)返回新对象
(结合下边栗子一起看,效果更佳)
function myNew(){
//用new Object()的方法创建了一个obj对象
var obj = new Object()
//取出传入的构造函数,因为shift会修改原数组,所以arguements会被去除第一个参数
//原地留下第一个参数值这样obj就可以访问到构造函数原型中的属性
Constructor = [].shift.call(arguements)
//结合下面栗子可知第一个参数是person构造函数
//可以打印一下看看console.log(Constructor)
//将obj的原型指向构造函数,这样obj就可以访问到构造函数原型中的属性
//对象__Pro__等于构造函数的prototype
//为了让对象能够调用person.prototype上的方法
obj.__proto__ = Constructor.prototype
//使用apply改变构造函数this的指向,到新建的obj对象
//并执行了constructor,这样obj就会被添加属性
var ret = Constructor.apply(obj,arguements)
//判断返回值是不是一个对象,如果是一个对象我们就返回这个对象
//如果不是我们就原样返回
return typeof ret ==='object' ? ret : obj
}
这是一个栗子:
function person(name, age) {
this.name = name;
this.age = age;
// 这里的this就是那个obj
this.habit = 'Games';
}
person.prototype.strength = 60;
person.prototype.sayYourName = function () {
console.log('I am ' + this.name);
}
var person = myNew(person, 'Kevin', '18')
console.log(person.name) // Kevin
console.log(person.habit) // Games
console.log(person.strength) // 60
person.sayYourName(); // I am Kevin
对于上边判断返回值是不是一个对象的那行代码解释:使用myNew来代替new似乎没有什么问题,但是我们稍微修改一下代码<br>
function Cat(name,gender){
this.name = name
this.gender = gender
return {name:'Jerry',skin:'block'}
}
Cat.prototype.say = ()=>{
console.log('miao')
}
const Cat = new Cat ('Tom','male');
console.log(cat.name)/*Jerry*/
console.log(cat.gender)/*undefned*/
console.log(typeof cat)/*object*/
cat.say() /*TypeError:cat.say is not a function*/
可以发现当构造函数里面有返回值时,明显new操作对象应该返回的对象是构造函数里面的返回值(仅当返回值是有效对象时),修改之前的代码。