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

意图:(用最纯的方式实现,简单、直接!)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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>标签渲染完成之后,加入

1
<script type= "text/javascript" > anchorChange(); </script>

效果见示例1,这样可以实现我们的需求,但这样做,最大的问题是什么???就是:所有的方法均为全局方法,你可以用全局变量来类比理解。所以,很严重的后果是:方法被覆盖!假设多人开发,如果有一同胞也写了一个方法(如下所示),则问题不言而喻!

1
2
3
function  changeColor() {
     // 我自己写了一个方法,改变了字体颜色
}

那如何解决这个问题呢?上述问题的关键点在于方法的namespace上!那我们试试Singleton如何?

Singleton

意图:(对功能进行“对象”级别的封装是个不错的选择!)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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>标签渲染完成之后,加入

1
<script type= "text/javascript" >  anchorChange.init(); </script>

 效果见示例二。哇!这样的确好了很多,但问题是还不够好!因为我们知道,面向对象的封装,是为了更好的保证对象的完整性。为什么要封装?目的就是为了合理的隐藏与公开,就像一个人,我封装了所有的内部结构,比如身体器官、血液、骨骼等,这些都是private的,而我只把胳膊、手提供给外界可视。这样的好处是什么??其实你这么想,如果外界可以直接访问你的骨骼、血液、器官,那出问题的机会岂不大发了??所以,封装是为了更好的保护我们的私有属性,减少错误调用,这些属性都是必不可少,但是只做为我们自己的内部服务,不需要外界直接访问,外界甚至根本不需要知道有这些属性。

那回顾头来看这个问题,我们并没有做好封装,因为就拿config属性来看,这就是不需要外界访问的私有域。为了解决这个问题,继续来看Module Pattern

Module Pattern

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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

1
2
3
4
5
6
7
8
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 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 

顾名思义,如同我们在设计模式之单例模式中提到的一样,提供一种“懒定义”,很好理解,懒就是不立刻或者提前去做,而是只有在需要的时候,才做,懒人么....

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaScript 设计模式是在 JavaScript 编程中经常使用的一种代码组织和架构方法。设计模式可以帮助开发者解决常见的问题,并提供可复用的解决方案。 以下是一些常见的 JavaScript 设计模式: 1. 工厂模式(Factory Pattern):通过使用工厂方法创建对象,将对象的创建和使用分离开来,提高代码的可扩展性和可维护性。 2. 单例模式(Singleton Pattern):确保一个类只有一个实例,并提供一个全局访问点来访问该实例。 3. 观察者模式(Observer Pattern):定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会被自动通知并更新。 4. 发布-订阅模式(Publish-Subscribe Pattern):也是一种观察者模式的变体,在这种模式中,发布者(Publisher)和订阅者(Subscriber)之间通过消息队列进行通信。 5. 原型模式(Prototype Pattern):通过复制现有对象来创建新对象,避免了使用类进行实例化的复杂性。 6. 适配器模式(Adapter Pattern):将一个类的接口转换成客户端所期望的另一个接口,使得原本不兼容的类可以一起工作。 7. 装饰者模式(Decorator Pattern):动态地给对象添加新的功能,而不影响其他对象。 8. 策略模式(Strategy Pattern):定义一系列算法,将每个算法封装起来,并使它们可以互换使用。 这些设计模式可以帮助开发者在编写 JavaScript 代码时更好地组织和设计代码结构,提高代码的可读性、可维护性和可扩展性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值