jQuery源码解读2:.extend()函数
2017-10-11 00:00
507 查看
一、不防从我们所有认识这个函数的功能入手
1. 这个函数把系列对象合并后返回一个新对象2. 合并有两种方式,规定在第一个参数上指明,true为深度,false为浅度。
第一个参数在源码中被确定用来表示是否深浅合并:如代码段:
target = arguments[ 0 ] || {},
二、逐行解释源码
//.extend函数是jQuery()对象的方法也是jQuery静态工具函数 jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, //默认如果不指定合并类型:深度或者否,默认的目标是第一个参数(target定1) target = arguments[ 0 ] || {}, i = 1, //巧用不定参,可以让这个函数的功能多样化 length = arguments.length, //默认为false,默认不深度递归合并 deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; // Skip the boolean and the target //上面把 i = 1 就是要跳过第一参数(当检测到第一个参数为布尔型时) //如果存在指定合并类型,那先这个目标对象就被改成下个参数(target改1) target = arguments[ i ] || {}; //如果存在合并类型且已经确定第一参数为目标对象的话,i++就是开始表明现在可以开始从i++开始找源对象了! i++; } // Handle case when target is a string or something (possible in deep copy) //如果传进来的目标不是一个对象而是非对象的其他数据类型(null 、字符串、undefined等) if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { target = {};(target改2) } // Extend jQuery itself if only one argument is passed //如果传进来就只有一个参数或者两个参数(其中一个是合并类型布尔型),也就是说传进来的参数只有目标对象无源对象, //那就修改目标对象为this(虽然上面(target定1)有默认表示第一个参数是目标对象),把第一个对象参数当做源对象。 if ( i === length ) { target = this;//(target改3) //因为上面误以为有两个参数,且第一参数是合并类型的布尔型,第二个参数是目标对象,上面i++。 //既然是误以为造成的i++,实际只有一个参数就得还原回来! i--; } for ( ; i < length; i++ ) { //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 //当前的源对象复制属性copy是普通JavaScript对象或数组,则递归合并 if ( deep && copy && ( jQuery.isPlainObject( copy ) || ( copyIsArray = Array.isArray( copy ) ) ) ) { if ( copyIsArray ) { copyIsArray = false; //如果原始值src不是数组,则修正为空数组 clone = src && Array.isArray( src ) ? src : []; } else { //如果原始值src不是普通JavaScript对象,则修正为空对象{}。 clone = src && jQuery.isPlainObject( src ) ? src : {}; } // Never move original objects, clone them // 递归调用extend方法,继续进行深度遍历 target[ name ] = jQuery.extend( deep, clone, copy ); //递归 //注意这里的递归得到的一个完整的对象赋给目标对象的[name]属性。而不是把递归中的属性给到目标对象属性 // Don't bring in undefined values //如果不是深度合并 } else if ( copy !== undefined ) { target[ name ] = copy; //如果不是深度合并,碰到源对象的属性为一个完整的对象,也不去递归了! } } } } // Return the modified object return target; };
三、注意深度递归合并与非深度合并直接的区别:
target[ name ] = jQuery.extend( deep, clone, copy ); //递归举个例子就能比较直观的看到问题
//默认的非深度递归 jQuery.extend({ name: “John”, location: { city: “Boston” } }, { last: “Resig”, location: { state: “MA” } } ); // 结果: => { name: “John”, last: “Resig”, location: { state: “MA” } } //深度递归 jQuery.extend( true, { name: “John”, location: { city: “Boston” } }, { last: “Resig”, location: { state: “MA” } } ); // 结果 => { name: “John”, last: “Resig”, location: { city: “Boston”, state: “MA” } }
四、学到的技术点
1. 采用“不定实参”arguments2.
相关文章推荐
- jQuery源码解读3:.ajax()函数
- JQuery3.1.1源码解读(五)【select 函数】
- jQuery.extend()源码解读
- JQuery3.1.1源码解读(十二)【event-extend】
- 读jquery插件源码必备知识--jQuery.extend 函数详解(二)
- jQuery源码——extend()函数
- jQuery.extend()源码解读
- jQuery.extend函数源码详解
- jQuery源码解读之extend()与工具方法、实例方法详解
- [转载]jQuery.extend 函数详解
- jQuery.extend 函数详解
- jQuery.extend 函数详解
- jQuery.extend 函数详解
- jQuery源码解读之addClass()方法分析
- jQuery.extend 函数详解
- jQuery源码解读之hasClass()方法分析
- jQuery.extend 函数详解
- jQuery.extend 函数详解
- <学习笔记> jQuery.extend 函数详解
- jQuery.extend 函数详解