搜尋
首頁web前端js教程jquery源碼的基本介紹

jquery源碼的基本介紹

Jul 09, 2018 pm 03:11 PM
jquery

這篇文章主要介紹了關於jquery原始碼學習一之概況,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

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能夠讓使用者的html頁面保持程式碼和html內容分離,也就是說,不用再在html裡面插入一堆js來呼叫指令了,只要定義id即可。

jquery大致可以分為 DOM 、 ajax 、選擇器 、 事件 、 動畫。當然jquery有13個模組之多,這裡的5個,是從另一個角度劃分的。

(令: jquery從2.0之後就不相容IE 6/7/8 了)

jquery源碼的基本介紹

一、整體架構
;(function(global, factory) {
    // 传入window可以将其作为一个局部变量使用,缩短了作用域链,大大加快执行速度
    factory(global);
}(typeof window !== "undefined" ? window : this, function(window, noGlobal) {
    // jquery方法
    var jQuery = function( selector, context ) {
        return new jQuery.fn.init( selector, context );
    };
    // jQuery.fn 是 jquery对象的原型对象
    jQuery.fn = jQuery.prototype = {};
    // 核心方法
    // 回调系统
    // 异步队列
    // 数据缓存
    // 队列操作
    // 选择器引
    // 属性操作
    // 节点遍历
    // 文档处理
    // 样式操作
    // 属性操作
    // 事件体系
    // AJAX交互
    // 动画引擎
    if ( typeof noGlobal === strundefined ) {
        window.jQuery = window.$ = jQuery;
    }

    return jQuery;
}));

關於上述程式碼,解釋如下:

  1. jQuery的整體程式碼包裹在一個立即執行的自呼叫匿名的函數中,這樣可以盡量減少和其他第三方函式庫的干擾;自動初始化這個函數,讓其只建構一次。

  2. 在上述程式碼最後,將jQuery物件加入到全域window上,並為之設定變數$,從而使得可以在外界存取jQuery;

  3. 為自呼叫匿名函數設定參數global,並傳入參數window,這樣一方面可以縮短作用域鏈,可以盡快存取到window;

  • # #自呼叫函數的原理(立即執行的自呼叫函數)

jQuery使用()將匿名函數括起來,然後後面再加一對小括號(包含參數列表)的目的,簡單來說就是小括號括起來後,就當作是一個表達式來處理,得到的就是一個
function 物件了。同時小括號也取得了這個函數的引用位置,然後傳入參數就可以直接執行了。
總結: 全域變數是魔鬼, 匿名函數可以有效的保證在頁面上寫入JavaScript,而不會造成全域變數的污染,透過小括號,讓其載入的時候立即初始化,這樣就形成了一個單例模式的效果因此只會執行一次。
(function( global, factory ) {

        // 因为jquery既要再普通环境下运行,也要再例如AMD、commonJs下运行,所以我们需要做不同的适应
        // node CommonJs规范
        if ( typeof module === "object" && typeof module.exports === "object" ) {
            module.exports = global.document ?
                factory( global, true ) :
                function( w ) {
                    if ( !w.document ) {
                            throw new Error( "jQuery requires a window with a document" );
                    }
                    return factory( w );
                };
        } else {
            // AMD
            factory( global );
        }


      // 传入参数(window和一个执行函数)  
    }(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
         
         // 【1】
         // 创建jQuery对象, 实际上是jQuery.fn.init所返回的对象
         var jQuery = function( selector, context ) {
              return new jQuery.fn.init( selector, context );
              // 如果调用new jQuery, 生成的jQuery会被丢弃,最后返回jQuery.fn.init对象
              // 因此可以直接调用jQuery(selector, context), 不需要使用new
              // 如果使用new jQuery()容易出现死循环
              // 我们平常使用 $() ,就是直接调用jquery函数了
         }

         // 【2】
         // 创建jQuery对象原型,为jQuery添加各种方法
         jQuery.fn = jQuery.prototype = {
             ...
         }    
         
         // 【3】
         // 在调用new jQuery.fn.init后, jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype
         // 相当于将所有jQuery.fn的方法都挂载到一开始jQuery函数返回的对象上
         // 这里就是jquery的一个独特之处了,非常的巧妙
         jQuery.fn.init.prototype = jQuery.fn;

         // 【4】
         // 创建jQuery.extend方法
         jQuery.extend = jQuery.fn.extend = function() {、
              ...
         }
     

        // 【5】
        // 使用jQuery.extend扩展静态方法
        jQuery.extend({});

        // 【6】
        // 为window全局变量添加$对象,在给window全局添加变量的时候很有可可能会导致变量命名冲突哦,我们之后会学习到如何处理这种命名冲突的解决方法
        if ( typeof noGlobal === strundefined ) {     // var strundefined = typeof undefined
            window.jQuery = window.$ = jQuery;
            
            // $('')
            // 同 jQuery('')
        }


        return jQuery;
    }));

二、 jQuery的類別數組物件
可以這麼理解,jquery主要的任務就是

取得DOM操作DOM

jQuery的入口都是透過$()來的,透過傳入不同的參數,實作了9種重載方法。

1. jQuery([selector,[context]])
2. jQuery(element)
3. jQuery(elementArray)
4. jQuery(object)
5. jQuery(jQuery object)
6. jQuery(html,[ownerDocument])
7. jQuery(html,[attributes])
8. jQuery()
9. jQuery(callback)

// 9种用法整体来说可以分三大块:选择器、dom的处理、dom加载。
  • 在jquery內部使用了一種類數組物件的形式,這也是為什麼我們取得到同一個class的許多DOM後,既能夠呼叫jquery的方法,又能通過數組的方式來處理每一個dom物件了(比如遍歷)。

範例嘍

透過$(".Class")建構的物件結構如下所示:\

jquery源碼的基本介紹#

<p> 
    <span>1</span>
    <span>2</span>
    <span>3</span>
</p>



console.log($('.span'));

// jQuery.fn.init(3) [span.span, span.span, span.span, prevObject: jQuery.fn.init(1), context: document, selector: ".span"]
// 0:span.span
// 1:span.span
// 2:span.span
// context:    document
// length: 3
// prevObject: jQuery.fn.init [document, context: document]
// selector:".span"
// __proto__:Object(0)
// 模拟一下
function Ajquery(selecter) {
    // 如果传入的不是一个对象,则将其转换为对象
    if(!(selecter instanceof Ajquery)) {
        return new Ajquery(selecter);
    }
    var elem = document.getElementById(/[^#].*/.exec(selector)[0]); // 获取id
    this[0] = elem;
    this.length = 1;
    this.context = document;
    this.selector = selector;
    this.get = function(num) {
        return this[num];
    }
    return this;
}


// 使用

$('#show2').append(Ajquery('#book').get(0));

// 因此 $('')获取到的就是一个类数组对象

jQuery的無new建構原理

我們在建構jQuery物件的時候,並沒有使用new來創建,但其實是在

jQuery方法的內部,我們使用了new,這樣就保證了當前對象內部就又了一個this對象,並且吧所有的屬性和方法的鍵值對都映射到this上了,所以既可以透過鍊式取值,也可以透過索引取值。 jquery除了實作了類別陣列結構, 方法的原型共享,也實作了靜態與實例的共用.

javascript就是

函數式語言,函數可以實現類,所以javascript不是一個嚴格的物件導向的語言。

  • 平常的情況

function ajquery(name){
    this.name = name;
}
ajquery.prototype = function(){
   say: function(){
        return this.name;
   } 
}

var a = new ajquery();

a.say();
  • #但是在jquery中卻不是這麼來的。 jQuery沒有使用new運行符將jQuery顯示的實例化,還是直接呼叫其函數

$().ready() 
$().noConflict()
  • 如果要實作不用new直接取得實例

var aQuery = function(selector, context) {
       return new aQuery(); // 直接new一下
}
aQuery.prototype = {
    name:function(){},
    age:function(){}
}
// 如果是上诉的样子,直接new aQuery()则会导致死循环。
  • 如何得到一个正确的实例呢,那么可以把jQuery类当作一个工厂方法来创建实例,把这个方法放到jQuery.prototye原型中,然后实例化这个方法,从而创建一个实例

// 下面就是jquery的写法了
jQuery = function( selector, context ) {
        return new jQuery.fn.init( selector, context, rootjQuery );
},

// 但是问题又来了,init中的this指向的是实例init的原型,就导师了jquery类的this分离了,
// 解决这个问题的方法是:

jQuery.fn.init.prototype = jQuery.fn;

以上就是jQuery无new构造的原理了

// 精简分析
var ajquery = function(name) {
  return new ajquery.prototype.init(name);
}

ajquery.prototype = {
  init: function(name) {
    this.name = name;
    return this;
  },
  get: function() {
    return this.name;
  },
  name: 'zjj'
}

ajquery.prototype.init.prototype = ajquery.prototype;//这里使得init内部的this跟ajquery类的this保持了一致。

console.log(ajquery('zmf').get()); // zmf

三、 ready和load事件

针对于文档的加载

// 一
$(function() {

})
// 二
$(document).ready(function() {

})

// 三
$(document).load(function() {

})

在上面我们看到了一个是ready一个是load,那么这两个有什么区别呢?

// 我们先来看一个写DOM文档的加载过程吧
1. html 解析
2. 加载外部引用脚本和外部样式
3. 解析执行脚本
4. 构造DOM原型  // ready
5. 加载图片等文件 
6. 页面加载完毕 // load
document.addEventListener("DOMContentLoaded", function () {
    console.log('DOMContentLoaded回调')
}, false);

// 当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完成加载。

window.addEventListener("load", function () {
    console.log('load事件回调')
}, false);

console.log('脚本解析一')

//测试加载
$(function () {
    console.log('脚本解析二')
})

console.log('脚本解析三')

// 观察脚本加载的顺序
// test.html:34 脚本解析一
// test.html:41 脚本解析三
// test.html:38 脚本解析二
// test.html:26 DOMContentLoaded回调
// test.html:30 load事件回调

看完上面的过程我们不难看出ready是在文档加载完毕也就是DOM创建完毕后执行的,而load则是在页面加载完毕之后才执行的。
二者唯一的区别就是中间加了一个图片的加载,,但是图片等外部文件的加载确实很慢的呢。

在平时种我们为了增加用户的体验效果,首先应该执行的是我们的处理框架的加载。而不是图片等外部文件的加载。我们应该越早处理DOM越好,我们不需要等到图片资源都加载后才去处理框架的加载,这样就能增加用户的体验了。

// 源码分析
jQuery.ready.promise = function( obj ) {
    if ( !readyList ) {
        readyList = jQuery.Deferred();
        if ( document.readyState === "complete" ) {
            // Handle it asynchronously to allow scripts the opportunity to delay ready
            setTimeout( jQuery.ready );
        } else {
            document.addEventListener( "DOMContentLoaded", completed, false );
            window.addEventListener( "load", completed, false );
        }
    }
    return readyList.promise( obj );
};

DOM文档是否加载完毕处理方法

  • DOMContentLoaded

当HTML文档内容加载完毕后触发,并不会等待图像、外部引用文件、样式表等的完全加载。

<script>
  document.addEventListener("DOMContentLoaded", function(event) {
      console.log("DOM fully loaded and parsed");
  });

  for(var i=0; i<1000000000; i++){
      // 这个同步脚本将延迟DOM的解析。
      // 所以DOMContentLoaded事件稍后将启动。
  } 
</script>

该事件的浏览器支持情况是在IE9及以上支持。

兼容不支持该事件的浏览器
  • readystatechange

在IE8中能够使用readystatechange来检测DOM文档是否加载完毕。

对于跟早的IE,可以通过每隔一段时间执行一次document.documentElement.doScroll("left")来检测这一状态,因为这条代码在DOM加载完毕之前执行时会抛出错误(throw an error)。

document.onreadystatechange = subSomething;//当页面加载状态改变的时候执行这个方法.

function subSomething() 
{ 
 if(document.readyState == "complete"){ //当页面加载状态为完全结束时进入 
              //你要做的操作。
    }
}

// 用这个可以做一下等待网站图片或者其他东西加载完以后的操作,比如加载时我们可以调用加载动画,当complete也就是加载完成时我们让加载动画隐藏,这样只是一个小例子。还是很完美的。
针对IE的加载检测

Diego Perini 在 2007 年的时候,报告了一种检测 IE 是否加载完成的方式,使用 doScroll 方法调用,详情可见http://javascript.nwbox.com/I...。
原理就是对于 IE 在非 iframe 内时,只有不断地通过能否执行 doScroll 判断 DOM 是否加载完毕。在上述中间隔 50 毫秒尝试去执行 doScroll,注意,由于页面没有加载完成的时候,调用 doScroll 会导致异常,所以使用了 try -catch 来捕获异常。
结论:所以总的来说当页面 DOM 未加载完成时,调用 doScroll 方法时,会产生异常。那么我们反过来用,如果不异常,那么就是页面DOM加载完毕了。

// Ensure firing before onload, maybe late but safe also for iframes
document.attachEvent( "onreadystatechange", completed );
// A fallback to window.onload, that will always work
window.attachEvent( "onload", completed );
// If IE and not a frame
// continually check to see if the document is ready
var top = false;
try {
    // 非iframe中
    top = window.frameElement == null && document.documentElement;
} catch(e) {}
if ( top && top.doScroll ) {
    (function doScrollCheck() {
        if ( !jQuery.isReady ) {
            try {
                // Use the trick by Diego Perini
                // http://javascript.nwbox.com/IEContentLoaded/
                top.doScroll("left");
            } catch(e) {
                // 每个50ms执行一次
                return setTimeout( doScrollCheck, 50 );
            }
            // 分离所有dom就绪事件
            detach();

            // and execute any waiting functions
            jQuery.ready();
        }
    })();
}
三、 解决$的冲突
  • $太火热,jQuery采用$作为命名空间,不免会与别的库框架或者插件相冲突。

解决方案–– noConflict函数

引入jQuery运行这个noConflict函数将变量$的控制权让给第一个实现它的那个库,确保jQuery不会与其他库的$对象发生冲突。
在运行这个函数后,就只能使用jQuery变量访问jQuery对象。例如,在要用到$("aaron")的地方,就必须换成jQuery("aaron"),因为$的控制权已经让出去了。

// jquery导入
jQuery.noConflict();
// 使用 jQuery
jQuery("aaron").show();
// 使用其他库的 $()

// 别的库导入
$("aaron").style.display = ‘block’;

这个函数必须在你导入jQuery文件之后,并且在导入另一个导致冲突的库之前使用。当然也应当在其他冲突的库被使用之前,除非jQuery是最后一个导入的。

(function(window, undefined) {
    var
        // Map over jQuery in case of overwrite
        // 设置别名,通过两个私有变量映射了 window 环境下的 jQuery 和 $ 两个对象,以防止变量被强行覆盖
        _jQuery = window.jQuery,
        _$ = window.$;
 
    jQuery.extend({
        // noConflict() 方法让出变量 $ 的 jQuery 控制权,这样其他脚本就可以使用它了
        // 通过全名替代简写的方式来使用 jQuery
        // deep -- 布尔值,指示是否允许彻底将 jQuery 变量还原(移交 $ 引用的同时是否移交 jQuery 对象本身)
        noConflict: function(deep) {
            // 判断全局 $ 变量是否等于 jQuery 变量
            // 如果等于,则重新还原全局变量 $ 为 jQuery 运行之前的变量(存储在内部变量 _$ 中)
            if (window.$ === jQuery) {
                // 此时 jQuery 别名 $ 失效
                window.$ = _$;
            }
            // 当开启深度冲突处理并且全局变量 jQuery 等于内部 jQuery,则把全局 jQuery 还原成之前的状况
            if (deep && window.jQuery === jQuery) {
                // 如果 deep 为 true,此时 jQuery 失效
                window.jQuery = _jQuery;
            }
 
            // 这里返回的是 jQuery 库内部的 jQuery 构造函数(new jQuery.fn.init())
            // 像使用 $ 一样尽情使用它吧
            return jQuery;
        }
    })
}(window)

使用实例:

<script></script>//1.包含jQuery之外的库(比如Prototype)
<script></script>//2.包含jQuery库取得对$的使用权
<script>
    jQuery.noConflict();//3.调用noConflict()方法,让出$,把控制权让给最先包含的库
</script>
<script></script>

让出$控制权后,需要使用jQuery方法时,则不能用$来调用了,要用jQuery。或者通过定义新的名称来代替$符号。

var jq=jQuery.noConflict();

另外还有一个技巧,可以再.ready()方法中使用$。它的回调函数可以接收一个参数,这个参数为jQuery对象本身,可以重新命名jQuery为$,这样也是不会造成冲突的。

jQuery.(document).ready(function($){
   //这里可以正常使用$ 
})

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

以上是jquery源碼的基本介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
Python vs. JavaScript:學習曲線和易用性Python vs. JavaScript:學習曲線和易用性Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Python vs. JavaScript:社區,圖書館和資源Python vs. JavaScript:社區,圖書館和資源Apr 15, 2025 am 12:16 AM

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

從C/C到JavaScript:所有工作方式從C/C到JavaScript:所有工作方式Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript引擎:比較實施JavaScript引擎:比較實施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

超越瀏覽器:現實世界中的JavaScript超越瀏覽器:現實世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

使用Next.js(後端集成)構建多租戶SaaS應用程序使用Next.js(後端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

如何使用Next.js(前端集成)構建多租戶SaaS應用程序如何使用Next.js(前端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

JavaScript:探索網絡語言的多功能性JavaScript:探索網絡語言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器