【jQuery源码浅析】(三)--jQuery插件拓展--$.extend
来源:互联网 发布:mac os tftp 软件下载 编辑:程序博客网 时间:2024/05/22 08:18
前言
本文主要讲的不是如何使用jQuery的插件方法,而是jQuery.extend和jQuery.fn.extend的实现,这两种方法实现了拓展jQuery方法的途径,前者是增加jQuery的静态方法,也就是$.do()
这样;后者是增加jQuery的实例方法,也就是$(selector).do()
这样。这两者的用法分别为$.extend和$.fn.extend。如果想了解jQuery的插件开发可以看这里如何制作一个最简单的jQuery插件。
这两个方法最神奇的地方是居然用同一个函数来实现,其实从源码中可知this在里面起到了巨大的作用。要了解这两个方法的实现方式,就要先从方法的实现效果去反推和理解。
核心源码
// jQuery插件拓展195 jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[ 0 ] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; // Skip the boolean and the target target = arguments[ i ] || {}; i++; } // 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 if ( i === length ) { target = this; i--; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( ( options = arguments[ i ] ) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging plain objects or arrays 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 return target;262 };
思路分析
- 简单目标:对jQuery和jQuery.fn方法的拓展,也就是
$.do()
和$().do()
。 - 中等目标:把所有的对象合并到第一个对象target上面(如果只有一个对象就合并到自己身上,等于没有合并),并将target返回到方法外。
- 高级目标:深拷贝,也就是说把每个对象中的所有对象的属性都拷贝到第一个对象身上,从object原型继承的属性会被拷贝,值为undefined的属性不会被拷贝。$.extend()的深拷贝和浅拷贝详细讲解
源码分析
1)明确target是哪个对象
// 是用户传进来的第一个参数,如果不填,则新建一个对象(不能为空) var target = arguments[0] || {}; // 如果第一个参数类型为boolean,则target转为第二个参数,如果不填,则新建一个对象(不能为空) if (typeof target === "boolean") { target = arguments[1] || {}; } // 如果第一个参数不是对象或方法(也就有可能为字符串或其他),则将target转换成空对象 if (typeof target !== "object" && !jQuery.isFunction(target)) { target = {}; } // 如果只有一个参数,表示是 jQuery 静态方法 if (length === i) { // length = arguments.length target = this; // this指jQuery本身 // 所以$.extend和$.fn.extend可以写在一起,就是由这个this决定的 } // 最后的target一定是对象,要么是用户传进来的对象,要么是空对象{}
2)复制所有对象的属性到第一个对象target的属性中,如果有相同属性名,将会覆盖target的该属性名的值
// 如果target=this,则循环 1 次,返回原本的target // 如果target!=this,则循环 n-1 次,n为obj的数量(包括target本身) for (; i < length; i++) { // 取出每个对象的key,如果用es6,可以直接用for-of options = arguments[i] for (name in options) { if () {} else if (copy !== undefined) { target[name] = copy; } } }
3)深克隆,将所有对象的属性复制到target中,如果属性不是对象,则完全覆盖;如果是纯对象或者是数组,则不完全覆盖,只覆盖对象或数组里面的相同属性。
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 : {}; } // 递归 target[ name ] = jQuery.extend( deep, clone, copy ); // 最终会走到这里,如果是undefined,则直接退出 } else if ( copy !== undefined ) { target[ name ] = copy; }
最后总结
看完源码,感觉jQuery的extend方法太强大了,一个方法里面主要实现了两个目标,一是帮助jQuery和jQuery的实例增加方法,二是克隆对象。前者只能有一个参数,而后者可能有无限个参数。前者靠target = this
来实现,后者靠 递归 来实现。总之,用85行的代码(含注释和空行)就能同时实现两个功能,既强大又简洁,完全符合了jQuery的 write less, do more. 的追求。
相关资料
- jQuery API 3.2.1 速查表
- 【深入浅出jQuery】源码浅析–整体架构
- jQuery学习官网
- jQuery3.1.1.js源码下载
阅读全文
0 0
- 【jQuery源码浅析】(三)--jQuery插件拓展--$.extend
- jquery extend()函数拓展
- jquery源码-jquery.extend()
- jQuery源码-jQuery.extend
- jQuery源码解析--插件接口设计($.extend)
- 3.jQuery拓展方法extend();
- jQuery 源码学习(一)jQuery.extend()
- jquery 的插件 extend
- jquery extend jquery插件扩展
- jquery.extend源码分析
- jQuery.extend()源码解析
- jQuery插件开发/拓展
- 菜鸡看jquery源码(3)extend
- jQuery插件( jquery.extend 与 jquery.fn.extend的区别)
- jQuery源码解析之jQuery.extend(),jQuery.fn.extend()
- 插件编写---jquery源码品读之入口extend(1)
- jQuery源码阅读(八)---jQuery中的继承extend
- jQuery之插件开发--jQuery.fn.extend()
- 剑指offer | 训练题42:左旋转字符串
- qt+opencv遇到的错误和一点感想
- LZO算法
- 二进制中1的个数
- 【JSON】解析JSON格式异常
- 【jQuery源码浅析】(三)--jQuery插件拓展--$.extend
- 以太网
- 几个加性提升模型
- 1.实现sql语言中DQL语言,实现简单查询、条件查询、排序查询等。
- LNMP安装ftp服务器以及sublime text3使用sftp插件进行链接
- Android ButterKnife Zelezny在AS中的使用
- Ansible常用模块API调用
- 什么是数据库ACID?
- 上传遇到转码问题