[转]prototype 源码解读 超强推荐第1/3页


/**   
2   
3  * 定义一个全局对象, 属性 Version 在发布的时候会替换为当前版本号   
4   
5  */   
6    
7 var Prototype = {    
8    
9   Version: '@@VERSION@@'   
10    
11 }    
12    
13    
14 /**   
15   
16  * 创建一种类型,注意其属性 create 是一个方法,返回一个构造函数。   
17   
18  * 一般使用如下   
19   
20  *     var X = Class.create();  返回一个类型,类似于 java 的一个   
21   
22  * Class实例。   
23   
24  * 要使用 X 类型,需继续用 new X()来获取一个实例,如同 java 的   
25   
26  * Class.newInstance()方法。   
27   
28  *   
29   
30  * 返回的构造函数会执行名为 initialize 的方法, initialize 是   
31   
32  * Ruby 对象的构造器方法名字。   
33   
34  * 此时initialize方法还没有定义,其后的代码中创建新类型时会建立   
35   
36  * 相应的同名方法。   
37   
38  *   
39   
40  * 如果一定要从java上去理解。你可以理解为用Class.create()创建一个   
41   
42  * 继承java.lang.Class类的类。   
43   
44  * 当然java不允许这样做,因为Class类是final的   
45   
46  *   
47   
48  */   
49    
50 var Class = {    
51    
52   create: function() {    
53    
54     return function() {    
55    
56       this.initialize.apply(this, arguments);    
57    
58     }    
59    
60   }    
61    
62 }    
63    
64    
65 /**   
66   
67  * 创建一个对象,从变量名来思考,本意也许是定义一个抽象类,以后创建   
68   
69  * 新对象都 extend 它。   
70   
71  * 但从其后代码的应用来看, Abstract 更多是为了保持命名空间清晰的考虑。   
72   
73  * 也就是说,我们可以给 Abstract 这个对象实例添加新的对象定义。   
74   
75  *   
76   
77  * 从java去理解,就是动态给一个对象创建内部类。   
78   
79  */   
80    
81 var Abstract = new Object();    
82    
83    
84 /**   
85   
86  * 获取参数对象的所有属性和方法,有点象多重继承。但是这种继承是动态获得的。   
87   
88  * 如:   
89   
90  *     var a = new ObjectA(), b = new ObjectB();   
91   
92  *     var c = a.extend(b);   
93   
94  * 此时 c 对象同时拥有 a 和 b 对象的属性和方法。但是与多重继承不同的是,   
95   
96  * c instanceof ObjectB 将返回false。   
97   
98  */   
99    
100 Object.prototype.extend = function(object) {    
101    
102   for (property in object) {    
103    
104     this[property] = object[property];    
105    
106   }    
107    
108   return this;    
109    
110 }    
111    
112    
113 /**   
114   
115  * 这个方法很有趣,它封装一个javascript函数对象,返回一个新函数对象,新函   
116   
117  * 数对象的主体和原对象相同,但是bind()方法参数将被用作当前对象的对象。   
118   
119  * 也就是说新函数中的 this 引用被改变为参数提供的对象。   
120   
121  * 比如:   
122   
123  * <input type="text" id="aaa" value="aaa">   
124   
125  * <input type="text" id="bbb" value="bbb">   
126   
127  * .................   
128   
129  * <script>   
130   
131  *     var aaa = document.getElementById("aaa");   
132   
133  *     var bbb = document.getElementById("bbb");   
134   
135  *     aaa.showValue = function() {alert(this.value);}   
136   
137  *     aaa.showValue2 = aaa.showValue.bind(bbb);   
138   
139  * </script>   
140   
141  *  那么,调用aaa.showValue 将返回"aaa",   
142   
143  *  但调用aaa.showValue2 将返回"bbb"。   
144   
145  *   
146   
147  * apply 是ie5.5后才出现的新方法(Netscape好像很早就支持了)。   
148   
149  * 该方法更多的资料参考MSDN   
150   
151  *    
152   
153  * 还有一个 call 方法,应用起来和 apply 类似。可以一起研究下。   
154   
155  */   
156    
157 Function.prototype.bind = function(object) {    
158    
159   var method = this;    
160    
161   return function() {    
162    
163     method.apply(object, arguments);    
164    
165   }    
166    
167 }    
168    
169    
170 /**   
171   
172  * 和bind一样,不过这个方法一般用做html控件对象的事件处理。所以要传递event对象   
173   
174  * 注意这时候,用到了 Function.call。它与 Function.apply 的不同好像仅仅是对参   
175   
176  * 数形式的定义。如同 java 两个过载的方法。   
177   
178  */   
179    
180 Function.prototype.bindAsEventListener = function(object) {    
181    
182   var method = this;    
183    
184   return function(event) {    
185    
186     method.call(object, event || window.event);    
187    
188   }    
189    
190 }    
191    
192    
193 /**   
194   
195  * 将整数形式RGB颜色值转换为HEX形式   
196   
197  */   
198    
199 Number.prototype.toColorPart = function() {    
200    
201   var digits = this.toString(16);    
202    
203   if (this < 16) return '0' + digits;    
204    
205   return digits;    
206    
207 }    
208    
209    
210 /**   
211   
212  * 典型 Ruby 风格的函数,将参数中的方法逐个调用,返回第一个成功执行的方法的返回值   
213   
214  */   
215    
216 var Try = {    
217    
218   these: function() {    
219    
220     var returnValue;    
221    
222    
223     for (var i = 0; i < arguments.length; i++) {    
224    
225       var lambda = arguments[i];    
226    
227       try {    
228    
229         returnValue = lambda();    
230    
231         break;    
232    
233       } catch (e) {}    
234    
235     }    
236    
237    
238     return returnValue;    
239    
240   }    
241    
242 }    
243    
244    
245 /*--------------------------------------------------------------------------*/   
246    
247    
248 /**   
249   
250  * 一个设计精巧的定时执行器   
251   
252  * 首先由 Class.create() 创建一个 PeriodicalExecuter 类型,   
253   
254  * 然后用对象直接量的语法形式设置原型。   
255   
256  *   
257   
258  * 需要特别说明的是 rgisterCallback 方法,它调用上面定义的函数原型方法bind,   
259   
260  * 并传递自己为参数。   
261   
262  * 之所以这样做,是因为 setTimeout 默认总以 window 对象为当前对象,也就是说,   
263   
264  * 如果 registerCallback 方法定义如下的话:   
265   
266  *     registerCallback: function() {   
267   
268  *         setTimeout(this.onTimerEvent, this.frequency * 1000);   
269   
270  *     }   
271   
272  * 那么,this.onTimeoutEvent 方法执行失败,因为它无法   
273   
274  * 访问 this.currentlyExecuting 属性。   
275   
276  * 而使用了bind以后,该方法才能正确的找到this,   
277   
278  * 也就是PeriodicalExecuter的当前实例。   
279   
280  */   
281    
282 var PeriodicalExecuter = Class.create();    
283    
284 PeriodicalExecuter.prototype = {    
285    
286   initialize: function(callback, frequency) {    
287    
288     this.callback = callback;    
289    
290     this.frequency = frequency;    
291    
292     this.currentlyExecuting = false;    
293    
294    
295     this.registerCallback();    
296    
297   },    
298    
299    
300   registerCallback: function() {    
301    
302     setTimeout(this.onTimerEvent.bind(this), this.frequency * 1000);    
303    
304   },    
305    
306    
307   onTimerEvent: function() {    
308    
309     if (!this.currentlyExecuting) {    
310    
311       try {    
312    
313         this.currentlyExecuting = true;    
314    
315         this.callback();    
316    
317       } finally {    
318    
319         this.currentlyExecuting = false;    
320    
321       }    
322    
323     }    
324    
325    
326     this.registerCallback();    
327    
328   }    
329    
330 }    
331    
332    
333 /*--------------------------------------------------------------------------*/   
334    
335    
336 /**   
337   
338  * 这个函数就 Ruby 了。我觉得它的作用主要有两个   
339   
340  * 1.  大概是 document.getElementById(id) 的最简化调用。   
341   
342  * 比如:$("aaa") 将返回上 aaa 对象   
343   
344  * 2.  得到对象数组   
345   
346  * 比如: $("aaa","bbb") 返回一个包括id为   
347   
348  * "aaa"和"bbb"两个input控件对象的数组。   
349   
350  */   
351    
352 function $() {    
353    
354   var elements = new Array();    
355    
356    
357   for (var i = 0; i < arguments.length; i++) {    
358    
359     var element = arguments[i];    
360    
361     if (typeof element == 'string')    
362    
363       element = document.getElementById(element);    
364    
365    
366     if (arguments.length == 1)    
367    
368       return element;    
369    
370    
371     elements.push(element);    
372    
373   }    
374    
375    
376   return elements;    
377    
378 } 

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wjdxfw.html