|
復制代碼 代碼如下:
Prototype is a JavaScript framework that aims to ease development of dynamic web applications. Featuring a unique, easy-to-use toolkit for class-driven development and the nicest Ajax library around, Prototype is quickly becoming the codebase of choice for Web 2.0 developers everywhere.Ruby On Rails 中文社區的醒來貼了自己對于prototype的源碼解讀心得,頗有借鑒意義。
我喜歡Javascript,熱衷于 Ajax 應用。我把自己閱讀prototype源碼的體會寫下來,希望對大家重新認識 Javascript 有所幫助。
prototype.js 代碼:
復制代碼 代碼如下:
/**
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 * http://msdn.microsoft.com/library/en-us/script56/html/js56jsmthApply.ASP
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 }
JavaScript技術:[轉]prototype 源碼解讀 超強推薦第1/3頁,轉載需保留來源!
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。