你new什么new,Stanley(是单例)

347 阅读3分钟

大家好,我是睡个好jo,这次要分享的内容是new关键字的解释,并且通过对new的理解,我们去理解一个设计模式 ———— 单例模式

手写new操作符

让我们从手动实现new操作符的功能开始。以下是一个简化的模拟实现,展示了new操作的四个关键步骤:

new操作详解

Javascript
function Person(name) {
    this.name = name;
    this.sayHello = function() {
        console.log("Hello, I'm " + this.name);
    };
}

    // 注意:若构造函数显式返回一个对象,则new表达式的结果为该对象,否则为新创建的对象。
    // return {name: "Override"};
}

var person = new Person("Alice");
person.sayHello(); // 输出: Hello, I'm Alice

上述代码展示了new操作的基本流程:

  1. 创建一个新的空对象。
  2. 将新对象的原型(__proto__)设置为构造函数的原型(Person.prototype)。
  3. 将构造函数的this绑定到新对象上,并执行构造函数。
  4. 若构造函数未返回非基础类型的值(如对象),则new表达式的结果是新创建的对象。

手动模拟new操作

function myNew(Constructor, ...args) {
    const obj = Object.create(Constructor.prototype); // 创建一个空对象并设置原型
    const result = Constructor.apply(obj, args); // 调用构造函数,改变this指向新对象
    return typeof result === 'object' ? result : obj; // 构造函数显式返回对象则返回该对象
}

const person = myNew(Person, "Bob");
person.sayHello(); // 输出: Hello, I'm Bob

单例模式介绍

单例模式的核心在于控制类的实例化过程,确保在任何情况下,对于特定类而言,全局只存在一个实例。在JavaScript中,这通常用于那些只需要一个共享资源或控制点的场景,比如配置管理器、日志记录器等。

实现单例模式的一种经典方法是利用闭包和立即执行函数表达式:

let Singleton = (function () {
    let instance;

    function createInstance() {
        // 实际的Singleton构造函数及其逻辑
        function Singleton() {
            // 初始化逻辑...
        }

        return new Singleton();
    }

    return {
        getInstance: function () {
            if (!instance) {
                instance = createInstance();
            }
            return instance;
        }
    };
})();

// 使用单例
let instance1 = Singleton.getInstance();
let instance2 = Singleton.getInstance();

console.log(instance1 === instance2); // 输出 true,证明是同一个实例

在这个实现中,getInstance方法负责检查是否已存在实例,如果不存在,则创建并返回一个新的Singleton实例,之后对该方法的所有调用都将返回第一次创建的实例。 立即执行函数表达式 (IIFE):

Javascript 1(function () { ... })(); 这段代码定义并立即执行了一个匿名函数。这样做可以避免污染全局命名空间,将Singleton的实现细节封装在该函数内部。

私有变量 instance:

let instance;

instance变量用于保存Singleton的唯一实例。它被定义在这个闭包内部,因此外部无法直接访问或修改它。

创建实例的函数 createInstance:

function createInstance() {
    function Singleton() {
        // 初始化逻辑...
    }
    return new Singleton();
}

这个函数负责创建Singleton的实例。内部定义了Singleton构造函数,这可以在需要时初始化一个新的Singleton对象。但因为我们的目标是单例,所以这个构造函数只会在第一次调用getInstance时被执行一次。

返回的对象及getInstance方法:

return {
    getInstance: function () {
        if (!instance) {
            instance = createInstance();
        }
        return instance;
    }
};

结合手写new与单例模式

通过理解new操作符的工作原理,我们可以更好地设计和实现像单例这样的设计模式。实际上,在上述单例模式的实现中,虽然未直接使用new操作符,但我们手动模拟了构造函数实例化的过程。通过控制实例化逻辑,确保了全局唯一实例的存在,这正是单例模式的核心所在。

总之,手写new操作符不仅是对JavaScript底层机制的深刻理解,也是实现复杂设计模式,如单例模式等,的基础。掌握这些技能,可以帮助开发者更灵活地运用面向对象编程原则,写出更高效、易于维护的代码。在实际项目中,根据需求选择合适的实例化策略,比如适时采用单例模式,能显著提升应用的性能和资源利用率。