欢迎光临
我们一直在努力

jQuery源码浅析

这几天看了下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#中的实例方法。

jQuery源码浅析jQuery源码浅析

 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 situation 21 // target 是传入的第一个参数 22 // 如果第一个参数是布尔类型,则表示是否要深递归, 23 if (typeof target === "boolean") { 24 deep = target; 25 target = arguments[1] || {}; 26 // skip the boolean and the target 27 // 如果传了类型为 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 passed 38 // 如果参数的长度为 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 values 50 // 将每个源的属性全部复制到 target 上 51 if ((options = arguments[i]) != null) { 52 // Extend the base object 53 for (name in options) { 54 // src 是源(即本身)的值 55 // copy 是即将要复制过去的值 56 src = target[name]; 57 copy = options[name]; 58 59 // Prevent never-ending loop 60 // 防止有环,例如 extend(true, target, {'target':target}); 61 if (target === copy) { 62 continue; 63  } 64 65 // Recurse if we're merging plain objects or arrays 66 // 这里是递归调用,最终都会到下面的 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 them 80 // 递归 81 target[name] = jQuery.extend(deep, clone, copy); 82 83 // Don't bring in undefined values 84 // 最终都会到这条分支 85 // 简单的值覆盖 86 } else if (copy !== undefined) { 87 target[name] = copy; 88  } 89  } 90  } 91  } 92 93 // Return the modified object 94 // 返回新的 target 95 // 如果 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();

输出:

jQuery源码浅析

 

借鉴:jQuery v1.10.2 源码注解

  • 海报
海报图正在生成中...
赞(0) 打赏
声明:
1、本博客不从事任何主机及服务器租赁业务,不参与任何交易,也绝非中介。博客内容仅记录博主个人感兴趣的服务器测评结果及一些服务器相关的优惠活动,信息均摘自网络或来自服务商主动提供;所以对本博客提及的内容不作直接、间接、法定、约定的保证,博客内容也不具备任何参考价值及引导作用,访问者需自行甄别。
2、访问本博客请务必遵守有关互联网的相关法律、规定与规则;不能利用本博客所提及的内容从事任何违法、违规操作;否则造成的一切后果由访问者自行承担。
3、未成年人及不能独立承担法律责任的个人及群体请勿访问本博客。
4、一旦您访问本博客,即表示您已经知晓并接受了以上声明通告。
文章名称:《jQuery源码浅析》
文章链接:https://www.456zj.com/20636.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址