JQuery源码解析--callbacks

  1 (function (global, factory) {
  2     factory(global);
  3 })(this, function (window, noGlobal) {
  4     var rootjQuery;
  5     var class2type = {};
  6     var toString = class2type.toString;
  7     var arr = [];
  8     var indexOf = arr.indexOf;
  9     var myJQuery = function (selector, context) {
 10         return new myJQuery.fn.init(selector, context);
 11     };
 12
 13     myJQuery.fn = myJQuery.prototype = {
 14         constructor: myJQuery,//为撒指定
 15         length: 0,
 16         each: function (callback) {
 17             return myJQuery.each(this, callback);
 18         },
 19         pushStack: function (elems) {
 20             var ret = myJQuery.merge(this.constructor(), elems);
 21             ret.prevObject = this;
 22             ret.context = this.context;
 23             return ret;
 24         }
 25     };
 26
 27     myJQuery.extend = myJQuery.fn.extend = function () {
 28         var options, name, src, copy, target = arguments[0] || {}, length = arguments.length, i = 1;
 29         if (i === length) {
 30             target = this;
 31             i--;
 32         }
 33         for (; i < length; i++) {
 34             if ((options = arguments[i]) != null) {
 35                 for (name in options) {
 36                     src = target[name];
 37                     copy = options[name];
 38                     if (target === copy) {
 39                         continue;
 40                     }
 41
 42                     if (copy !== undefined) {
 43                         target[name] = copy;
 44                     }
 45                 }
 46             }
 47         }
 48         return target;
 49     };
 50
 51     function isArrayLike(obj) {
 52         var length = !!obj && "length" in obj && obj.length,
 53             type = myJQuery.type(obj);
 54         if (type === "function" || myJQuery.isWindow(obj)) {
 55             return false;
 56         }
 57
 58         return type === "array" || length === 0 ||
 59             typeof length === "number" && length > 0 && ( length - 1 ) in obj;
 60     }
 61
 62     myJQuery.extend({
 63         isWindow: function( obj ) {
 64             return obj != null && obj === obj.window;
 65         },
 66         //extend each,是一种静态方法 调用方式 myJQuery.each(.....)
 67         each: function (obj, callback) {
 68             var length, i = 0;
 69             if (isArrayLike(obj)) {
 70                 //如果是数组
 71                 length = obj.length;//设置的属性
 72                 for (; i < length; i++) {
 73                     if (callback.call(obj[i], i, obj[i]) === false) {
 74                         break;
 75                     }
 76                 }
 77             }
 78             else{
 79                 //如果是对象
 80                 for(i in obj){
 81                     if(callback.call(obj[i],i,obj[i])===false){
 82                         break;
 83                     }
 84                 }
 85             }
 86             return obj;
 87         },
 88         isFunction: function (obj) {
 89             return myJQuery.type(obj) === "function";
 90         },
 91         type: function (obj) {
 92             if (obj == null) {
 93                 return obj + "";
 94             }
 95
 96             // Support: Android<4.0, iOS<6 (functionish RegExp)
 97             /*return typeof obj === "object" || typeof obj === "function" ?
 98              class2type[toString.call(obj)] || "object" :
 99              typeof obj;*/
100             return typeof obj;
101         },
102         merge: function (first, second) {
103             var len = +second.length,
104                 j = 0,
105                 i = first.length;
106             for (; j < len; j++) {
107                 first[i++] = second[j];
108             }
109             first.length = i;
110             return first;
111         },
112         inArray: function (elem, arr, i) {
113             return arr == null ? -1 : indexOf.call(arr, elem, i);
114         }
115     });
116
117     myJQuery.fn.extend({
118         find: function (selector) {
119             var ret = [];
120             var arr = [12, 35, 68];
121             ret = this.pushStack(arr);
122             ret.selector = selector;
123             return ret;
124         }
125     });
126
127     var rnotwhite = (/\S+/g); //大s 非空白字符 小s 空白字符
128     ///g 表示该表达式将用来在输入字符串中查找所有可能的匹配,返回的结果可以是多个。如果不加/g最多只会匹配一个
129
130     function createOptions(options) {
131         var object = {};
132         //match 匹配成功,返回数组,否则 返回null
133         myJQuery.each(options.match(rnotwhite) || [], function (_, flag) {
134             object[flag] = true;
135         });
136         return object;
137     }
138
139     myJQuery.Callbacks = function (options) {
140         options = typeof  options === "string" ? createOptions(options) : myJQuery.extend({}, options);
141         var firing, memory, fired, locked, list = [], queue = [], firingIndex = -1;
142         var fire = function () {
143             locked = options.once;
144             for (; queue.length; firingIndex = -1) {
145                 memory = queue.shift();
146                 while (++firingIndex < list.length) {
147                     if(list[firingIndex].apply(memory[0], memory[1])===false && options.stopOnFalse===true){
148                         firingIndex=list.length;
149                         memory = false; //预防 参数里有 memory
150                     }
151                 }
152             }
153
154             //memory是一个全局变量,一直存在,而在add的时候,又有
155             // if(memory && !firing){ fire(); }
156             if(!options.memory){
157                 memory=false;
158             }
159
160             if (locked) {
161                 if (memory) {
162                     list=[];
163                 } else {
164                     list = "";
165                 }
166             }
167         };
168         var self = {
169             add: function () {
170                 if (list) {
171                     if (memory && !firing) {
172                         firingIndex = list.length - 1;
173                         queue.push(memory);
174                     }
175
176                     (function addSelf(args) {
177                         myJQuery.each(args, function (_, arg) {
178                             if (myJQuery.isFunction(arg)) {
179                                 if (!options.unique || !self.has(arg)) {
180                                     list.push(arg);
181                                 }
182                             } else if (arg && arg.length && myJQuery.type(arg) !== "string") {
183                                 //适用于 add([fn1,fn2]);
184                                 addSelf(arg);
185                             }
186                         });
187                     })(arguments);
188
189                     if(memory && !firing){
190                         //传入 memory关键字,在add的时候,将之前所有的fn fire 一次
191                         fire();
192                     }
193                     return this;
194                 }
195             },
196             remove: function () {
197                 myJQuery.each(arguments, function (_, arg) {
198                     var index = 0;
199                     while ((index = myJQuery.inArray(arg, list, index)) > -1) {
200                         list.splice(index, 1);
201                     }
202                 });
203                 return this;
204             },
205             has: function (fn) {
206                 return fn ? myJQuery.inArray(fn, list) > -1 : list.length > 0;
207             },
208             empty: function () {
209                 if (list) {
210                     list = [];
211                 }
212                 return this;
213             },
214             disable: function () {
215
216             },
217             disabled: function () {
218
219             },
220             lock: function () {
221
222             },
223             locked: function () {
224
225             },
226             fireWith: function (context, args) {
227                 //when options.once=true,the locked=true,and not fired
228                 if (!locked) {
229                     args = args || [];
230                     queue.push([context, args]);
231                     fire();
232                 }
233                 return this;
234             },
235             fire: function () {
236                 self.fireWith(this, arguments);
237                 return this;
238             },
239             fired: function () {
240
241             }
242         };
243         return self;
244     }
245     var init = myJQuery.fn.init = function (selector, context, root) {
246         if (!selector) {
247             return this;
248         }
249         root = root || rootjQuery;
250         //处理标签 div p li
251         if (typeof selector === "string") {
252             return ( context || root ).find(selector);
253         } else if (selector.nodeType) {
254             this.context = this[0] = selector;
255             this.length = 1;
256             return this;
257         }
258     };
259
260     init.prototype = myJQuery.fn;
261
262     rootjQuery = myJQuery(document);
263
264     if (!noGlobal) {
265         window.myJQuery = window.F$ = myJQuery;
266     }
267
268     return myJQuery;
269 });
时间: 2024-08-24 21:02:50

JQuery源码解析--callbacks的相关文章

jquery源码解析:代码结构分析

本系列是针对jquery2.0.3版本进行的讲解.此版本不支持IE8及以下版本. (function(){ (21, 94)     定义了一些变量和函数,   jQuery = function(){}; (96,283)   给jQuery对象添加一些属性和方法(实例方法,通过$("div")这类的jQuery实例对象来调用) (285,347)   extend : jQuery的继承方法 (349,817)   jQuery.extend():扩展一些工具方法(静态方法,直接通

jQuery源码解析(架构与依赖模块)第一章 理解架构

1-1 jQuery设计理念 引用百科的介绍: jQuery是继prototype之后又一个优秀的Javascript框架.它是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器(IE 6.0+, FF 1.5+, Safari 2.0+, Opera 9.0+),jQuery2.0及后续版本将不再支持IE6/7/8浏览器.jQuery使用户能更方便地处理HTML(标准通用标记语言下的一个应用).events.实现动画效果,并且方便地为网站提供AJAX交互.jQuery还有一个比较大的优势是,它

五.jQuery源码解析之jQuery.extend(),jQuery.fn.extend()

给jQuery做过扩展或者制作过jQuery插件的人这两个方法东西可能不陌生.jQuery.extend([deep],target,object1,,object2...[objectN]) jQuery.fn.extend([deep],target,object1,,object2...[objectN])这两个属性都是用于合并两个或多个对象的属性到target对象.deep是布尔值,表示是否进行深度合并,默认是false,不执行深度合并.通过这种方式可以在jQuery或jQuery.fn

十三.jQuery源码解析之$.type()

512行:出现了一个class2type. 在jQuery中全局搜索这个变量. 这段代码的意思是将一串字符串通过空格分割成数组,并且使用each遍历数组来初始化class2type. 最终的结果应该是这样的. { "[object Array]":"array", "[object Boolean]":"boolean", "[object Date]":"date", "[o

四.jQuery源码解析之jQuery.fn.init()的参数解析

从return new jQuery.fn.init( selector, context, rootjQuery )中可以看出 参数selector和context是来自我们在调用jQuery方法时传过来的.那么selector和context都有哪些可能. 对于表格中的4~9行中的可能做具体分析. 如果selector是字符串,则首先检测是html代码还是#id. 126行的if语句:以"<"开头,以">"结尾,且长度>=3.则假设额这个是HT

二.jQuery源码解析之构建jQuery之构建函数jQuery的7种用法

一:$(selectorStr[,限制范围]),接受一个选择器(符合jQuery规范的字符串),返回一个jQuery对象;二:$(htmlStr[,文档对象]),$(html[,json对象])传入html字符串,创建一个新的dom元素 三:$(dom元素),$(dom元素集合)将dom元素转换成jQuery对象.四:$(自定义对象)封装普通对象为jQuery对象.五:$(回调函数)绑定ready事件监听函数,当Dom加载完成时执行.六:$(jQuery对象)接受一个jQuery对象,返回一个j

八.jQuery源码解析之get()

理论上get是用来返回jQuery对象中部分或全部元素为数组的,但是转换为数组后,数组中的单个元素又是一个一个dom元素.所以get还有另外一个功效,就是将jQuery对象转换成dom对象.如果get中的参数为空了,则直接调用toArray();如果参数小于0,则表示从元素后面开始计算,如果num>0表示直接返回指定位置的元素. 八.jQuery源码解析之get(),布布扣,bubuko.com

十七.jQuery源码解析之入口方法Sizzle(1)

函数Sizzle(selector,context,results,seed)用于查找与选择器表达式selector匹配的元素集合.该函数是选择器引擎的入口. 函数Sizzle执行的6个关键步骤如下: 1.解析选择器表达式,解析出块表达式和关系符. 2.如果存在位置伪类,则从左向右查找: a.查找第一个块表达式匹配的元素集合,得到第一个上下文元素集合. b.遍历剩余的块表达式和块间关系符,不断缩小上下文元素集合. 3.否则从右向左查找: a.查找最后一个块表达式匹配的元素集合,得到候选集,映射集

十五.jQuery源码解析之Sizzle总体结构.htm

Sizzle是一款纯javascript实现的css选择器引擎,它具有完全独立,无库依赖;小;易于扩展和兼容性好等特点. W3C Selectors API规范定义了方法querySelector()和querySelectorAll(),但是IE6,7不支持这两个方法. 在Sizzele内部,如果浏览器支持方法querySelectorAll(),则调用该方法查找元素,如果不支持,则模拟该方法的行为. Sizzle支持几乎所有的css3选择器,并且会按照文档位置返回结果. 上面截取的只是Siz