一篇文章,new,原型,单例设计模式全部搞定!

前言

最近,在最近学习过程中。讨论到了关于JS的类的知识点,在JavaScript中,大家都知道在创建一个类的时候,是通过new关键字来创建的。但是new关键字到底是如何详细实现我们一无所知。

原型模式

要先搞懂new关键字的实现,必然先要先搞懂JS到底是如何实现类的继承等特性。在JS这门编程语言中是没有传统的类,只有原型式类,“原型式类”(Prototype-based class)实际上指的是使用原型链prototype chain)来实现对象的继承和复用的一种方式。JavaScript本身是一种基于原型的语言,而不是传统的基于类的语言。那到底什么是原型链呢?

原型链

在JS这么语言中,只有两种数据类型,一种是基本数据类型,一种是复杂类型(对象类型)

  1. 每个对象都有一个原型(prototype) : 在JavaScript中,除了基本数据类型(如数字、字符串、布尔值等),每个对象都关联着一个原型对象。这个原型对象是一个对象,可以拥有自己的属性和方法。
  2. Prototype内部属性: 每个对象内部都有一个隐藏的属性,称为Prototype,这个属性指向该对象相关联的原型。
  3. 原型链的形成: 当试图访问一个对象的属性或方法时,如果该对象本身没有这个属性或方法,JavaScript引擎会继续在其Prototype所指向的原型对象中查找。如果原型对象也没有,引擎会继续在原型的原型对象中查找,以此类推,直到找到该属性或方法,或者到达原型链的末端(通常是Object.prototype)。
  4. 继承: 通过将一个原型对象指向另一个对象作为其原型,可以实现继承。子类型的原型对象可以继承父类型的属性和方法,同时还可以覆盖或扩展这些属性和方法。当使用new关键字创建一个实例时,这个实例的[[Prototype]]会被设置为构造函数的prototype属性所指向的原型对象。

    这么多文绉绉的字相信大家肯定有点懵,没事接下来我将用图形的方式带大家感受一下。

image.png

image.png
prototype就是对象相关联的原型对象,__proto__这个语法可能有些人会很懵,__proto__是用来查询自己的构造函数(我愿意称之为父类)的相关联原型对象。可以理解是上一级的相关联原型对象。看下面这段代码你就明白了。

    function A(){
    }
    var a =new A();
    console.log(a.__proto__ === A.prototype)//true

new关键字

要想实现一个功能,我们必须知道这个功能起到了什么作用,这里也是一样。在探究new的实现的时候,我们必须知道new到底实现了一个什么功能?
在JavaScript中,new关键字是一个非常重要的构造器,用于实例化对象,具体实现了以下几个关键功能:

  1. 创建新对象new操作符首先会在内存中创建一个新的空对象,这个对象将成为实例化的结果。
  2. 绑定原型:新创建的对象的内部属性[[Prototype]]会被设置为构造函数的prototype属性所指向的原型对象。这意味着新对象可以继承构造函数原型上的方法和属性。
  3. 执行构造函数:接着,new操作会调用构造函数,并将新创建的对象(即this上下文)传递给构造函数。在构造函数内部,你可以初始化对象的属性和执行其他必要的设置。
  4. 返回对象:如果构造函数没有显式返回一个对象(或者返回一个原始值,如数字、字符串等),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;
        }
    }

其实就是用一个静态属性来存储第一个创建的实例,往后的每次创建都对这个静态属性进行判断,如果存在则直接返回没有则创建再返回。

今天的代码就分享到这里啦,如果喜欢的话不妨点个关注和赞吧,以后也会一直进行基础内容和进阶内容的更新。谢谢大家>_<!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绯雨934

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值