这几天看了下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()

 (function (window, undefined) {
var
// ...
jQuery = function (selector, context) {
//实例化方法 jQuery() 实际上是调用了原型方法 jQuery.fn.init
return new jQuery.fn.init(selector, context, rootjQuery);
};
// jQuery.prototype 即是 jQuery 的原型,挂载在上面的方法,即可让所有生成的 jQuery 对象使用
jQuery.fn = jQuery.prototype = {
// 实例化化方法,这个方法可以称作 jQuery 对象构造器
init: function (selector, context, rootjQuery) {
// ...
}
}
//这里将jQuery的原型赋值给init原型,让init实例化之后可以调用jQuery的原型方法
//这也就是为什么实例化init可以调用jQuery的原型val()方法 比如:$("#id").val()
jQuery.fn.init.prototype = jQuery.fn;
})(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 后续的大部分功能都通过该函数扩展
// 虽然实现方式一样,但是要注意区分用法的不一样,那么为什么两个方法指向同一个函数实现,但是却实现不同的功能呢,
// 阅读源码就能发现这归功于 this 的强大力量
// 如果传入两个或多个对象,所有对象的属性会被添加到第一个对象 target
// 如果只传入一个对象,则将对象的属性添加到 jQuery 对象中,也就是添加静态方法
// 用这种方式,我们可以为 jQuery 命名空间增加新的方法,可以用于编写 jQuery 插件
// 如果不想改变传入的对象,可以传入一个空对象:$.extend({}, object1, object2);
// 默认合并操作是不迭代的,即便 target 的某个属性是对象或属性,也会被完全覆盖而不是合并
// 如果第一个参数是 true,则是深拷贝
// 从 object 原型继承的属性会被拷贝,值为 undefined 的属性不会被拷贝
// 因为性能原因,JavaScript 自带类型的属性不会合并
jQuery.extend = jQuery.fn.extend = function () {
var src, copyIsArray, copy, name, options, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false; // Handle a deep copy situation
// target 是传入的第一个参数
// 如果第一个参数是布尔类型,则表示是否要深递归,
if (typeof target === "boolean") {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
// 如果传了类型为 boolean 的第一个参数,i 则从 2 开始
i = 2;
} // Handle case when target is a string or something (possible in deep copy)
// 如果传入的第一个参数是 字符串或者其他
if (typeof target !== "object" && !jQuery.isFunction(target)) {
target = {};
} // extend jQuery itself if only one argument is passed
// 如果参数的长度为 1 ,表示是 jQuery 静态方法
if (length === i) {
//此时的this:如果外部调用的是jQuery.extend方法,则this指jQuery类,扩展到jQuery类上
//而如果是jQuery.fn.extend方法则this指jQuery原型,扩展到jQuery的原型上
target = this;
--i;
} // 可以传入多个复制源
// i 是从 1或2 开始的
for (; i < length; i++) {
// Only deal with non-null/undefined values
// 将每个源的属性全部复制到 target 上
if ((options = arguments[i]) != null) {
// Extend the base object
for (name in options) {
// src 是源(即本身)的值
// copy 是即将要复制过去的值
src = target[name];
copy = options[name]; // Prevent never-ending loop
// 防止有环,例如 extend(true, target, {'target':target});
if (target === copy) {
continue;
} // Recurse if we're merging plain objects or arrays
// 这里是递归调用,最终都会到下面的 else if 分支
// jQuery.isPlainObject 用于测试是否为纯粹的对象
// 纯粹的对象指的是 通过 "{}" 或者 "new Object" 创建的
// 如果是深复制
if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))) {
// 数组
if (copyIsArray) {
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : [];
} else {
clone = src && jQuery.isPlainObject(src) ? src : {};
} // Never move original objects, clone them
// 递归
target[name] = jQuery.extend(deep, clone, copy); // Don't bring in undefined values
// 最终都会到这条分支
// 简单的值覆盖
} else if (copy !== undefined) {
target[name] = copy;
}
}
}
} // Return the modified object
// 返回新的 target
// 如果 i < length ,是直接返回没经过处理的 target,也就是 arguments[0]
// 也就是如果不传需要覆盖的源,调用 $.extend 其实是增加 jQuery 的静态方法
return target;
};

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

 (function (window, undefined) {
var jQuery = function () {
return new jQuery.fn.init();
};
jQuery.fn = jQuery.prototype = {
add: function () { console.log("add"); },
remove: function () { console.log("remove"); },
init: function () { console.log("init"); return this; }
};
jQuery.fn.init.prototype = jQuery.fn;
//添加扩展(静态、实例)方法【demo】
//传入{methodName:function(){}}
jQuery.extend = jQuery.fn.extend = function (obj) {
for (var item in obj) {
this[item] = obj[item];
}
}
window.jQuery = window.$ = jQuery;
})(window)
 $.extend({ staticMethod: function () { console.log("staticMethod"); } });
$.fn.extend({ instanceMethod: function () { console.log("instanceMethod"); } });
$.staticMethod();
$().instanceMethod();

输出:

借鉴:jQuery v1.10.2 源码注解

jQuery源码浅析的更多相关文章

  1. jQuery源码浅析2–奇技淫巧

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  2. 【深入浅出jQuery】源码浅析--整体架构

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  3. 【深入浅出jQuery】源码浅析2--奇技淫巧

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  4. (转)【深入浅出jQuery】源码浅析2--奇技淫巧

    [深入浅出jQuery]源码浅析2--奇技淫巧 http://www.cnblogs.com/coco1s/p/5303041.html

  5. 【深入浅出jQuery】源码浅析2--使用技巧

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  6. 【深入浅出jQuery】源码浅析--整体架构(转)

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  7. jQuery源码解析资源便签

    最近开始解读jQuery源码,下面的链接都是搜过来的,当然妙味课堂 有相关的一系列视频,长达100多期,就像一只蜗牛慢慢爬, 至少品读三个框架,以后可以打打怪,自己造造轮子. 完全理解jQuery源代 ...

  8. jQuery 源码学习 - 01 - 简洁的 $('...')

    首先贴上学习参考资料:[深入浅出jQuery]源码浅析--整体架构,备用地址:chokcoco/jQuery-. jQuery 库,js 开发的一个里程碑,它的出现,让网页开发者们告别荒蛮的上古时代, ...

  9. jQuery 源码学习 - 02 - jQuery.fn.extend 与 jQuery.extend

    参考资料:[深入浅出jQuery]源码浅析--整体架构,备用地址:chokcoco/jQuery-. extend 方法在 jQuery 中是一个很重要的方法.jQuery 内部用它来拓展静态方法或者 ...

随机推荐

  1. httpclient post请求带参数返回数据乱码问题解决

    客户端代码: //带参数的post请求 @Test public void doPostWithParam() throws Exception { CloseableHttpClient httpC ...

  2. Codeforces Round #343 (Div. 2) A

    A. Far Relative’s Birthday Cake time limit per test 1 second memory limit per test 256 megabytes inp ...

  3. hadoop设置公平队列

    http://hadoop.apache.org/docs/r1.2.1/fair_scheduler.html fair-scheduler.xml文档 <?xml version=" ...

  4. bzoj 4070 [Apio2015]雅加达的摩天楼 Dijkstra+建图

    [Apio2015]雅加达的摩天楼 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 644  Solved: 238[Submit][Status][D ...

  5. IAR ------ 扩展关键字__weak

    __weak作用:允许多个同名函数同时存在,但是最多只有一个没有__weak修饰.如果有non-weak函数(没__weak修饰),则此函数被使用,否则从__weak修饰的函数中选择其中一个. 下图来 ...

  6. Moodle配置

    Moodle配置 1.   内部设置 在 Moodle 站点管理员界面中有一系列的配置页面(可以从'设置' 块中访问 '网站管理'区).这里有一些重要的系统设置,你需要进行检查. 根据提示信息并结合实 ...

  7. tp if condition in_array用法

    <if condition="in_array($vo['status'],[3])"> <a href="javascript:void(0);&qu ...

  8. Java多线程之“同步”

    好习惯要坚持,这是我第二篇博文,任务略重,但是要坚持努力!!! 1.竞争条件 首先,我们回顾一下<Java核心技术卷>里讲到的多线程的“竞争条件”.由于各线程访问数据的次序,可能会产生讹误 ...

  9. 再续前缘-apache.commons.beanutils的补充

    title: 再续前缘-apache.commons.beanutils的补充 toc: true date: 2016-05-32 02:29:32 categories: 实在技巧 tags: 插 ...

  10. JAVA中3种将byte转换为String的方法

    HttpClient 类库中GetMethod类的getResponseBody方法返回的是byte[]类型,要操作起来不方便,我想把它转化成String类型. 查了网上的资料,有说法认为用这种方法比 ...