手撕js中的new关键字
前言
在js中,要想创建实例对象,就得依靠new关键字,new是JavaScript中实现面向对象编程、继承机制、以及管理对象生命周期不可或缺的一部分,对于构建健壮、可扩展的JavaScript应用程序至关重要。今天我们来了解new出一个类的实例化对象,它的底层到底进行了什么操作,并且手写一个和new功能相同的函数,以加深我们对new底层操作的理解。
探索new的功能
1、创建一个新的对象 大家请看如下代码以及控制台输出结果:
-为什么两个传入相同的属性值的obj对象会是不相等的呢,明明所有的属性都是一样。但是我们知道obj1 == obj2 是通过比较对象的地址,所以由此而知,obj2对象的new Duck并不是调用obj1在栈中的引用,而是在堆内存中创建了一个name="小黄鸭"的新对象。
2、设置原型链
请看如下代码及结果
这说明new不仅创建了一个新对象,并且将其原型链指向了Duck类的原型(prototype),这意味着新对象能够继承构造函数原型上的方法和属性。
3、绑定this值并执行构造函数体
通过以下两张图片
我们得知new在实例对象时,其中new将this关键字绑定到新创建的对象上,并将属性值一一传入this指向的新对象中,进行对象的初始化,并进行其他必要的设置。
4、处理返回值
在new进行完前三项操作时,会将该创建的对象返回给obj1.使obj1指向该栈内存中新对象的引用。
在进行完所有的四项操作后,new的执行就结束了,这就是new底层进行的所有操作。
手撕new
在我们刚刚了解完new在底层到底完成了哪些功能之后,我们手撕起来就很轻松了,总共就只需要实现以上四个步骤就可以了。思路也就是上面四个步骤
①创建新对象obj ②设置原型链 ③绑定this值并执行函数构造体 ④处理对象
实现源码如下(mynew函数)
function Duck(nickname,area){
this.nickname = nickname
this.area = area
}
function mynew(Fun, ...args){
let object = {}
Fun.apply(object,args)
object.__proto__ = Fun.prototype
return object
}
let duck = mynew(Duck,'yellow dog','狗狗宠物店')
console.log(duck,duck.__proto__)
其中参数Fun,...args分别为类名和要传入的属性集合 其中Fun.apply方法,用于改变this的指向(通过欺骗词法作用域),指向obj对象,并将值以Fun的构造函数的方式传给obj。 最后没有问题,能够输出duck中的各项属性 由于Duck中没有通过prototype添加实例方法,所以这里为空
结语
通过对“new”关键字的深入理解,我们能够更加得心应手地控制对象的创建与继承,无论是面对简单的数据封装,还是复杂的类层级设计,都能游刃有余。它不仅是JavaScript语言设计中的一个小巧思,更是通往高级编程技巧的必经之路,“new”关键字虽小,却承载着JavaScript面向对象编程的重要使命,是每个JavaScript开发者技能树上不可或缺的一环。希望大家能在我的讲解下能够更加清晰地理解new关键字的底层原理。
转载自:https://juejin.cn/post/7375851690661855272