几乎很难从jQuery分离其中的一部分功能。所以在这里我分享下应该读 jQuery 源码的一些成果,以及读源码的方法。啃代码是必须的。
1. 代码折叠是必须的。
因此必须在支持语法折叠的编辑器里打开源码。 根据折叠层次,我们可以很快知道: 所有 jQuery 的代码都在一个函数中:
<div> <span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">( window, undefined ) {<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> jQuery 代码</span><span style="COLOR: #008000"></span><span style="COLOR: #000000"><br><br>})(window);</span> </div>
这样可以避免内部对象污染全局。传入的参数1是 window, 参数2是 undefined , 加快js搜索此二对象的速度。
2. 接着打开第一级折叠。
可以发现 jQuery 代码是按这样顺序来组织:
- 定义 jQuery 函数 ( 代码 20 - 1081 行)
- 生成 jQuery.support (代码 1083 - 1276 行)
- 和 data 有关扩展 (代码 1279 - 1510 行)
- 和队列有关扩展 (代码 1514 - 1605 行)
- 和属性有关扩展 (代码 1609 - 1988 行)
- 和事件有关扩展 (代码 1993 - 3175 行)
- 内部的Sizzle CSS Selector Engine (代码 3183 - 4518 行)
- 和节点有关扩展 (代码 4520 - 5492 行)
- 和样式有关扩展 (代码 5497 - 5825 行)
- 和ajax有关扩展 (代码 5830 - 7172 行)
- 和效果有关扩展 (代码 7176 - 7696 行)
- 和定位有关扩展 (代码 7700 - 8065 行)
下面的模块可以用上面的模块,上面的模块不需要下面的模块
3. 定义 jQuery 函数 ( 代码 20 - 1081 行)
总的代码是这样的框架:
<div> <span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> jQuery </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">() {<br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 创建 jQuery 对象</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> jQuery </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">( selector, context ) {<br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 略</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br> };<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 创建 jQuery.fn 对象</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> jQuery.fn </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> jQuery.prototype </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> {<br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 略</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> };<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 声明 jQuery.extend </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> jQuery.extend </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> jQuery.fn.extend </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">() {<br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 略</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> };<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 使用 jQuery.extend 扩展自己</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> jQuery.extend({<br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 略</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br> });<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 浏览器方面的一些琐碎</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 略</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 定义全局对象</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> (window.jQuery </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> window.$ </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> jQuery);<br><br>})();</span> </div>
从这里知道: 平时所用的 $ 其实就是 jQuery 函数的别名。
3.1 jQuery对象 (代码 23 - 26 行)
jQuery对象似乎一直都是这东西:
<div> <span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> jQuery </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">( selector, context ) {<br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 实际上 jQuery 对象是 jQuery.fn.init 返回的。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> jQuery.fn.init( selector, context, rootjQuery );<br>} </span> </div>
这个函数表示: 要想知道函数 jQuery 是什么东西,必须看 jQuery.fn.init 对象。
同时这也解释了为什么写代码不需要 new jQuery。
再看第29行 - 97行, 都是一些变量声明,这些变量在下面的函数用到。提取变量的好处: 对正则节约编译的时间, 同时能在压缩的时候获得更小的结果。
3.2 jQuery.fn 对象 (代码 99 - 320 行)
这个fn 其实是 jQuery.prototype ,这也是为啥jQuery.fn 就是扩展 jQuery对象的唯一原因。
肯能有人会疑问, jQuery 返回 new jQuery.fn.init, 也就是说,平时的函数应该是 jQuery.fn.init.prototype 所有的成员,不是 jQuery.prototype 成员。当然原因也很简单: jQuery.fn.init.prototype === jQuery.prototype (代码 322 行)
jQuery 对js对象处理和中国人讲话一样绕。这里总结下到底 jQuery 对象是个什么家伙。
jQuery 是普通函数, 返回 jQuery.fn.init 对象的实例( new jQuery.fn.init() )。
然后 jQuery.fn === jQuery.prototype === jQuery.fn.init.prototype ,最后, jQuery返回的对象的成员和 jQuery.fn 的成员匹配。
jQuery.fn 下有很多成员,下面稍作介绍:
init - 初始化(下详细说明)
constructor - 手动指定一个构造函数。 因为默认是 jQuery.fn.init
length - 让这个对象更接近一个 原生的数组
size - 返回 length
toArray - 通过 Array.prototype slice 实现生成数组
get - 即 this[ num ] ,当然作了下 参数索引 的处理。
pushStack - 加入一个元素
ready - 浏览器加载后执行(下详细说明)
end - 通过保存的 prevObject 重新返回
each - 参考 http://www.cnblogs.com/Fooo/archive/2011/01/11/1932900.html
参考 http://www.cnblogs.com/rubylouvre/archive/2009/11/21/1607632.html
3.3 jQuery.fn.init (代码 101 - 211 行)
jQuery.fn.init 就是所谓的 $ 函数。 也就是说,平常的 $("#id") 就是 new jQuery.fn.init("#id");
这个函数很长,但代码覆盖率小。
<div> <span style="COLOR: #000000"> init: </span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">( selector, context, rootjQuery ) {<br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 参数: selector 选择器</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> context 上下文</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> rootjQuery 父节点</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 处理 $("")、 $(null) 和 $(undefined)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">selector ) {<br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">;<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 处理 $(DOMElement)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( selector.nodeType ) {<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 直接扔数组中, 就搞定了。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.context </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">] </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> selector;<br> </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.length </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">;<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 处理 $("body") body 元素只存在一次,单独找它</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( selector </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">body</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">context </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> document.body ) {<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 同样扔数组中, 顺便把 selector 更新更新。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.context </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> document;<br> </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">] </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> document.body;<br> thisis.selector </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">body</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br> </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.length </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">;<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 处理 $(HTML 代码 或者是 css 选择器) </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( </span><span style="COLOR: #0000ff">typeof</span><span style="COLOR: #000000"> selector </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">string</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> ) {<br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 略</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> <br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 处理 $(函数)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> } </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( jQuery.isFunction( selector ) ) {<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 如果是函数,则执行 $(document).ready , 这样 $(document).ready(func) 简为 $(func)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> rootjQuery.ready( selector );<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 略。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 如果传入的是一个 Dom列表 ( getElementsByTagName 结果 ) 则转为 jQuery 数组。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> jQuery.makeArray( selector, </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000"> );<br>}</span> </div>
<div> <span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 这部分代码是 上段中 略 的 也就是说是 jQuery(字符串) 处理。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 检查是否字符串是常用选择器 (/^(?:[^)[^>]*$|#([\w\-]+)$)/)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">match </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> quickExpr.exec( selector );<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 检查是否正确匹配</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( match </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> (match[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">] </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">context) ) {<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 处理: $(html) -> $(array)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( match[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">] ) {<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 获取正文,默认 document</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> context </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> context </span><span style="COLOR: #0000ff">instanceof</span><span style="COLOR: #000000"> jQuery </span><span style="COLOR: #000000">?</span><span style="COLOR: #000000"> context[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">] : context;<br> doc </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (context </span><span style="COLOR: #000000">?</span><span style="COLOR: #000000"> context.ownerDocument </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> context : document);<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 如果传入简单的 "", ( /^(?:)?$/)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> ret </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> rsingleTag.exec( selector );<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 返回 createElement("tag")</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> jQuery.merge( </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">, selector );<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 处理: $("#id")</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> } </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> {<br> elem </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> document.getElementById( match[</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">] );<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 因为有的浏览器 getElementById 不只返回 id匹配的,所以做检查。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">;<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 处理 $("标签")</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> } </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">context </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">rnonword.test( selector ) ) {<br> </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.selector </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> selector;<br> </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.context </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> document;<br> selector </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> document.getElementsByTagName( selector );<br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> jQuery.merge( </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">, selector );<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">处理: $(选择器, $(...))</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> } </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">context </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> context.jquery ) {<br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> (context </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> rootjQuery).find( selector );<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 处理: $(选择器, 上下文)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> (相当于: $(上下文).find(选择器)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> } </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> {<br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.constructor( context ).find( selector );<br> }</span> </div>
3.4 jQuery.fn.extend (代码 324 - 386 行)
这个函数用于 扩展函数
函数中含多个参数判断,为了使用可以更灵活。
基本原理就是for(in),这里不具体介绍了。
3.5 jQuery.noConflict (代码 389 - 399 行 )
<div> <span style="COLOR: #000000">noConflict: </span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">( deep ) {<br> window.$ </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> _$;<br><br> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( deep ) {<br> window.jQuery </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> _jQuery;<br> }<br><br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> jQuery;<br> },</span> </div>
不多解释了,就是让 jQuery 恢复为全局的对象。
3.6 jQuery.ready (代码 407 -381 行)
其中有2个函数:
jQuery.ready 触发执行 readyList 中的所有函数
jQuery.bindReady 初始化让 jQuery.ready 成功执行
<div> <span style="COLOR: #000000">bindReady: </span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">() {<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 如果已经执行 bindReady 则返回。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( readyBound ) {<br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;<br> }<br><br> readyBound </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 如果页面已经加载, 马上执行 jQuery.ready</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( document.readyState </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">complete</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> ) {<br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> setTimeout( jQuery.ready, </span><span style="COLOR: #000000">1</span><span style="COLOR: #000000"> );<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 标准浏览器支持 DOMContentLoaded</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( document.addEventListener ) {<br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 你懂的</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> document.addEventListener( </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">DOMContentLoaded</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, DOMContentLoaded, </span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000"> );<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 为什么还要 load ? , 因为有些时候 DOMContentLoaded 失败(如 iframe) ,而 load 总是会成功, 所以,同时处理 DOMContentLoaded load, 在 jQuery.ready 中会删除监听函数,保证最后这个函数只执行一次</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> window.addEventListener( </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">load</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, jQuery.ready, </span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000"> );<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> IE浏览器( IE 8 以下)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> } </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( document.attachEvent ) {<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 使用 onreadystatechange</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> document.attachEvent(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">onreadystatechange</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, DOMContentLoaded);<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 同理</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> window.attachEvent( </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">onload</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, jQuery.ready );<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 如果 IE 下且非 iframe, 这里有个技巧。 见 doScrollCheck();</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 原理: 浏览器在没加载时 设置 scrollLeft 会错误,所哟每隔1秒厕所 是否 scrollLeft 成功,如果发现成功,则执行 jQuery.ready 。但这只对非 frame 会有用。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> toplevel </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">;<br><br> </span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"> {<br> toplevel </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> window.frameElement </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;<br> } </span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">(e) {}<br><br> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( document.documentElement.doScroll </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> toplevel ) {<br> doScrollCheck();<br> }<br> }<br> },</span> </div>
bindReady 函数在执行 ready 时执行。(jQuery 1.4 之前版本都是 绝对执行,不管需不需要 ready 函数)
4. 生成 jQuery.support (代码 1083 - 1276 行)
人人都说 jQuery.support 是个好东西。确实,这东西可以解决很多兼容问题。
jQuery.support 是基于检测的浏览器兼容方式。也就是说,创建一个元素, 看这个元素是否符合一些要求。
比如测试元素是否支持checkOn属性,只要先 set check = 'on' 然后看浏览器是否 get check == 'on'。
此部分源码不具体介绍了。
5.和 data 有关扩展 (代码 1279 - 1510 行)
jQuery的 data() 用于存储一个字典。而这些数据最后都保存在 jQuery.cache ( 代码 1283 行) , 全局对象存在 windowData ( 代码 1279 行) 。
但如果正确根据对象找到其在 jQuery.cache 的存储对象? 这就是 expando 字符串。
比如一个对象: elem 。
满足: elem.expando = "jQuery12321";
那么 jQuery.cache["jQuery12321"] 就是存储这个 elem 数据的对象。
实际上, 不是 elem.expando 表示键值,而是 elem[ jQuery.expando ] 表示。
而一个对象数据又是一个字典,所以最后执行 jQuery.data(elem, 'events') 后就是:
jQuery.cache[elem[jQuery.expando]]['events'] 的内容 (jQuery.cache[elem[jQuery.expando]] = {} )
6.和队列有关扩展 (代码 1514 - 1605 行)
队列是 jQuery 1.5 新增的。
主要用于特效等需要等待执行的时候。
队列主要操作就是 进队queue 出队dequeue
jQuery 队列内的数据:
如果没有执行:
[将执行的1, 将执行的2]
现在开始执行 , 如果 type 为空或 "fx", 队列内数据:
["inprogress", 将执行的2]
执行完之后:
["将执行的2]
以上的这些数据都存在 jQuery.data(obj, (type || "fx") + "queue") (代码 1520 - 1522行)
jQuery.delay 则用于延时执行一个函数。相当于把原来队列更新为 setTImeout 后的结果。 (代码 1589 -1598 行)
7.和属性有关扩展 (代码 1609 - 1988 行)
从这里开始,需要了解一个函数jQuery.access。对于 attr ,css 之类的函数,如果需要返回值,只返回第一个元素的值,如果是设置值,则设置每个元素的值。这个神奇的效果就是 jQuery.access 搞定的。
jQuery.access代码在 794 - 819 行
jQuery大部分函数都是依赖 jQuery.access 实现的,比如有一个函数 XX,对用户而言,调用的是 jQuery.fn.XX, 而这个函数需要对多个元素(jQuery数组内的所有的节点) 操作,或者对1个元素操作, 通过 jQuery.access 转换(不一定都是),最后只写对1个元素的操作。这1个元素的操作往往是 jQuery.XX 函数,因此,我们往往能看到即存在 jQuery.XX, 又存在 jQuery.fn.XX, 而其实 jQuery.fn.XX 都是依靠 jQuery.XX 的,或者说jQuery.XX是底层函数, jQuery.fn.XX 是方便用户的工具 。
jQuery.fn.attr 这个函数(代码 1632 - 1634 行) 只有1句话,真正的实现是 jQuery.attr (代码 1880 - 1988)
又是一个大于100行的函数
<div> <span style="COLOR: #000000">attr: </span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">( elem, name, value, pass ) {<br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 检查是否为 nodeType 为 Element</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">elem </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> elem.nodeType </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">3</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> elem.nodeType </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">8</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> elem.nodeType </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">2</span><span style="COLOR: #000000"> ) {<br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> undefined;<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 如果这个属性需要特殊对待。 height/width/left 等属性需特殊计算</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( pass </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> name </span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000"> jQuery.attrFn ) {<br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> jQuery(elem)[name](value);<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 检查是否为 XML 还 HTML </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> notxml </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> elem.nodeType </span><span style="COLOR: #000000">!==</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">1</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">jQuery.isXMLDoc( elem ),<br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Whether we are setting (or getting)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> set </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> value </span><span style="COLOR: #000000">!==</span><span style="COLOR: #000000"> undefined;<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 修正名字, 比如 float 改 cssFloat</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> name </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> notxml </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> jQuery.props[ name ] </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> name;<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 只有在节点的时候执行。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( elem.nodeType </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">1</span><span style="COLOR: #000000"> ) {<br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 在 IE7- 下, href src 属性直接获取会返回绝对位置,而不是真实的位置字符串,</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 要获得它们的真实值,需要 elem.getAttribute("href", 2);</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> special </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> rspecialurl.test( name );<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Safari 误报默认选项。通过获取父元素的已选择索引来修复。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( name </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">selected</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">jQuery.support.optSelected ) {<br> </span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> parent </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> elem.parentNode;<br> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( parent ) {<br> parent.selectedIndex;<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 对 optgroups ,同理</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( parent.parentNode ) {<br> parent.parentNode.selectedIndex;<br> }<br> }<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 检查属性是否存在, 有些时候 name in elem 会失败,所以多次测试。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( (name </span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000"> elem </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> elem[ name ] </span><span style="COLOR: #000000">!==</span><span style="COLOR: #000000"> undefined) </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> notxml </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">special ) {<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 如果设置属性</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( set ) {<br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 在IE, 不能设置属性 type 。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( name </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">type</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> rtype.test( elem.nodeName ) </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> elem.parentNode ) {<br> jQuery.error( </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">type property can't be changed</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> );<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 如果 value === null, 表示移除属性</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( value </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000"> ) {<br> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( elem.nodeType </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">1</span><span style="COLOR: #000000"> ) {<br> elem.removeAttribute( name );<br> }<br><br> } </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> {<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 一切属性设置就是1句话。。。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> elem[ name ] </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> value;<br> }<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 表单索引元素获取需要 getAttributeNode( name ).nodeValue</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( jQuery.nodeName( elem, </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">form</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> ) </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> elem.getAttributeNode(name) ) {<br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> elem.getAttributeNode( name ).nodeValue;<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> elem.tabIndex 特殊处理</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( name </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">tabIndex</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> ) {<br> </span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> attributeNode </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> elem.getAttributeNode( </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">tabIndex</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> );<br><br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> attributeNode </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> attributeNode.specified </span><span style="COLOR: #000000">?</span><span style="COLOR: #000000"><br> attributeNode.value :<br> rfocusable.test( elem.nodeName ) </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> rclickable.test( elem.nodeName ) </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> elem.href </span><span style="COLOR: #000000">?</span><span style="COLOR: #000000"><br> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000"> :<br> undefined;<br> }<br><br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> elem[ name ];<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 处理 style 属性</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">jQuery.support.style </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> notxml </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> name </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">style</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> ) {<br> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( set ) {<br> elem.style.cssText </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">""</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> value;<br> }<br><br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> elem.style.cssText;<br> }<br><br> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( set ) {<br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 这里除了 IE, 其它属性使用标准 setAttribute </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> elem.setAttribute( name, </span><span style="COLOR: #000000">""</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> value );<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 如果属性不存在,返回 undefined, 而不是 null 或 "" 之类的。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">elem.attributes[ name ] </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> (elem.hasAttribute </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">elem.hasAttribute( name )) ) {<br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> undefined;<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 见上</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> attr </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">jQuery.support.hrefNormalized </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> notxml </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> special </span><span style="COLOR: #000000">?</span><span style="COLOR: #000000"><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Some attributes require a special call on IE</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> elem.getAttribute( name, </span><span style="COLOR: #000000">2</span><span style="COLOR: #000000"> ) :<br> elem.getAttribute( name );<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 同上</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> attr </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">?</span><span style="COLOR: #000000"> undefined : attr;<br> }<br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 如果不是 DOM 元素,检查处理。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( set ) {<br> elem[ name ] </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> value;<br> }<br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> elem[ name ];<br> }</span> </div>
8.和事件有关扩展 (代码 1993 - 3175 行)
8.1 事件
平时我们都是调用 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 (代码 2012 - 2155 行)
<div> <span style="COLOR: #000000">追加: </span><span style="COLOR: #0000ff">関数</span><span style="COLOR: #000000">(elem、types、handler、data) {<br><br> </span><span style="COLOR: #008000">/ /</span><span style="COLOR: #008000"> はノード上でのみ動作します。 </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( elem.nodeType </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span> <span style="COLOR: #000000">3</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> elem.nodeType </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">8</span><span style="COLOR: #000000"> ) {<br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> IE はできません代わりにウィンドウを渡すとオブジェクトがコピーされます。 </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( jQuery.isWindow( elem ) </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> ( elem </span><span style="COLOR: #000000">!==</span><span style="COLOR: #000000"> ウィンドウ </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">elem.frameElement ) ) {<br> elem </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> window;<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> handler === false の場合、つまりイベントを防ぐということは、 </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> このように、bind("evt", false である限り) ); このイベントを防ぎます。 </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( ハンドラー </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000"> ) {<br> ハンドラー </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> returnFalse;<br> } </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">ハンドラー) {<br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;<br> }<br> <br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> handleObjIn は内部処理ハンドル、handleObj は直接使用される処理ハンドルです。 </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> handleObjIn, handleObj;<br><br> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( handler.handler ) {<br> handleObjIn </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> ハンドラー;<br> ハンドラー </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> handleObjIn.handler;<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 関数の一意の GUID を生成します。以下に詳細を紹介します。 </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">handler.guid ) {<br> handler.guid </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> jQuery.guid</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">;<br> }<br><br> </span><span style="COLOR: #008000">// </span><span style="COLOR: #008000"> ノードのデータを取得します。 </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> elemData </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> jQuery.data( elem );<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> データがない場合は直接リターンします。 </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">elemData ) {<br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ネイティブ JS オブジェクトとの混同を避けてください。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">eventKey </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> elem.nodeType </span><span style="COLOR: #000000">?</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">イベント</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> : </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">__events__ </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ここが鍵です。 </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> elemData はデータが保存される場所であり、elemData[eventKey] は現在のデータを保存するオブジェクトですイベント。 elemData.handle は、現在バインドされているすべての関数の配列です。 </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> つまり、関数をバインドするときに、この関数を elemData.handle に置きます。イベントがトリガーされると、elemData.handle 内の関数が走査されて実行されます。 </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ネイティブ DOM の内部にも関数とイベントの配列があるため、なぜこれが行われるのか疑問に思う人もいるかもしれません。すべての機能はトリガー後に実行されます。答えはまだ互換性があります。 </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 標準ブラウザは addEventListener を使用します</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> IE はattachEvent</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> を使用しており、これら 2 つはまだ存在しますギャップです。 addEventListener が関数を実行する順序は関数が追加された順序ですが、attachEvent が関数を実行する順序は関数が追加された順序と逆であるためです。 </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> jQuery はカスタム ハンドラー配列を使用します: </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> ネイティブ イベントは 1 回だけバインドされるため、イベントがトリガーされた後、配列内の関数が手動で実行されます。これにより互換性が確保されます。 </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 同時に、どの関数がバインドされているかを知ることもでき、これにより、トリガー機能。 </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br> イベント </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> elemData[eventKey ],<br>eventHandle </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> elemData.handle;<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> いくつかの関数。 。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( </span><span style="COLOR: #0000ff"></span><span style="COLOR: #000000"> イベントの種類 </span><span style="COLOR: #000000">= ==</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">関数</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> ) {<br>eventHandle </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> events.handle;<br> events </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> events.events;<br><br> } </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">イベント ) {<br> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">elem.nodeType ) { <br> elemData[eventKey ] </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> elemData </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">関数</span><span style="COLOR: #000000">(){};<br> }<br><br> elemData.events </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> イベント </span><span style="COLOR: #000000">= </span><span style="COLOR: #000000"> {};<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 初めて実行する場合は、eventHandle</span> を作成する必要があります<span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">eventHandle ) {<br><br> </span><span style="COLOR: #008000"> //</span><span style="COLOR: #008000">eventHandle は、実際にネイティブ イベントにバインドされる関数です。この関数は events.hadlers を実行するために使用されます。 </span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> elemData.handle </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> イベントハンドル </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">() {<br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> トリガーの 2 番目のイベントと when</span><span style="COLOR: #008000"><br></span> <span style="COLOR: #000000"></span>//<span style="COLOR: #008000"></span> ページがアンロードされた後にイベントが呼び出されます<span style="COLOR: #008000"></span><span style="COLOR: #008000"><br></span> <span style="COLOR: #000000"></span>return<span style="COLOR: #0000ff"> </span> <span style="COLOR: #000000"></span>typeof<span style="COLOR: #0000ff"></span> jQuery <span style="COLOR: #000000"></span>!==<span style="COLOR: #000000"></span> <span style="COLOR: #000000"></span>"<span style="COLOR: #000000"></span>未定義<span style="COLOR: #000000"></span>"<span style="COLOR: #000000"></span> <span style="COLOR: #000000"></span>&&<span style="COLOR: #000000"></span> <span style="COLOR: #000000"></span>!<span style="COLOR: #000000"></span>jQuery.event.triggered <span style="COLOR: #000000"></span>?<span style="COLOR: #000000"> </span><span style="COLOR: #000000"> jQuery.event.handle.apply(eventHandle.elem, argument ) :<br> 未定義;<br> };<br> }<br><br> <br></span>//<span style="COLOR: #008000"></span> 関数とネイティブをバインドして、関数が現在のスコープで実行可能であることを確認します。<span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> eventHandle.elem </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> elem;<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 处理 jQuery(...).bind("mouseover mouseout", fn);</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> types </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> types.split(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><br> </span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> type, i </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">, namespaces;<br><br> </span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000"> ( (type </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> types[ i</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000"> ]) ) {<br> handleObj </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> handleObjIn </span><span style="COLOR: #000000">?</span><span style="COLOR: #000000"><br> jQuery.extend({}, handleObjIn) :<br> { handler: handler, data: data };<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 略</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> <br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 绑定 type guid</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> handleObj.type </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> type;<br> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">handleObj.guid ) {<br> handleObj.guid </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> handler.guid;<br> }<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 获取当前的函数数组。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> handlers </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> events[ type ],<br> special </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> jQuery.event.special[ type ] </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> {};<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 如果第一次,则创建这个数组。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">handlers ) {<br> handlers </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> events[ type ] </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> [];<br><br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 特殊事件要执行 setup 而不是标准 addEventListener。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 此行用来支持自定义的事件。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">special.setup </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> special.setup.call( elem, data, namespaces, eventHandle ) </span><span style="COLOR: #000000">===</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000"> ) {<br> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 标准事件。 这里绑定的为 eventHandle</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( elem.addEventListener ) {<br> elem.addEventListener( type, eventHandle, </span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000"> );<br><br> } </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ( elem.attachEvent ) {<br> elem.attachEvent( </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">on</span><span style="COLOR: #000000">"</span><s></s> </div>

PythonとJavaScriptの主な違いは、タイプシステムとアプリケーションシナリオです。 1。Pythonは、科学的コンピューティングとデータ分析に適した動的タイプを使用します。 2。JavaScriptは弱いタイプを採用し、フロントエンドとフルスタックの開発で広く使用されています。この2つは、非同期プログラミングとパフォーマンスの最適化に独自の利点があり、選択する際にプロジェクトの要件に従って決定する必要があります。

PythonまたはJavaScriptを選択するかどうかは、プロジェクトの種類によって異なります。1)データサイエンスおよび自動化タスクのPythonを選択します。 2)フロントエンドとフルスタック開発のためにJavaScriptを選択します。 Pythonは、データ処理と自動化における強力なライブラリに好まれていますが、JavaScriptはWebインタラクションとフルスタック開発の利点に不可欠です。

PythonとJavaScriptにはそれぞれ独自の利点があり、選択はプロジェクトのニーズと個人的な好みに依存します。 1. Pythonは、データサイエンスやバックエンド開発に適した簡潔な構文を備えた学習が簡単ですが、実行速度が遅くなっています。 2。JavaScriptはフロントエンド開発のいたるところにあり、強力な非同期プログラミング機能を備えています。 node.jsはフルスタックの開発に適していますが、構文は複雑でエラーが発生しやすい場合があります。

javascriptisnotbuiltoncorc;それは、解釈されていることを解釈しました。

JavaScriptは、フロントエンドおよびバックエンド開発に使用できます。フロントエンドは、DOM操作を介してユーザーエクスペリエンスを強化し、バックエンドはnode.jsを介してサーバータスクを処理することを処理します。 1.フロントエンドの例:Webページテキストのコンテンツを変更します。 2。バックエンドの例:node.jsサーバーを作成します。

PythonまたはJavaScriptの選択は、キャリア開発、学習曲線、エコシステムに基づいている必要があります。1)キャリア開発:Pythonはデータサイエンスとバックエンド開発に適していますが、JavaScriptはフロントエンドおよびフルスタック開発に適しています。 2)学習曲線:Python構文は簡潔で初心者に適しています。 JavaScriptの構文は柔軟です。 3)エコシステム:Pythonには豊富な科学コンピューティングライブラリがあり、JavaScriptには強力なフロントエンドフレームワークがあります。

JavaScriptフレームワークのパワーは、開発を簡素化し、ユーザーエクスペリエンスとアプリケーションのパフォーマンスを向上させることにあります。フレームワークを選択するときは、次のことを検討してください。1。プロジェクトのサイズと複雑さ、2。チームエクスペリエンス、3。エコシステムとコミュニティサポート。

はじめに私はあなたがそれを奇妙に思うかもしれないことを知っています、JavaScript、C、およびブラウザは正確に何をしなければなりませんか?彼らは無関係であるように見えますが、実際、彼らは現代のウェブ開発において非常に重要な役割を果たしています。今日は、これら3つの間の密接なつながりについて説明します。この記事を通して、JavaScriptがブラウザでどのように実行されるか、ブラウザエンジンでのCの役割、およびそれらが協力してWebページのレンダリングと相互作用を駆動する方法を学びます。私たちは皆、JavaScriptとブラウザの関係を知っています。 JavaScriptは、フロントエンド開発のコア言語です。ブラウザで直接実行され、Webページが鮮明で興味深いものになります。なぜJavascrを疑問に思ったことがありますか


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

AtomエディタMac版ダウンロード
最も人気のあるオープンソースエディター

SublimeText3 英語版
推奨: Win バージョン、コードプロンプトをサポート!

ドリームウィーバー CS6
ビジュアル Web 開発ツール

EditPlus 中国語クラック版
サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

DVWA
Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、
