1 js中的对象都是object,使用firebug查看都是Object:{}形式,js中的function默认返回的是this对象,任何代码只要知道this对象那么就比较容易的理解,jquery中绝大多数的this对象都是一个数组对象,可以广泛的支持设计的需要。
2 createDocumentFragment主要可以提高效率。可以配合缓存使用,这个主要是通过jquery对象的fragement属性来实现。
3 动态方法apply和call的广泛的使用和isFunction,isObject等方法的使用。
4 初始化中的new jQuery.fn.init中的 jQuery.fn为jQuery的prototype,方便闭包的实现和可扩展性,而且jQuery.fn.init.prototype=jQuery.fn,所以 jQuery.fn=== jQuery.prototype===jQuery.fn.init.prototype。
5 正则表达式的使用,靠,看了好久终于看懂了一些,比较的强大,对一些基本的操作进行了比较完美的分类。反正我是想不到啦。
6 var getData = function(elem, key){
return1 && 2 || null; //如果缓存里没有, 返回null
}
这里有点linux的味道,如果1和2都是true则返回2的结果,否则返回null
6 大量使用闭包,即匿名function,可以有效的减少js的冲突,增加可用性。
平时我们都是调用 click(func) 之类的函数, 而其实这些都是工具函数,真正和事件挂钩的函数是
jQuery.fn.bind - 调用 jQuery.event.add
jQuery.fn.unbind - 调用 jQuery.event.remove
jQuery.fn.trigger - 调用 jQuery.event.trigger
jQuery.fn.one - 调用 jQuery.fn.bind,Query.fn.unbind
要想知道jQuery的事件原理,必须读 jQuery.event.add
// 只对节点操作。
if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
return ;
}
// IE 无法传递 window,而是复制这个对象 。
if ( jQuery.isWindow( elem ) && ( elem !== window && ! elem.frameElement ) ) {
elem = window;
}
// 如果 handler === false, 也就是说就是阻止某事件,
// 这样只要 bind("evt", false); 就是阻止此事件。
if ( handler === false ) {
handler = returnFalse;
} else if ( ! handler ) {
return ;
}
// handleObjIn 是内部处理句柄, handleObj 是直接使用的处理句柄。
var handleObjIn, handleObj;
if ( handler.handler ) {
handleObjIn = handler;
handler = handleObjIn.handler;
}
// 为函数生成唯一的 guid 。具体下面介绍。
if ( ! handler.guid ) {
handler.guid = jQuery.guid ++ ;
}
// 获取一个节点的数据。
var elemData = jQuery.data( elem );
// 如果没有数据,则直接返回。
if ( ! elemData ) {
return ;
}
// 避免和原生的js对象混淆。
var eventKey = elem.nodeType ? " events " : " __events__ " ,
// 这里就是关键。
// elemData 是存储数据的位置, 而 elemData[ eventKey ] 就是存储当前事件的对象。 elemData.handle 就是当前绑定的所有函数数组。
// 也就是说,当我们绑定一个函数时,会往 elemData.handle 放这个函数,然后事件触发时,会遍历 elemData.handle 中函数然后去执行。
// 肯能有人会问,为什么这么做,因为原生的DOM内部也有一个 函数数组,事件触发后会执行全部函数。答案还是 兼容。
// 标准浏览器使用 addEventListener
// IE 使用 attachEvent
// 而这2者还是有差距的。因为 addEventListener 执行函数的顺序即添加函数的顺序,然而 attachEvent 执行函数的顺序和添加的顺序是相反的。
// jQuery 使用自定义的 handler 数组,好处有:
// 因为最后仅绑定一次原生事件,事件触发后,手动执行 数组中的函数。这样保证兼容。
// 同时也可以知道到底绑定了什么函数,可以方便 trigger 函数的完成。
events = elemData[ eventKey ],
eventHandle = elemData.handle;
// 一些功能。。
if ( typeof events === " function " ) {
eventHandle = events.handle;
events = events.events;
} else if ( ! events ) {
if ( ! elem.nodeType ) {
elemData[ eventKey ] = elemData = function (){};
}
elemData.events = events = {};
}
// 如果是第一次执行,需创建 eventHandle
if ( ! eventHandle ) {
// eventHandle 就是真正绑定到原生事件的那个函数,这个函数用来执行events.hadlers 用。
elemData.handle = eventHandle = function () {
// Handle the second event of a trigger and when
// an event is called after a page has unloaded
return typeof jQuery !== " undefined " && ! jQuery.event.triggered ?
jQuery.event.handle.apply( eventHandle.elem, arguments ) :
undefined;
};
}
// 绑定函数和原生,这样可以保证函数可执行为目前作用域。
eventHandle.elem = elem;
// 处理 jQuery(...).bind("mouseover mouseout", fn);
types = types.split( " " );
var type, i = 0 , namespaces;
while ( (type = types[ i ++ ]) ) {
handleObj = handleObjIn ?
jQuery.extend({}, handleObjIn) :
{ handler: handler, data: data };
// 略
// 绑定 type guid
handleObj.type = type;
if ( ! handleObj.guid ) {
handleObj.guid = handler.guid;
}
// 获取当前的函数数组。
var handlers = events[ type ],
special = jQuery.event.special[ type ] || {};
// 如果第一次,则创建这个数组。
if ( ! handlers ) {
handlers = events[ type ] = [];
// 特殊事件要执行 setup 而不是标准 addEventListener。
// 此行用来支持自定义的事件。
if ( ! special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
// 标准事件。 这里绑定的为 eventHandle
if ( elem.addEventListener ) {
elem.addEventListener( type, eventHandle, false );
} else if ( elem.attachEvent ) {
elem.attachEvent( " on " + type, eventHandle );
}
}
}
// 自定义事件,执行 add
if ( special.add ) {
special.add.call( elem, handleObj );
if ( ! handleObj.handler.guid ) {
handleObj.handler.guid = handler.guid;
}
}
// 不管是不是首次,都放入目前绑定的函数。
handlers.push( handleObj );
// 为实现 trigger 。
jQuery.event.global[ type ] = true ;
}
// 让IE下可以正常回收 elem 内存。
elem = null ;
},
8.2 事件对象
框架的义务当然也包括 事件参数的修复。jQuery 是自定义事件对象, 这个对象模拟真实事件对象。
根据上文可以知道,真正绑定事件的是一个函数,这个函数执行时会先 生成自定义事件对象, 然后把此对象作为参数调用所有的 handler 。
jQuery 自定义事件是 jQuery.Event 。 (代码 2583-2610 行)
// 支持 没有 new jQuery.Event
if ( ! this .preventDefault ) {
return new jQuery.Event( src );
}
// 略
}
// 处理字符串参数,分七种情形:
//①单个标签,带对象属性包 ---> jQuery.merge |
//②单个标签,不带对象属性包 ---> attr + jQuery.merge |
//③复杂的HTML片断 ---> buildFragment + jQuery.merge |
//④ID选择器,与找到的元素的ID不同 ---> getElementById + Sizzle + pushStack |
//⑤ID选择器,与找到的元素的ID相同 ---> getElementById + 简单属性添加 |
//⑥标签选择器 ---> getElementsByTagName + jQuery.merge |
//⑦其他CSS表达式 ---> Sizzle + pushStack