前言
本次要实现的是 new 关键字,通过对 new 关键字进行代码分析,看看我们在使用 new 时,js会对构造函数进行什么样的操作,最后通过分析的结果来实现一个自定义new关键字
分析new
我们来看看new操作符具体做了什么
首先我们创建一个方法,输出方法并执行
function fun() {
}
console.log(fun())
此时,输出的是
undefined
那我们通过给它添加new关键字,看看会如何变化
function fun() {
}
console.log(new fun())
此时,输出
fun{},多了个空对象。由此,可以得出,
new关键字会创建一个空对象并返回
接下来,判断一下fun()与new fun()原型的关系
function fun() {
}
console.log(new fun().__proto__ === fun.prototype)
返回的结果是
true由此,我们可以得出
new关键字会将 空对象的原型指向构造函数的原型
接下来,判断我们看看this的指向。
首先,方法内的this肯定是指向window的。如果给方法添加了new关键字后,this会改变吗?
function fun() {
this.name = 'zs'
console.log(this)
}
fun()
此时,
this指向window
function fun() {
this.name = 'zs'
console.log(this)
}
new fun()
此时,
this指向fun由此,我们可以得出
new关键字会改变this指向,将空对象的this指向构造函数
最后,我们看看如果方法内有return,那么new会做什么
当我们return一个基本类型时
function fun() {
// return 123
// return 'a'
return true
}
console.log(new fun())
输出的还是空对象,说明
new没有做任何操作
当我们return一个引用类型时
function fun() {
return []
// return {}
}
console.log(new fun())
此时,输出的是
[],说明new给我们返回的是我们return的引用类型由此,我们可以得出new关键字对构造函数有返回值时,会判断是引用类型还是基本类型,如果是引用类型,那就直接用你
return的
所有,new大致做了四个操作:
- 创建了一个空对象
- 将空对象原型指向构造函数原型
- 将空对象this指向构造函数
- 对构造函数有返回值的处理进行判断
自定义new
myNew()
说明:
模拟构造函数创建实例对象的过程
- 语法:
myNew(Fn,...args) - 功能:创建Fn构造函数的实例对象
实现:
我们实现的结构:
let obj = myNew(Person,'zs',20),Person是构造函数
-
结构:函数接收的参数,第一为构造函数,后面的参数为实例化需要的参数
-
功能实现:
-
创建新对象
-
修改新对象的原型对象。函数的显示原型给对象隐式原型
-
修改函数内部
this指向新对象,并执行。通过call()执行函数并修改this -
返回新对象
判断返回结果,通过
instanceof判断是否为Object对象,如果是对象类型的就返回result,如果不是对象类型的就返回新对象。
-
代码:
myNew.js
function myNew(Fn, ...args) {
// 创建对象
let obj = {}
// 修改新对象的原型
obj.__proto__ = Fn.prototype
// 修改this指向,并执行
let result = Fn.call(obj, ...args)
// 返回新对象
return result instanceof Object ? result : obj
}
myNew.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./myNew.js"></script>
</head>
<body>
<script>
function Person(name) {
this.name = name
return {
age: 18
}
}
let obj = myNew(Person, 'zs')
console.log(obj)
</script>
</body>
</html>