博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jQuery 源码解析二:jQuery.fn.extend=jQuery.extend 方法探究
阅读量:5140 次
发布时间:2019-06-13

本文共 4706 字,大约阅读时间需要 15 分钟。

      终于动笔开始 jQuery 源码解析第二篇,写文章还真是有难度,要把自已懂的表述清楚,要让别人听懂真的不是一见易事。

      在  一文,大致描述了 jQuery 源码整体大致架构,主要分为以下几个点:

      A 通过自执行函数,在内部将 jQuery (jQuery 为一个函数,同时,在 JS 中,函数也为对象)以 window.jQuery=window.$ 引入,供用户直接便可使用 $、jQuery 调用。

      B 以 C#、Java 为例,可知存在静态方法、对象方法区别,该原理类比 jQuery ,jQuery.xxx 相当于给为其增加静态方法,而 jQuery.fn.xxx 则可类比于相当于给其增加对象方法。

      C 在 jQuery 源码内部,巧妙运用原型,直接上代码:

jQuery = function( selector, context ) {    //  用户调用 jQuery 方法,即是以 jQuer.fn.init 为构造函数所创建的对象    return new jQuery.fn.init( selector, context, rootjQuery );};// 在 JS 中,所有函数对象默认将有 prototype 属性// 为 jQuery.prototype 另起一个简单的别名,即 jQuery.fn//  其中 jQuery.fn 内部包含 constructor 属性(重新将该函数指向 jQuery)、init 函数jQuery.fn = jQuery.prototype = {    constructor: jQuery,    init: function( selector, context, rootjQuery ){          .....          },     // Start with an empty selector    selector: "",    // The current version of jQuery being used    jquery: "1.8.3",   .....};//  关键一步,将 jQuery.fn.init 函数的 prototype属性 指向 jQuery.fn ,这一步相当重要jQuery.fn.init.prototype = jQuery.fn;JS 中通过原型实现继承,其中使用最简单的介绍,JS 中对象的 __proto__ 属性===该对象 constructor 的 prototype 属性, 在调用方法以及获取属性,首先在自身查找,然后,即沿着 __proto__ 属性查找(而其等于 该对象 constructor 的 prototype 属性), 如果还没找到,继续沿着对象的 __proto__ 的 __proto__ 一步一步往上查找,最终查找到 Object.prototype.__proto__ 为止,没有即返回 undefined.

    在 jQuery 源码中,同时,还大量包括扩展 jQuery 对象自身属性方法,以及扩展 jQuery.fn (jQuery.prototype)属性方法,而该些扩展功能,即通过 jQuery.fn.extend=jQuery.extend=function(){} 实现,

具体分析,请查看下述代码部分.  

jQuery.extend = jQuery.fn.extend = function () {    //  arguments 在 JS 可获取函数实际传入参数,其包含 length 属性    var src, copyIsArray, copy, name, options, clone,    //  可获取 arguments 类数组首个实参        target = arguments[0] || {},        i = 1,        length = arguments.length,        deep = false;   // 若传入首个实参为 boolean 值,则做相关逻辑处理    if ( typeof target === "boolean" ) {        deep = target;    //  将 target 重新赋值,如若首个实参为 boolean 值        target = arguments[i] || {};    // 同时,将 i 的值加 一,则为 i=2        i++;    }    // Handle case when target is a string or something (possible in deep copy)    // 首个实参类型不等于 object 并且不等于 function 类型,则做相关逻辑处理    if ( typeof target !== "object" && !jQuery.isFunction(target) ) {        target = {};    }    // extend jQuery itself if only one argument is passed    // 如若传入实参仅为一个,则做下方逻辑处理    if (i === length) {        // 将 target 重新赋值,如若 jQuery.extend 则此时 this =jQuery,        // 如若 jQuery.fn.extend ,则此时 this =jQuery.fn=jQuery.prototype         target = this;        // 同时,将 i 的值减一,则 i=0        i--;    }    // 如传入实参参数为 1 ,此时,扩展对象属性 this =jQuery,this=jQuery.fn=jQuery.prototype    // 如传入实参参数个数不为1,此时,将分为首个实参为 boolean 值,以及相关情况    for ( ; i < length; i++ ) {        // 首先,判断传入实际值是否为 undefined 、null         if ( (options = arguments[ i ]) != null ) {            //  再对传入实参值进行遍历操作,扩展对象属性            for (name in options) {                // 参考上方逻辑,如实参个数为1,则 target指向 this                 // 如若实参个数不为1 ,则 target 指向 argument[0]                 // 如若实参个数为 bool 值,则 target 指向 argument [1]                src = target[ name ];                copy = options[ name ];                //  判断需扩展对象与此时扩展属性进行比较,以防扩展对象与扩展属性相等,出现循环引用                if ( target === copy ) {                    continue;                }                //  如若首个参数值 boolean 值为 true 且扩展属性为 true 且 扩展属性为数组或者纯对象,进入深度复制逻辑处理                if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))) {                    // 如若是数组
//  jQuery.fn.extend(true,  { Name: "jack", age: 20, {Physics:30}}  ,{ Name: "jack",  {Math:40,English:100,Chinese:76}})  // jQuery.fn.extend( { Name: "jack", age: 20, {Physics:30}}  ,{ Name: "jack",  {Math:40,English:100,Chinese:76}})
if (copyIsArray) {
copyIsArray = false; // 若此时需扩展对象 target[name] 属性(数组)进行扩展 clone = src && jQuery.isArray(src) ? src : []; } // 如若扩展属性为纯对象 else {
clone = src && jQuery.isPlainObject(src) ? src : {}; } // 进行递归调用,进行属性扩展 target[ name ] = jQuery.extend( deep, clone, copy ); // 直接扩展对象属性 ,如果扩展属性不为 undefined ,target[name]=copy,直接扩展对象属性 } else if (copy !== undefined) { // jQuery.fn.extend({ Name: "jack", age: 20, {Math:30}} ,{ Name: "jack", age: 20, {Math:40,English:100,Chinese:76}}) target[ name ] = copy; } } } } // 最后,返回 target 对象 return target; };

        在 jQuery 源码中,可大量发现 jQuery.extend、jQuery.fn.extend 使用,而此时,为 jQuery对象、jQuery.fn ( jQuery.fn ) 进行方法属性扩展。

        最后,有一个问题,在 jQuery 大量的链式调用,实现原理如何?大家可联想一下,在 java、C# 中要实现这种调用,在一个类中,如何实现该种功能?在 Java、C# 中,在一个类中,每个方法逻辑写完后,最终都返回 this,是不是就可以实现该功能。当然,在 C# 中,现在已有扩展方法可实现该功能。

 

参考资料:http://www.cnblogs.com/chyingp/archive/2013/06/03/3115210.html

转载于:https://www.cnblogs.com/Lumia1020/p/5324407.html

你可能感兴趣的文章
Eclipse启动Tomcat端口占用
查看>>
建立索引
查看>>
php 中的魔术常量
查看>>
解释下浮动和它的工作原理?清除浮动的技巧
查看>>
改变命运的三个层次
查看>>
Command Line 3
查看>>
设计模式
查看>>
[ASP.NET]Treeview 控件显示服务端目录文件夹及文件
查看>>
dotnet core webapi +vue 搭建前后端完全分离web架构(一)
查看>>
maven打包时生成源代码
查看>>
GetLastError() 返回值含义
查看>>
浏览器的同源策略
查看>>
[转] iptables
查看>>
在Mac系统下如何恢复SourceTree全局忽略的文件
查看>>
设计模式之类关系
查看>>
10年后编程还有意义吗?(转自深氪)
查看>>
一个控件例子
查看>>
结对编程
查看>>
ADO.NET 非连接方式进行数据访问
查看>>
基础类-NSString
查看>>