博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jQuery源码浅析
阅读量:4573 次
发布时间:2019-06-08

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

这几天看了下jQuery源码,有些收获,解答了我以前对jQuery的疑问,现在我把收获分享给大家。

、jQuery为何弄成自执行函数,以及为何在引用了jquery文件之后,可以通过$或jQuery来调用其方法

(function (window, undefined) {....})(window);$.isFunction();

   1) 弄成自执行函数: 防止在这里边 var 定义的变量,属于这个函数域内的局部变量,避免污染全局,只在后面暴露 $ 和 jQuery 这 2 个变量给外界,尽量的避开变量冲突。

     2)可以通过$或jQuery来调用:在jQuery源码里有这么一句,将jQuery赋值给window下的jQuery和window下的.$

window.jQuery = window.$ = jQuery;

、为什么需要加上undefined当做参数?

(function (window, undefined) {....})(window);

   jQuery内部有用到undefined作为判断条件,如果在外部改变了undefined的值,会影响jQuery内部判断,所以参数里加上undefined就是确保undefined就是undefined,为什么这么说?在早期浏览器全局的undefined是可以被赋值的,可以当做变量使用,比如IE9以下,不过在新版浏览器里则没有这个问题,观察jQuery2.0+发现没有出现把undefined作为参数传递,因为2.0+不再支持IE9以下浏览器了。

、为何不用new就能调用jQuery的原型方法,比如$("#id").val()

1 (function (window, undefined) { 2     var 3     // ... 4     jQuery = function (selector, context) { 5         //实例化方法 jQuery() 实际上是调用了原型方法 jQuery.fn.init 6         return new jQuery.fn.init(selector, context, rootjQuery); 7     }; 8     // jQuery.prototype 即是 jQuery 的原型,挂载在上面的方法,即可让所有生成的 jQuery 对象使用 9     jQuery.fn = jQuery.prototype = {10         // 实例化化方法,这个方法可以称作 jQuery 对象构造器11         init: function (selector, context, rootjQuery) {12             // ...13         }14     }15     //这里将jQuery的原型赋值给init原型,让init实例化之后可以调用jQuery的原型方法16     //这也就是为什么实例化init可以调用jQuery的原型val()方法 比如:$("#id").val()17     jQuery.fn.init.prototype = jQuery.fn;18 })(window);

、jQuery.fn.extend 与 jQuery.extend有什么区别

     1)jQuery.extend(object) 为扩展 jQuery 类本身,为类添加新的静态方法;

   2)jQuery.fn.extend(object) 给 jQuery 对象添加实例方法,也就是通过这个 extend 添加的新方法,实例化的 jQuery 对象都能使用,因为它是挂载在 jQuery.fn 上的方法(jQuery.fn =jQuery.prototype )。 

   官方解释是:

   1)jQuery.extend(): 把两个或者更多的对象合并到第一个当中,

   2)jQuery.fn.extend():把对象挂载到 jQuery 的 prototype 属性,来扩展一个新的 jQuery 实例方法。

     使用 jQuery.extend() 扩展的静态方法,我们可以直接使用 $.xxx 进行调用(xxx是扩展的方法名),像c#中的静态方法。

   而使用 jQuery.fn.extend() 拓展的实例方法,需要使用 $().xxx 调用,像c#中的实例方法。

1 // 扩展合并函数 2 // 合并两个或更多对象的属性到第一个对象中,jQuery 后续的大部分功能都通过该函数扩展 3 // 虽然实现方式一样,但是要注意区分用法的不一样,那么为什么两个方法指向同一个函数实现,但是却实现不同的功能呢, 4 // 阅读源码就能发现这归功于 this 的强大力量 5 // 如果传入两个或多个对象,所有对象的属性会被添加到第一个对象 target 6 // 如果只传入一个对象,则将对象的属性添加到 jQuery 对象中,也就是添加静态方法 7 // 用这种方式,我们可以为 jQuery 命名空间增加新的方法,可以用于编写 jQuery 插件 8 // 如果不想改变传入的对象,可以传入一个空对象:$.extend({}, object1, object2); 9 // 默认合并操作是不迭代的,即便 target 的某个属性是对象或属性,也会被完全覆盖而不是合并10 // 如果第一个参数是 true,则是深拷贝11 // 从 object 原型继承的属性会被拷贝,值为 undefined 的属性不会被拷贝12 // 因为性能原因,JavaScript 自带类型的属性不会合并13 jQuery.extend = jQuery.fn.extend = function () {14     var src, copyIsArray, copy, name, options, clone,15         target = arguments[0] || {},16         i = 1,17         length = arguments.length,18         deep = false;19 20     // Handle a deep copy situation21     // target 是传入的第一个参数22     // 如果第一个参数是布尔类型,则表示是否要深递归,23     if (typeof target === "boolean") {24         deep = target;25         target = arguments[1] || {};26         // skip the boolean and the target27         // 如果传了类型为 boolean 的第一个参数,i 则从 2 开始28         i = 2;29     }30 31     // Handle case when target is a string or something (possible in deep copy)32     // 如果传入的第一个参数是 字符串或者其他33     if (typeof target !== "object" && !jQuery.isFunction(target)) {34         target = {};35     }36 37     // extend jQuery itself if only one argument is passed38     // 如果参数的长度为 1 ,表示是 jQuery 静态方法39     if (length === i) {40         //此时的this:如果外部调用的是jQuery.extend方法,则this指jQuery类,扩展到jQuery类上41         //而如果是jQuery.fn.extend方法则this指jQuery原型,扩展到jQuery的原型上42         target = this;43         --i;44     }45 46     // 可以传入多个复制源47     // i 是从 1或2 开始的48     for (; i < length; i++) {49         // Only deal with non-null/undefined values50         // 将每个源的属性全部复制到 target 上51         if ((options = arguments[i]) != null) {52             // Extend the base object53             for (name in options) {54                 // src 是源(即本身)的值55                 // copy 是即将要复制过去的值56                 src = target[name];57                 copy = options[name];58 59                 // Prevent never-ending loop60                 // 防止有环,例如 extend(true, target, {'target':target});61                 if (target === copy) {62                     continue;63                 }64 65                 // Recurse if we're merging plain objects or arrays66                 // 这里是递归调用,最终都会到下面的 else if 分支67                 // jQuery.isPlainObject 用于测试是否为纯粹的对象68                 // 纯粹的对象指的是 通过 "{}" 或者 "new Object" 创建的69                 // 如果是深复制70                 if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))) {71                     // 数组72                     if (copyIsArray) {73                         copyIsArray = false;74                         clone = src && jQuery.isArray(src) ? src : [];75                     } else {76                         clone = src && jQuery.isPlainObject(src) ? src : {};77                     }78 79                     // Never move original objects, clone them80                     // 递归81                     target[name] = jQuery.extend(deep, clone, copy);82 83                     // Don't bring in undefined values84                     // 最终都会到这条分支85                     // 简单的值覆盖86                 } else if (copy !== undefined) {87                     target[name] = copy;88                 }89             }90         }91     }92 93     // Return the modified object94     // 返回新的 target95     // 如果 i < length ,是直接返回没经过处理的 target,也就是 arguments[0]96     // 也就是如果不传需要覆盖的源,调用 $.extend 其实是增加 jQuery 的静态方法97     return target;98 };
View Code

最后做一个模拟JQuery Demo供大家学习

1 (function (window, undefined) { 2     var jQuery = function () { 3         return new jQuery.fn.init(); 4     }; 5     jQuery.fn = jQuery.prototype = { 6         add: function () { console.log("add"); }, 7         remove: function () { console.log("remove"); }, 8         init: function () { console.log("init"); return this; } 9     };10     jQuery.fn.init.prototype = jQuery.fn;11     //添加扩展(静态、实例)方法【demo】12     //传入{methodName:function(){}}13     jQuery.extend = jQuery.fn.extend = function (obj) {14         for (var item in obj) {15             this[item] = obj[item];16         }17     }18     window.jQuery = window.$ = jQuery;19 })(window)
1 $.extend({ staticMethod: function () { console.log("staticMethod"); } });2 $.fn.extend({ instanceMethod: function () { console.log("instanceMethod"); } });3 $.staticMethod();4 $().instanceMethod();

输出:

 

借鉴:

转载于:https://www.cnblogs.com/zuqing/p/5349759.html

你可能感兴趣的文章
栈的顺序存储结构以及实现
查看>>
【python】-- Socket粘包问题 ,解决粘包的几种方法、socket文件下载,md5值检验
查看>>
2016-09-12
查看>>
CDHD驱动器——ServoStudio配置高创伺服速度模式不转
查看>>
完整版本的停车场管理系统源代码带服务端+手机android客户端
查看>>
【UOJ 92】有向图的强联通分量
查看>>
bzoj 1192
查看>>
Windows10/Servers 2016的TrustedInstaller权限获取(及乱改System后救砖
查看>>
关于mysql转移数据库时没有导出sql脚本的情况下,如何导入数据到新的数据库中...
查看>>
链表逆序
查看>>
[zz]链表倒序
查看>>
简单易用的图像解码库介绍 —— stb_image
查看>>
【漏洞复现】永恒之蓝 ms17-010 漏洞利用 攻击手法
查看>>
HTML标签(二)
查看>>
在weblogic下运行Python脚本
查看>>
短信开发技术总结--协议篇
查看>>
HashMap实现原理分析
查看>>
私有类方法
查看>>
java网络编程Socket通信详解
查看>>
为什么使用Nosql:Nosql和SQL的区别
查看>>