javascript中new关键字到底做了啥?
先看看MDN中对new的描述
我们可以看到,在mdn文档对new的描述中,new主要做了4个操作,大多初学者也许还不能够理解,那我们来用代码还原一下new的4个操作。
封装myNew
//封装一个myNew,来简单实现new关键字的功能
//这里的callback就是构造函数
function myNew(callback, p1, p2) {
//对应第一个操作:创建一个空的简单JavaScript对象
const obj = {}
//第二步:链接该对象
obj.__proto__ = callback.prototype
//第三步:将步骤1新创建的对象作为this的上下文
callback.call(obj, p1, p2)
//第四步:返回该对象
return obj
}
好啦,简简单单的几行代码,就能简单还原一下new的操作,下面我们看一下是不是一样呢。
//定义一个简单的构造函数
function People(name, age) {
this.name = name
this.age = age
};
//给构造函数的原型对象上添加一个实例方法
People.prototype.say = function () {
console.log('hello ' + this.name);
}
//来new一下
//毕竟封装的myNew,使用形式上和new还是有一些区别
const lqs = myNew(People, 'lqsss', 18)
//直接new关键字
const zty = new People('ztyyy', 18)
//打印两者,顺带调用一下方法
console.log(lqs);
console.log(zty);
lqs.say()
zty.say()
结果如下:
我们发现两者肉眼可见的一样!并且连__proto__.constructor也指向正确!
上面就是对new 的简单封装,但是new关键字还有许多坑!
new关键值的返回值问题
我们都知道,new的函数中,是自动返回一个实例的,但是如果手动返回一个值呢?看下述代码
function People(name, age) {
this.name = name
this.age = age
//我们在构造函数中手动返回一个对象
return {
name: 'zty',
age: 18
}
}
const lqs = new People('lqsss', 18)
//我们打印new的实例
console.log(lqs);//{name: "zty", age: 18}
我们发现在手动返回一个对象时,new的返回竟然被替换掉了!那总是会这样吗,这次我们来返回一个函数
function People(name, age) {
this.name = name
this.age = age
return function () {}
}
const lqs = new People('lqsss', 18)
console.log(lqs);//ƒ () {}
在收到返回函数时,构造函数的自动返回值依然被替换掉了,那么我们在试试其他数据类型
function People(name, age) {
this.name = name
this.age = age
return 'zty'
}
const lqs = new People('lqsss', 18)
console.log(lqs);//People {name: "lqsss", age: 18}
这次我们手动返回了一个字符串,但是并没有替换掉自动返回的对象,构造函数还是顺利执行了!
在多次实验之后,得出一个结论!
!!!new之后的函数,如果没有手动return 则会返回一个构造函数的实例,如果手动写了return 并且return的是一个引用数据类型,那么实例会被引用数据类型替换掉!如果return的是一个简单数据类型,那么构造函数还是能顺利进行return!