最近开始着手准备面试,就一边刷面经一边写一些文章。其实这些文章网上都有很多了,那我为什么还要发篇文章写这些呢?之前看到过这么一句话我觉得还蛮好的:学习就好比是座大山,人们沿着不通过的路登山,分享自己看到的风景,你不一定能看到别人看到的风景,体会到别人的心情。只有自己去登山,才能看到不一样的风景,体会才更加深刻。
- New的一生
我们平时经常使用new 来创建一个实例,但是new到底做了什么呢? 让我们来看看接下来会发生什么
(1)创建一个新的对象
(2)将构造函数的作用域赋给新的对象(因此this就指向了这个新对象)
(3)执行构造函数中的代码(为这个新对象添加属性)
(4)绑定原型
(5)返回新对象
2.接下来让我们来模拟实现一个new,因为new是一个关键字,这里我们函数名叫做myNew
(结合下边栗子一起看,效果更佳)
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操作对象应该返回的对象是构造函数里面的返回值(仅当返回值是有效对象时),修改之前的代码。