原型式继承不控制实例数量,单例模式重在唯一性保障;二者结合是用原型式继承组织对象结构和方法复用,并在创建环节加入单例控制逻辑,使单例实例具备原型链能力。

原型式继承本身不负责控制实例数量,单例模式的核心是“唯一性保障”,二者结合的关键在于:用原型式继承组织对象结构和方法复用,再在创建环节加入单例控制逻辑——不是靠原型链生成单例,而是让单例实例“拥有原型链能力”。
原型式继承提供可复用的对象骨架
JavaScript 中常用 Object.create() 实现原型式继承,它能快速让新对象共享已有对象的方法与属性,避免重复定义:
- 把通用行为(如
save、validate)放在一个基础对象里 - 用
Object.create(base)创建子对象,自动获得这些能力 - 子对象可覆盖或扩展方法,不影响其他实例
单例控制必须落在实例化入口上
无论用哪种继承方式,单例都得在“第一次创建”时拦截后续调用。常见做法有两类:
-
静态属性缓存:在构造函数或工厂函数上挂一个
instance属性,每次调用前检查是否已存在 -
闭包封装:用 IIFE 包住私有
instance变量,只暴露一个获取实例的函数,外部无法绕过
结合示例:带原型能力的单例管理器
比如做一个配置管理器,既要共享 get/set 方法,又要全局唯一:
const ConfigPrototype = {
get(key) { return this.data[key]; },
set(key, value) { this.data[key] = value; }
};
const ConfigSingleton = (function() {
let instance = null;
return function() {
if (!instance) {
instance = Object.create(ConfigPrototype);
instance.data = {}; // 每个实例独立的数据空间
}
return instance;
};
})();
// 使用
const cfg1 = ConfigSingleton();
const cfg2 = ConfigSingleton();
console.log(cfg1 === cfg2); // true
console.log(cfg1.get === cfg2.get); // true(方法来自同一原型)
注意避坑点
直接对原型对象赋值状态(如 ConfigPrototype.data = {})会导致所有继承它的对象共享数据,破坏单例应有的“独立状态+统一接口”设计意图。状态必须挂在实例自身,方法才放在原型上。











