前言
最近,在最近学习过程中。讨论到了关于JS的类的知识点,在JavaScript中,大家都知道在创建一个类的时候,是通过new关键字来创建的。但是new关键字到底是如何详细实现我们一无所知。
原型模式
要先搞懂new
关键字的实现,必然先要先搞懂JS
到底是如何实现类的继承等特性。在JS
这门编程语言中是没有传统的类,只有原型式类,“原型式类”(Prototype-based class
)实际上指的是使用原型链(prototype chain
)来实现对象的继承和复用的一种方式。JavaScript本身是一种基于原型的语言,而不是传统的基于类的语言。那到底什么是原型链呢?
原型链
在JS这么语言中,只有两种数据类型,一种是基本数据类型,一种是复杂类型(对象类型)
- 每个对象都有一个原型(prototype) : 在JavaScript中,除了基本数据类型(如数字、字符串、布尔值等),每个对象都关联着一个原型对象。这个原型对象是一个对象,可以拥有自己的属性和方法。
Prototype
内部属性: 每个对象内部都有一个隐藏的属性,称为Prototype
,这个属性指向该对象相关联的原型。- 原型链的形成: 当试图访问一个对象的属性或方法时,如果该对象本身没有这个属性或方法,JavaScript引擎会继续在其
Prototype
所指向的原型对象中查找。如果原型对象也没有,引擎会继续在原型的原型对象中查找,以此类推,直到找到该属性或方法,或者到达原型链的末端(通常是Object.prototype
)。 - 继承: 通过将一个原型对象指向另一个对象作为其原型,可以实现继承。子类型的原型对象可以继承父类型的属性和方法,同时还可以覆盖或扩展这些属性和方法。当使用
new
关键字创建一个实例时,这个实例的[[Prototype]]
会被设置为构造函数的prototype
属性所指向的原型对象。
这么多文绉绉的字相信大家肯定有点懵,没事接下来我将用图形的方式带大家感受一下。
prototype就是对象相关联的原型对象,__proto__
这个语法可能有些人会很懵,__proto__
是用来查询自己的构造函数(我愿意称之为父类)的相关联原型对象。可以理解是上一级的相关联原型对象。看下面这段代码你就明白了。
function A(){
}
var a =new A();
console.log(a.__proto__ === A.prototype)//true
new关键字
要想实现一个功能,我们必须知道这个功能起到了什么作用,这里也是一样。在探究new的实现的时候,我们必须知道new到底实现了一个什么功能?
在JavaScript中,new
关键字是一个非常重要的构造器,用于实例化对象,具体实现了以下几个关键功能:
- 创建新对象:
new
操作符首先会在内存中创建一个新的空对象,这个对象将成为实例化的结果。 - 绑定原型:新创建的对象的内部属性
[[Prototype]]
会被设置为构造函数的prototype
属性所指向的原型对象。这意味着新对象可以继承构造函数原型上的方法和属性。 - 执行构造函数:接着,
new
操作会调用构造函数,并将新创建的对象(即this
上下文)传递给构造函数。在构造函数内部,你可以初始化对象的属性和执行其他必要的设置。 - 返回对象:如果构造函数没有显式返回一个对象(或者返回一个原始值,如数字、字符串等),
new
操作会自动返回新创建的对象实例。如果构造函数显式返回一个对象,则返回该对象,而不是默认创建的实例。
如果你问我为什么是实现了这些功能我只想说。。。。。。
实现代码
//这里的A象征着传进来的构造函数,...args相当与将参数变为一个数组
function myNew(A,...args){
let newA ={};
newA.__proto__ =A.prototype;
//这里的A.apply(newA,args)相当于执行A同时让A的全局执行上下文对象指向了newA,
//也就是this指向了newA,并且传入参数args
let resultA =A.apply(newA,args);
//进行判断,也就是上面的步骤四
if(resultA instanceof Object){return resultA};
else {return newA;}
}
恭喜你,你已经完成了手写关键字new.接下来就是引入单例设计模式了
单例设计模式
单例模式(Singleton Pattern)是一种常用的设计模式,属于创建型模式的一种。它的核心思想是确保一个类只有一个实例,并提供一个全局访问点来获取这个实例,从而控制对资源的共享或对特定操作的唯一控制。
那我们如何只让一个类只有一个实例呢?普通的new关键字肯定是不行的了。这里只能通过我们来手写关键字new了再加上一些判断,老规矩上代码。
//类A
fucntion A(name){this.name =name;}
//用一个静态属性来存储是否已经存在实例
A.instance =null;
function newA(A,name){
//如果还没有实例,这边直接使用new关键字了
if(!A.instance){
A.instance =new newA(name){};
return A.instance;
}
else{
return A.instance;
}
}
其实就是用一个静态属性来存储第一个创建的实例,往后的每次创建都对这个静态属性进行判断,如果存在则直接返回没有则创建再返回。
今天的代码就分享到这里啦,如果喜欢的话不妨点个关注和赞吧,以后也会一直进行基础内容和进阶内容的更新。谢谢大家>_<!