大家好,我是睡个好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
操作的基本流程:
- 创建一个新的空对象。
- 将新对象的原型(
__proto__
)设置为构造函数的原型(Person.prototype
)。 - 将构造函数的
this
绑定到新对象上,并执行构造函数。 - 若构造函数未返回非基础类型的值(如对象),则
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底层机制的深刻理解,也是实现复杂设计模式,如单例模式等,的基础。掌握这些技能,可以帮助开发者更灵活地运用面向对象编程原则,写出更高效、易于维护的代码。在实际项目中,根据需求选择合适的实例化策略,比如适时采用单例模式,能显著提升应用的性能和资源利用率。