目录
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 了)

2435376960-5660f862299c3_articlex[1].png

一、 总体架构
;(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")构建的对象结构如下所示:\

4151887352-5b18d895282f1_articlex[1].png

<p> 
    <span class="span">1</span>
    <span class="span">2</span>
    <span class="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 src="prototype.js"></script>//1.包含jQuery之外的库(比如Prototype)
<script src="jquery.js"></script>//2.包含jQuery库取得对$的使用权
<script>
    jQuery.noConflict();//3.调用noConflict()方法,让出$,把控制权让给最先包含的库
</script>
<script src="myscript.js"></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脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它们
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++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如何移除元素的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 09:06 PM

标题:jQuery小技巧:快速修改页面所有a标签的文本在网页开发中,我们经常需要对页面中的元素进行修改和操作。在使用jQuery时,有时候需要一次性修改页面中所有a标签的文本内容,这样可以节省时间和精力。下面将介绍如何使用jQuery快速修改页面所有a标签的文本,同时给出具体的代码示例。首先,我们需要引入jQuery库文件,确保在页面中引入了以下代码:&lt

使用jQuery修改所有a标签的文本内容 使用jQuery修改所有a标签的文本内容 Feb 28, 2024 pm 05:42 PM

标题:使用jQuery修改所有a标签的文本内容jQuery是一款流行的JavaScript库,被广泛用于处理DOM操作。在网页开发中,经常会遇到需要修改页面上链接标签(a标签)的文本内容的需求。本文将介绍如何使用jQuery来实现这个目标,并提供具体的代码示例。首先,我们需要在页面中引入jQuery库。在HTML文件中添加以下代码:

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

如何判断jQuery元素是否具有特定属性?在使用jQuery操作DOM元素时,经常会遇到需要判断元素是否具有某个特定属性的情况。这种情况下,我们可以借助jQuery提供的方法来轻松实现这一功能。下面将介绍两种常用的方法来判断一个jQuery元素是否具有特定属性,并附上具体的代码示例。方法一:使用attr()方法和typeof操作符//判断元素是否具有特定属

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

jQuery是一种流行的JavaScript库,被广泛用于处理网页中的DOM操作和事件处理。在jQuery中,eq()方法是用来选择指定索引位置的元素的方法,具体使用方法和应用场景如下。在jQuery中,eq()方法选择指定索引位置的元素。索引位置从0开始计数,即第一个元素的索引是0,第二个元素的索引是1,依此类推。eq()方法的语法如下:$("s

See all articles