jQuery 源码学习 - 02 - jQuery.fn.extend 与 jQuery.extend
参考资料:【深入浅出jQuery】源码浅析--整体架构,备用地址:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | // 扩展合并函数 // 合并两个或更多对象的属性到第一个对象中,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; }; |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· 单线程的Redis速度为什么快?
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
2018-05-28 EChart.js 笔记一