一、new操作符的实现原理
new操作符的执行过程:
(1) 在内存中自动创建一个新对象
(2) 将对象的原型
指向构造函数的原型
。
(3)构造函数内部的this
指向创建出来的新对象
(4)判断函数的返回值类型
,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。
二、什么是对象的原型?
🔔每一个对象中都有一个[[Prototype]],我们称为对象的原型(隐式原型)
对象的原型不是直接显示的,需要用一些方法才能查看。
方法1:浏览器给对象提供了一个属性,可以查看该对象的原型 obj.__proto__
方法2:Object.getPrototypeOf(obj)
(es5之后)
🔔原型有什么用?
查找对象的属性时,会触发getter操作
1. 先看自己对象中有没有该属性,有就直接使用
2. 没有就沿着原型中查找,直到找到Object的原型,Object的原型为null
三、函数的原型
函数也是一个对象,除了有隐式原型外,还有显示原型。显示原型可以直接通过prototype属性获取到。
四、实现new操作符
写法1
代码如下:
const _new = function(Fun,...args) {
//1. 创建一个新对象
let obj = Object.create(null)
//2.将对象的__proto__属性指向构造函数的原型
// 等同于obj.__proto__ = Fun.protoType
Object.setPrototypeOf(obj,Fun.prototype)
//3.将对象的this绑定到函数上,并向函数传参
let res = Fun.apply(obj,args)
//4.//确保返回的是一个对象
return res instanceof Object?res:obj
}
写法2
代码如下:
const _new = function(Fun,...args) {
// 新创建对象的原型对象
let obj = Object.create(Fun.prototype)
let res = Fun.apply(obj,args)
return res instanceof Object?res:obj
}
写法3
代码如下:
const _new = function(Fun,...args) {
let obj = {}
obj.__proto__ = Fun.prototype
let res = Fun.apply(obj,args)
return res instanceof Object ? res :obj
}
注意:函数自身不是构造器。但是,当你在普通函数调用前面放一个new
关键字时,这就将函数调用变成了“构造器调用”。事实上,new 在某种意义上劫持了普通函数并将它以另一种方式调用:构建一个对象,外加这个函数要做的其他任何事。
function NothingSpecial() {
console.log( "Don't mind me!" );
}
var a = new NothingSpecial();
// "Don't mind me!"
a; // {}
NothingSpecial 仅仅是一个普通的函数,但当用 new 调用时,几乎是一种副作用,它会 构建 一个对象,并被我们赋值到 a。这个 调用 是一个 构造器调用,但是 NothingSpecial 本身并不是一个 构造器。
换句话说,在 JavaScript中,更合适的说法是,“构造器”是在前面 用 new 关键字调用的任何函数。
函数不是构造器,但是当且仅当 new 被使用时,函数调用是一个“构造器调用”。