⚠ 准备常识:
- 理解原型和原型链
- 理解
this
绑定
1 new 运算符简介
MDN 文档:
new
运算符 创立一个用户定义的对象类型的实例或具备构造函数的内置对象的实例。
class Person {constructor(name) {this.name = name;}
}
// 创立自定义对象类型的实例
const person = new Person('小明')
// 创立具备构造函数的内置对象的实例
const date = new Date()
new
的作用:创建对象的实例
2 new 到底干了什么事
下面说了 new
的作用是创建对象的实例,那么它到底是怎么创立实例的,外部干了哪几件事?
以 new Person()
为例,当它执行时,会产生以下事件:
-
创立一个空的简略
JS
对象const obj = {}
-
给这个对象增加属性
__proto__
,并将该属性链接到构造函数的 原型对象obj.__proto__ = Person.prototype
-
调用构造函数
Person
,并将this
绑定到新创建的对象obj
Person.apply(obj)
- 如果构造函数没有显式返回一个 对象,则返回新创建的对象,即
obj
3 模仿实现 new 运算符
如上所述,new
运算符就干了这么 4
件事,上面咱们就依据这 4 个步骤用函数来模仿实现new
(面试手写代码)
const _new = function(constructor, ...args) {const obj = {}
obj.__proto__ = constructor.prototype
const res = constructor.apply(obj, args)
// 这一步在 "补充" 中会具体解释
return res instanceof Object ? res : obj
}
代码非常简单,就是依照下面 4
步,一步一步写就能够了
4 补充
-
ES5
提供了Object.create
办法,该办法能够创立一个对象,并让新对象的__proto__
属性指向曾经存在的对象。所以咱们能够应用这个办法合并 1、2 两步
const obj = Object.create(constructor.prototype) // 等价于 const obj = {} obj.__proto__ = constructor.prototype
-
为什么咱们在
_new
函数最初一句代码是:return res instanceof Object ? res : obj
因为
new
运算符的第4
步会分以下3
种状况:-
如果构造函数没有显式
return
(通常状况)那么
person
就是 新创建的对象obj
-
如果构造函数返回的不是一个对象,比方
1
、"abc"
那么
person
还是 新创建的对象obj
function Person() { ... return 1 }
-
如果构造函数显式返回了一个对象,比方
{}
、function() {}
那么
person
就不是 新创建的对象obj
了,而是显式return
的这个对象function Person() { // 函数也是对象 return function() {} }
-
-
留神,模仿实现的函数
_new
传入的参数只能是构造函数,不能是类class Animal {...} _new(Animal) // 会报错:Class constructor Animal cannot be invoked without 'new' // 类只能通过 new 来创立实例