代码改变世界

Pro javascript design pattern 读书笔记之 The structure of a chain

2008-10-29 14:18  wlstyle  阅读(222)  评论(0)    收藏  举报

Chaining

在这章中我们将关注javascript的chain methods together.通过使用一些简单的技术,开发者能很优雅的写代码(就向jquery中)。为通常的任务节省了很多的时间,你能改进代码的实现方式。最后你能写一个包含chaining所有技术的javascript库。Chains所有你喜欢的代码在一块。

Chaining 只是一个语法上的hack.它允许你通过减少初始化操作从而在一些代码中体验复杂的操作。Chaining需要两个部分:一个在html元素中创建对象的工厂,和一些使用这些html元素执行操作的方法。每一个方法都能通过在方法名后加入一个点号加入到链中。链相当于一个在页面中选择元素然后对这个元素执行多个操作。

让我们看一些例子。使用一些内置的函数,你能通过观察”before and after”的对比来了解chainning的基本概念。在这个例子中内置函数是如果工作的并不重要,这是第一个通过一个id对一个元素进行引用然后给他分配一个事件监听函数。当单击的时候,他设置文本的颜色为绿色,然后显示这个元素。

 

 1 //without chaining
 2 
 3 addevent($('example'),'click',function(){
 4 
 5     setStyle(this,'color','green');
 6 
 7     show(this);
 8 
 9 })
10 
11 //with chaining
12 
13 $('example').addevent('click',function(){
14 
15     $(this).setStyle('color','green').show();
16 
17 })
18 

 

The structure of a chain

你已经对$这个函数很熟悉了。通常返回一个html元素或者html元素的集合。$函数如下:

 

 1 function $(){
 2 
 3     var elements=[];
 4 
 5     for(var i=0,len=arguments.length;i<len;i++){
 6 
 7         var element=arguments[i];
 8 
 9         if (typeof element ==="string"){
10 
11             element= document.getElementById(element);
12 
13         }
14 
15         if(arguments.length === 1){
16 
17             return element;
18 
19         }
20 
21         elements.push(element);
22 
23         
24 
25     }
26 
27     return elements;
28 
29     
30 
31 }
32 
33 

 

然而,如果你改变这个函数,让他作为一个构造函数,存储这些元素作为一个实例的属性,然后在原型方法中返回一个对实例的引用,你就能给予它chain的能力。你需要改变$函数以便他成为一个工厂方法。创建一个支持chaining的对象.你同样希望$函数能有一个包含元素的数组,所以你能使用同样的公有接口。改造后的代码如下:

 

 1 (function(){
 2 
 3     //use a private class
 4 
 5     function _$(els){
 6 
 7         this.elements=[];
 8 
 9         for(var i=0,len=els.length;i<len;i++){
10 
11             var element=els[i];
12 
13             if(typeof element === "string"){
14 
15                 element=document.getElementById(element);
16 
17             }
18 
19             this.elements.push(element);            
20 
21         }       
22 
23     }
24 
25     //the public interface
26 
27     window.$=function(){
28 
29         return new _$(els)
30 
31     }
32 
33 })()
34 

 

因为所有的对象通过原型实现继承,你能使用被返回实例对象的引用调用每一个作为原型链的方法。通过这中思想。我们继续改造这个函数,通过在$中添加构造函数属性。这样就使链成为一种可能。

 

  1 (function(){
  2 
  3     //use a private class
  4 
  5     function _$(els){
  6 
  7         this.elements=[];
  8 
  9         for(var i=0,len=els.length;i<len;i++){
 10 
 11             var element=els[i];
 12 
 13             if(typeof element === "string"){
 14 
 15                 element=document.getElementById(element);
 16 
 17             }
 18 
 19             this.elements.push(element);            
 20 
 21         }       
 22 
 23     }
 24 
 25     _$.prototype={
 26 
 27         each: function(fn){
 28 
 29             for(var i=0,len= this.elements.length;i<len;i++){
 30 
 31                 fn.call(this,this.elements[i]);
 32 
 33             }
 34 
 35             return this;
 36 
 37         },
 38 
 39         setStyle:function(prop,val){
 40 
 41             this.each(function(el){
 42 
 43                 el.style[prop]=val;
 44 
 45             });
 46 
 47             return this;
 48 
 49         },
 50 
 51         show:function(){
 52 
 53             var that=this;
 54 
 55             this.each(function(el){
 56 
 57                 that.setStyle('display','block');
 58 
 59             });
 60 
 61             return this;
 62 
 63             
 64 
 65         },
 66 
 67         addEvent:function(type,fn){
 68 
 69             var add=function(el){
 70 
 71                 if(window.addEventListener){
 72 
 73                     el.addEventListener(type,fn,false);
 74 
 75                 }else if(window.attachEvent){
 76 
 77                     el.attachEvent('on'+type,fn);
 78 
 79                     
 80 
 81                 }
 82 
 83             };
 84 
 85             this.each(function(el){
 86 
 87                 add(el)
 88 
 89             });
 90 
 91             return this;
 92 
 93         }
 94 
 95         
 96 
 97     };
 98 
 99     //the public interface
100 
101     window.$=function(){
102 
103         return new _$(els)
104 
105     }
106 
107 })()
108 
109 

 

如果你检查每个方法的最后一行,你会注意到他们都是以return this 结束。这个可以在方法之间传递对象。有了链的接口。你就以下面这种方式写代码了。

 

 1 $(window).addEvent('load',function(){
 2 
 3     $('test-1','test-2').show().
 4 
 5     setStyle('color','red').
 6 
 7     addEvent('click',function(e){
 8 
 9         $(this).setStyle('color','green');
10 
11     });
12 
13 })
14 

这样就为window对象在加载的时候绑定了一个事件,id为test-1和test-2的元素立即显示。他们内部的元素将被设置为红色。他们然后绑定了一个事件监听函数。当这个函数执行的时候将设置文字的颜色为绿色。

这种写法和jquery这个库很类似。这个接口也很接近。链的锚点是window对象或者是html元素。每一个操作都以锚点为中心。在上面是例子中,有两个链。一个是对于window对象的加载事件。另外是id为thes-1和test-2元素设置样式的事件。我们将在下一部分深入这种模式。