目錄
jQuery
首頁 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

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

jQuery引用方法詳解:快速上手指南 jQuery引用方法詳解:快速上手指南 Feb 27, 2024 pm 06:45 PM

jQuery引用方法詳解:快速上手指南jQuery是一個受歡迎的JavaScript庫,被廣泛用於網站開發中,它簡化了JavaScript編程,並為開發者提供了豐富的功能和特性。本文將詳細介紹jQuery的引用方法,並提供具體的程式碼範例,幫助讀者快速上手。引入jQuery首先,我們需要在HTML檔案中引入jQuery函式庫。可以透過CDN連結的方式引入,也可以下載

jQuery中如何使用PUT請求方式? jQuery中如何使用PUT請求方式? Feb 28, 2024 pm 03:12 PM

jQuery中如何使用PUT請求方式?在jQuery中,發送PUT請求的方法與發送其他類型的請求類似,但需要注意一些細節和參數設定。 PUT請求通常用於更新資源,例如更新資料庫中的資料或更新伺服器上的檔案。以下是在jQuery中使用PUT請求方式的具體程式碼範例。首先,確保引入了jQuery庫文件,然後可以透過以下方式發送PUT請求:$.ajax({u

深度剖析:jQuery的優勢與劣勢 深度剖析:jQuery的優勢與劣勢 Feb 27, 2024 pm 05:18 PM

jQuery是一款廣泛應用於前端開發的快速、小巧、功能豐富的JavaScript庫。自2006年發布以來,jQuery已成為眾多開發者的首選工具之一,但在實際應用中,它也不乏一些優點和缺點。本文將深度剖析jQuery的優勢與劣勢,並結合具體的程式碼範例進行說明。優點:1.簡潔的語法jQuery的語法設計簡潔明了,可以大幅提升程式碼的可讀性和編寫效率。比如,

jQuery小技巧:快速修改頁面所有a標籤的文本 jQuery小技巧:快速修改頁面所有a標籤的文本 Feb 28, 2024 pm 09:06 PM

標題:jQuery小技巧:快速修改頁面所有a標籤的文字在網頁開發中,我們經常需要對頁面中的元素進行修改和操作。使用jQuery時,有時候需要一次修改頁面中所有a標籤的文字內容,這樣可以節省時間和精力。以下將介紹如何使用jQuery快速修改頁面所有a標籤的文本,同時給出具體的程式碼範例。首先,我們需要引入jQuery庫文件,確保在頁面中引入了以下程式碼:&lt

jQuery如何移除元素的height屬性? jQuery如何移除元素的height屬性? Feb 28, 2024 am 08:39 AM

jQuery如何移除元素的height屬性?在前端開發中,經常會遇到需要操作元素的高度屬性的需求。有時候,我們可能需要動態改變元素的高度,而有時候又需要移除元素的高度屬性。本文將介紹如何使用jQuery來移除元素的高度屬性,並提供具體的程式碼範例。在使用jQuery操作高度屬性之前,我們首先需要了解CSS中的height屬性。 height屬性用於設定元素的高度

使用jQuery修改所有a標籤的文字內容 使用jQuery修改所有a標籤的文字內容 Feb 28, 2024 pm 05:42 PM

標題:使用jQuery修改所有a標籤的文字內容jQuery是一款受歡迎的JavaScript庫,被廣泛用於處理DOM操作。在網頁開發中,經常會遇到需要修改頁面上連結標籤(a標籤)的文字內容的需求。本文將介紹如何使用jQuery來實現這個目標,並提供具體的程式碼範例。首先,我們需要在頁面中引入jQuery庫。在HTML檔案中加入以下程式碼:

了解jQuery中eq的作用及應用場景 了解jQuery中eq的作用及應用場景 Feb 28, 2024 pm 01:15 PM

jQuery是一種流行的JavaScript庫,被廣泛用於處理網頁中的DOM操作和事件處理。在jQuery中,eq()方法是用來選擇指定索引位置的元素的方法,具體使用方法和應用場景如下。在jQuery中,eq()方法選擇指定索引位置的元素。索引位置從0開始計數,即第一個元素的索引是0,第二個元素的索引是1,依此類推。 eq()方法的語法如下:$("s

如何判斷jQuery元素是否具有特定屬性? 如何判斷jQuery元素是否具有特定屬性? Feb 29, 2024 am 09:03 AM

如何判斷jQuery元素是否具有特定屬性?在使用jQuery操作DOM元素時,常會遇到需要判斷元素是否具有某個特定屬性的情況。在這種情況下,我們可以藉助jQuery提供的方法來輕鬆實現這項功能。以下將介紹兩種常用的方法來判斷一個jQuery元素是否具有特定屬性,並附上具體的程式碼範例。方法一:使用attr()方法和typeof運算子//判斷元素是否具有特定屬

See all articles