本文详解JavaScript单例模式的原理与实现。首先解析apply和call在函数执行与this指向中的作用,随后通过闭包和缓存机制展示单例模式的核心代码。文章包含创建弹窗、遮罩层等实际应用场景,并附带完整可运行代码供前端开发者参考。
单例模式概述与背景
本文详细介绍JavaScript设计模式中的单例模式,涵盖其原理与具体用法,供开发者参考学习。
设计模式可视为业务代码的预先解决方案。在真实业务逻辑编写之前,设计模式已然存在。它是开发者长期积累业务经验后总结出的通用解决方案。
许多开发者习惯于编写命令式代码,即根据具体业务需求直接编写功能,例如添加点击事件或进行数据验证。这类代码往往缺乏对设计模式或前人经验的借鉴与优化。
不再寻找客观借口,近期开始关注设计模式,并尝试从设计模式的视角来优化开发流程。
apply与call方法解析
在深入单例设计模式之前,必须明确JavaScript中apply和call方法的作用。
apply和call的直接作用是执行函数,并根据对象是否发生变化,产生借用方法或使用自身方法的情况。两者的区别在于参数形式:apply接收数组作为第二个参数,而call接收参数列表。此处重点阐述它们的功能。
1)函数执行示例
//运行函数
function test(){
alert(1);
}
test.apply();
函数即使不使用apply也能正常运行,但在某些特定场景下,使用apply会使代码显得更为专业。
2)在apply(this, arguments)中,若this保持不变,即直接利用对象自身方法,则不存在借用的概念。
var arr=[1,2,3];
var max=Math.max.apply(null,arr);
alert(max);
3)若this发生改变,此时则是借助this这个对象来调用其他对象的方法。
<script>
/*定义一个人类*/
function Person(name, age) {
this.name = name;
this.age = age;
}
/*定义一个学生类*/
function Student(name, age, grade) {
Person.apply(this, arguments);
this.grade = grade;
}
//创建一个学生类
var student = new Student("qian", 21, "一年级");
//测试
alert("name:" + student.name + "\n" + "age:" + student.age + "\n" + "grade:" + student.grade);
//测试结果name:qian age:21 grade:一年级
//因为在执行过程中this的对象发生改变,所以是this借助了Persion对象的方法。
</script>
运行结果:

单例模式核心实现
介绍完apply和this的相关知识后,接下来解释单例设计模式。
单例模式的核心在于创建并仅返回一个对象。由于只有一个实例,因此涉及缓存概念。本文采用现有案例,只要能清晰说明问题即为好案例。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> 单利模式应用</title>
</head>
<body>
<div>
<button id="openbtn">
创建按钮
</button>
<script type="text/javascript">
//设计模式核心代码
var getSingle = function(fn) {
var result;
return function() {
return (result || (result = fn.apply(this,arguments)));
}
}
//业务代码之创建div代码
var createDiv = function() {
var div = document.createElement("div");
div.innerHTML = "我是创建对象";
console.warn('11');//多次点击只输出一次
return div;
}
var createSingleDiv = getSingle(createDiv);
//业务代码之触发事件
document.getElementById("openbtn").onclick = function() {
var div = createSingleDiv();
document.getElementsByTagName("body")[0].appendChild(div);
}
</script>
</div>
</body>
</html>
运行结果:

上述代码中的||运算符具有短路计算特性:如果result已有值,后续表达式将不再计算。此外,这里的apply仅起到执行函数的作用。
单例模式用途广泛,目前已知的应用包括创建弹窗、创建遮罩层以及实现jQuery的one函数效果等。
最后,该设计模式的核心代码运用了闭包。闭包能够保存作用域链,从而引发静态变量的改变,进而产生缓存效果。
感兴趣的朋友可以使用在线HTML/CSS/JavaScript前端代码调试运行工具:http://tools.jb51.net/code/WebCodeRun测试上述代码运行效果。
更多关于JavaScript相关内容还可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》
希望本文所述对大家JavaScript程序设计有所帮助。