文章出處
文章列表
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> 1.add的參數兼容,比如cb.add(fn1).add(fn2)等同于add(fn1,fn2)等同于add([fn1,fn2])。 2.$.Callbacks("memory"),第一次fire,執行之前的函數隊列。fire之后add的時候,就執行加入的函數。 3.$.Callbacks("unique"),add的時候判斷當前函數,是否已存于執行隊列中。 4.$.Callbacks("once"),第一次fire的時候,打個標記表明once了。第二次fire的時候,有once,就不執行隊列。 5.$.Callbacks("stopOnFalse"),判斷執行隊列中函數的執行結果,為false,則中斷函數隊列的遍歷執行。 6.$.Callbacks("memory once"),字符串對象化,使得字符串順序變換也沒關系。之后各回各家,該干嘛干嘛去。 7.$.Callbacks是一個對象工廠。 8.$.Callbacks的lock和disable的區別。lock只是不再add,但還能fire。disable不僅不能add,連fire也不行。 9.$.Callbacks的remove方法,就是從隊列去除指定函數。 10.fire的時候可以指定上下文 </body> <script type="text/javascript"> function showType(type, obj) { var clas = Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); return obj !== undefined && obj !== null && clas === type; } var $={}; // 依賴 類型判斷showType,遍歷處理 $.Callbacks = function(strArg){ var list = []; var fired_flag=false; var lock_flag=false ,disable_flag = false; var str_list = strArg.split(" "); var fire_args = []; var cbArg_obj = { "once":false, "unique":false, "memory":false, "stopOnFalse":false }; for(var i=0,l=str_list.length; i<l; i++){ cbArg_obj[str_list[i]] = true; } var once_flag = cbArg_obj["once"], unique_flag= cbArg_obj["unique"], memory_flag= cbArg_obj["memory"], stopOnFalse_flag= cbArg_obj["stopOnFalse"]; var self = { "add":function(){ if(lock_flag || disable_flag){ return; } // 參數兼容 var arg = arguments; (function add(arg){ for(var i=0,l = arg.length; i< l; i++){ var argItem = arg[i]; if(list.indexOf(argItem)>-1 && unique_flag){ return; } if(showType("function",argItem) ){ list.push(argItem); if(memory_flag && fired_flag){ argItem.apply(null,fire_args); } } else if(showType("array",argItem)){ add(argItem); } } })(arg); // 為了鏈性調用 return this; }, "fire":function(){ if( (once_flag && fired_flag) || disable_flag){ return; } if(arguments.length){ fire_args = arguments || []; } for(var i =0,l= list.length; i< l; i++){ if( (list[i].apply(this,fire_args) == false) && stopOnFalse_flag){ break; } } fired_flag = true; }, "remove":function(fn){ for(var i=0,l= list.length; i<l; i++){ if(list[i] == fn){ list.splice(i,1); } } }, "lock":function(){ lock_flag = true; }, "disable":function(){ disable_flag = true; } }; return self; }; function fn1(){ alert(1); } function fn2(){ alert(2); } function fn3(){ alert(3); } function fn4(){ alert(4); } function fnThis(arg){ alert(arg); } function fnFalse(){ return false; } var cb = $.Callbacks("once memory"); cb.add(fn1).add(fn2).add(fn4); cb.fire("hi"); cb.add(fnThis); cb.fire("aaa"); </script> </html>
源代碼閱讀這件事:
第一步,查看API。先明白這些API怎么用,因為API就是這些代碼的需求。
第二步,思考為什么這么寫。一個需求實現,可以有多種實現方式。但是作者偏偏用這種,是為了代碼性能優化、解耦,抑或偷懶?
第三步,自己重新實現。有時候,第二步你怎么想,也想不出作者這樣寫的原因。自己動手重新實現,實現過程中,才更能理解作者的用心。
文章列表
全站熱搜