extend() 方法, 合并两个或更多对象的属性到第一个对象中,jQuery后续的大部分功能都通过该函数扩展,
当参数只有一个对象时,则将对象的属性添加到jQuery对象中。
jquery 中扩展插件的形式: 2种方法
$.extend({ //扩展工具方法 aaa:function(){ alert(10); }, bbb:function(){ alert(20) } }); $.fn.extend({ //扩展jquery实例方法 aaa:function(){ alert("fn 1"); }, bbb:function(){ alert("fn 2"); } }); $.extend() ; this -> $ this.aaa -> $.aaa(); $.fn.extend(); this -> $.fn (原型) this.aaa -> $().aaa()
当参数中有多个对象的时候,后面的对象都是扩展到第一个对象上:
var a = {name:"Linda"}; $.extend(a,{name:"Joke",age:20},{address:"China"}); console.log(a); // { name="Joke", age=20, address="China"}
还有 深拷贝 和 浅拷贝 , jquery默认是浅拷贝
浅拷贝: var a = {name:"Linda"}; var b = {firends:['aa','bb','cc']}; $.extend(a,b); a.firends.push('dd'); console.log(b); // { firends:['aa','bb','cc','dd']} 深拷贝: var a = {name:"Linda"}; var b = {firends:['aa','bb','cc']}; $.extend(true,a,b); //第一个参数设置为 true , 那就是 深拷贝 a.firends.push('dd'); 此时a 的引用类型的 修改对 b 没有影响 console.log(b); // { firends:['aa','bb','cc']}
源码的 分解:
jQuery.extend = jQuery.fn.extend = function() { 定义一些变量
if(){} 看看是不是深拷贝情况
if(){} 看看参数正确不
if(){} 看看是不是插件情况 for(){ 可能有多个对象情况
if(){} 防止循环引用
if(){} 深拷贝
else if(){} 浅拷贝
}
源码:
jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, //target存储第一个参数, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { //当第一个参数是boolean类型时,知道是深拷贝还是浅拷贝,默认是false 浅拷贝 deep = target; target = arguments[1] || {}; // 此时 target就存储第一个对象 // skip the boolean and the target 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 if ( length === i ) { target = this; // 此时 i表示target 存储的对象在参数中的位置, 如果等于 参数的长度,说明 是向jquery中 添加属性 --i; //也就是只有一个参数,或者2个参数,但第一个参数是boolean类型,实际也就是1个 } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( (options = arguments[ i ]) != null ) { //如果传入的参数,不是null // Extend the base object for ( name in options ) { //对对象进行for循环 src = target[ name ]; //对象扩展的目标, copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { //防止是循环引用,例如: var a = {}; b={name:a}; b中的name属性的值是一个引用类型a , continue; // 如果没有这个判断,那么 $.extend(a,b); 后 a就是一个无线循环的引用, } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { //dep是true,copy也存在,copy是json格式,或者 copy是一个数组 if ( copyIsArray ) { //如果copy是一个数组, copyIsArray = false; clone = src && jQuery.isArray(src) ? src : []; //判断第一个对象的属性值,是不是数组; } else { clone = src && jQuery.isPlainObject(src) ? src : {}; //判断第一个对象的属性值,是不是json; } // 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; };
jquery 中 : 拷贝继承,能够 满足 构造函数继承和 原型继承 方式,
js中 : 构造函数继承 //原型继承