javascript编程模式
参考:JavaScript Programming Patterns
本篇会介绍六种js编程模式:
- The Old-School Way
- Singleton
- Module Pattern
- Revealing Module Pattern
- Custom Objects
- Lazy Function Definition
问题场景:网页中有三个超链接,每点击一个,则将其背景色设为特定值,如下所示:
<a href="#">设置背景为红色</a> <a href="#">设置背景为绿色</a> <a href="#">设置背景为蓝色</a>
The Old-School Way
意图:(用最纯的方式实现,简单、直接!)
function changeColor(linkObj, newColor) {
linkObj.style.backgroundColor = newColor;
}
function anchorChange() {
var config = { colors: [ "red", "green", "blue" ] };
// 获取所有的标签
var anchors = document.getElementsByTagName("a");
var size = anchors.length;
// 遍历+加入click监听
for (var i = 0; i < size; i++) {
anchors[i].color = config.colors[i];
anchors[i].onclick = function () {
changeColor(this, this.color);
return false;
};
}
}
使用方式:在所有的<a>标签渲染完成之后,加入
<script type="text/javascript"> anchorChange(); </script>
效果见示例1,这样可以实现我们的需求,但这样做,最大的问题是什么???就是:所有的方法均为全局方法,你可以用全局变量来类比理解。所以,很严重的后果是:方法被覆盖!假设多人开发,如果有一同胞也写了一个方法(如下所示),则问题不言而喻!
function changeColor() {
// 我自己写了一个方法,改变了字体颜色
}
那如何解决这个问题呢?上述问题的关键点在于方法的namespace上!那我们试试Singleton如何?
Singleton
意图:(对功能进行“对象”级别的封装是个不错的选择!)
var anchorChange = {
config: { colors: [ "red", "green", "blue" ] },
changeColor: function (linkObj, newColor) {
linkObj.style.backgroundColor = newColor;
},
init: function () {
var self = this;
var anchors = document.getElementsByTagName("a");
var size = anchors.length;
for (var i = 0; i < size; i++) {
anchors[i].color = self.config.colors[i];
anchors[i].onclick = function () {
self.changeColor(this, this.color);
return false;
};
}
}
};
使用方式:在所有的<a>标签渲染完成之后,加入
<script type="text/javascript"> anchorChange.init(); </script>
效果见示例二。哇!这样的确好了很多,但问题是还不够好!因为我们知道,面向对象的封装,是为了更好的保证对象的完整性。为什么要封装?目的就是为了合理的隐藏与公开,就像一个人,我封装了所有的内部结构,比如身体器官、血液、骨骼等,这些都是private的,而我只把胳膊、手提供给外界可视。这样的好处是什么??其实你这么想,如果外界可以直接访问你的骨骼、血液、器官,那出问题的机会岂不大发了??所以,封装是为了更好的保护我们的私有属性,减少错误调用,这些属性都是必不可少,但是只做为我们自己的内部服务,不需要外界直接访问,外界甚至根本不需要知道有这些属性。
那回顾头来看这个问题,我们并没有做好封装,因为就拿config属性来看,这就是不需要外界访问的私有域。为了解决这个问题,继续来看Module Pattern
Module Pattern
var anchorChange = function () {
// private property
var config = { colors: [ "red", "green", "blue" ] }
// this is a private method
// can be accessed within anchorChange
// cannot be accessed from outside
function alterColor(linkObj, color) {
linkObj.style.backgroundColor = color;
}
return {
// public method
// can be accessed from outside
changeColor: function (linkObj, newColor) {
// calls private function to change color
alterColor(linkObj, newColor);
},
// public method
// can be accessed from outside
init: function () {
var self = this;
// assign reference to current object to "self"
// get all links on the page
var anchors = document.getElementsByTagName("a");
var size = anchors.length;
for (var i = 0; i < size; i++) {
anchors[i].color = config.colors[i];
anchors[i].onclick = function () {
self.changeColor(this, this.color);
// this is bound to the anchor object
return false;
};
}
}
};
}();
效果见示例三。这个已经逐渐符合我们的预期啦,良好的封装让我们的游刃有余!额。。。稍等,好像略显复杂,目的明确,结构不清晰啊!有没有更直接、更简单的??千呼万唤始出来,Revealing Module Pattern登场!!!
Revealing Module Pattern
var anchorChange = function () {
// private property
var config = { colors: [ "red", "green", "blue" ] }
// this is a publicmethod
// can be accessed from outside
function changeColor(linkObj, color) {
linkObj.style.backgroundColor = color;
}
// public method
// can be accessed from outside
init: function () {
var self = this;
// assign reference to current object to "self"
// get all links on the page
var anchors = document.getElementsByTagName("a");
var size = anchors.length;
for (var i = 0; i < size; i++) {
anchors[i].color = config.colors[i];
anchors[i].onclick = function () {
self.changeColor(this, this.color);
// this is bound to the anchor object
return false;
};
}
}
return {
init : init,
changeColor : changeColor
};
}();
效果见示例4。简单+清晰+明了+大气十足!!单不要忘了,javascritp与java的区别,JavaScript is object-based, but Java is object-oriented.In JavaScript, you just need to call the constructor function of your (custom) object with respective parameters to create an object. You do not have any classes or subclasses as e.g. in Java.这就引出了Custom Objects模式
Custom Objects
// custom object constructor
var anchorChanger = function () {
this.init();
};
anchorChanger.prototype.config = { colors: [ "red", "green", "blue" ] }
anchorChanger.prototype.changeColor = function (linkObj, newColor) {
linkObj.style.backgroundColor = newColor;
};
anchorChanger.prototype.init = function () {
var self = this;
// get all links on the page
var anchors = document.getElementsByTagName("a");
var size = anchors.length;
for (var i = 0; i < size; i++) {
anchors[i].color = self.config.colors[i];
anchors[i].onclick = function () {
self.changeColor(this, this.color);
return false;
};
}
};
效果见示例5.真心不错啊!但还有一个问题尚未解决,比如,我需要在changeColor()中进行大量的数学计算,花费较长的时间,那么,上述几种方案就显得美中不足啦,所以,提出Lazy Function Definition,是为了完善和补充以上应用场景,go on!
Lazy Function Definition
顾名思义,如同我们在设计模式之单例模式中提到的一样,提供一种“懒定义”,很好理解,懒就是不立刻或者提前去做,而是只有在需要的时候,才做,懒人么....
// lazy function definition
var anchorChange = function () {
// define configuration
var config = { colors: [ "red", "green", "blue" ] };
// get all links
var anchors = document.getElementsByTagName("a");
var size = anchors.length;
// loop through anchors and attach events
for (var i = 0; i < size; i++) {
anchors[i].color = config.colors[i];
anchors[i].onclick = function () {
anchorChange5().changeColor(this, this.color);
return false;
};
}
// redefine function so that it only holds the changeColor function
anchorChange = function () {
return {
changeColor: function (linkObj, newColor) {
linkObj.style.backgroundColor = newColor;
}
};
};
};
效果见示例6.
posted on 2014-11-11 14:28 zhangwenhao2 阅读(99) 评论(0) 收藏 举报
浙公网安备 33010602011771号