new是什么
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例
简单来说就是执行了构造函数并返回实例对象
new 做了什么
function Animal(name) {
this.name = name
}
Animal.prototype.say = function (word) {
console.log(word)
}
const cat = new Animal('cat')
console.log(cat) // {name: cat}
cat.say('喵喵喵') // 喵喵喵
const dog = Animal('dog')
console.log(dog) // undefined
dog.say('汪汪汪') // TypeError: Cannot read property 'say' of undefined
从以上代码得到的结果来看,new执行了构造函数Animal,并且返回了一个对象,对象中包含了name属性,且对象能访问Animal原型的say方法。
而因为正常执行的构造函数Animal,没有返回值,所以dog是undefined。
那么如果给构造函数Animal添加返回值,会发生什么
function Animal(name) {
this.name = name
return 0
}
Animal.prototype.say = function (word) {
console.log(word)
}
const cat = new Animal('cat')
console.log(cat) // {name: cat}
cat.say('喵喵喵') // 喵喵喵
const dog = Animal('dog')
console.log(dog) // 0
console.log(window.name) // dog
dog.say('汪汪汪') // TypeError: dog.say is not a function
这段代码中new产生的结果并没有变化,而正常执行的Animal函数因为Animal有了返回值,所以dog是0,而因为this是谁调用this就指向谁,所以window.name是dog
如果给构造函数Animal的返回值是一个对象,又会发生什么
function Animal(name) {
this.name = name
return {age: 1}
}
Animal.prototype.say = function (word) {
console.log(word)
}
const cat = new Animal('cat')
console.log(cat) // {age: 1}
cat.say('喵喵喵') // TypeError: cat.say is not a function
const dog = Animal('dog')
console.log(dog) // {age: 1}
dog.say('汪汪汪') // TypeError: dog.say is not a function
这段代码的结果和正常执行的构造函数结果一样的
所以可以看出如果构造函数的返回值是一个对象,new返回这个对象,如果返回值不是对象类型,那么new会返回一个新的对象,且将this指向这个新的对象
由此可以看出new主要做了以下几件事情
1.创建一个空的简单 JavaScript 对象(即 {});
2.为步骤 1 新创建的对象添加属性 __proto__,将该属性链接至构造函数的原型对象;
3.将步骤 1 新创建的对象作为 this 的上下文;
4.如果该函数没有返回对象,则返回 this。
那么如果我们想自己实现一个new该怎么做呢
1.首先这个函数需要接收一个参数,这个参数是必须是一个构造函数,如果不是构造函数直接抛出一个错误
2.我们还需要接收构造函数接收的参数,因为参数是不定量的,这里我们使用展开运算符代表剩余参数
3.我们需要新建一个对象,这个对象需要继承构造函数的原型链,这里使用Object.create创建新对象并继承原型
4.我们需要执行这个函数
5.我们需要将this指向我们新建的对象, 结合第4步我们可以使用apply
6.如果这个构造函数的返回值是一个对象,返回这个对象,如果不是,返回this
以下是详细代码
function myNew(constructor, ...args) {
if(typeof constructor !== 'function') {
throw `constructor is not a constructor`
}
const obj = Object.create(constructor.prototype);
const result = constructor.apply(obj, args)
return result instanceof Object ? result : obj
}