$.extend.apply( null, [ true, { "a" : 1, "b" : 2 } ] );
//console.log(window.a); //window.location.reload();
$.extend.apply( null, [ true, { "a" : 1, "b" : 2 } ].concat( { "c" : 3, "d" : 4 } ) );
//console.log(window.a)

一、问题:

  1. null在这里是干啥?

  2. window.a分别是什么?

二、我们先一起来了解下jQuery中的extend函数

在jQuery-V1.2.6中:

jQuery.extend = jQuery.fn.extend = function() {
// copy reference to target object
var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; // Handle a deep copy situation
if ( target.constructor == Boolean ) {
deep = target;
target = arguments[1] || {};
// 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" && typeof target != "function" )
target = {}; // extend jQuery itself if only one argument is passed
if ( length == i ) {
target = this;
--i;
} for ( ; i < length; i++ )
// Only deal with non-null/undefined values
if ( (options = arguments[ i ]) != null )
// Extend the base object
for ( var name in options ) {
var src = target[ name ], copy = options[ name ]; // Prevent never-ending loop
if ( target === copy )
continue; // Recurse if we're merging object values
if ( deep && copy && typeof copy == "object" && !copy.nodeType )
target[ name ] = jQuery.extend( deep,
// Never move original objects, clone them
src || ( copy.length != null ? [ ] : { } )
, copy ); // Don't bring in undefined values
else if ( copy !== undefined )
target[ name ] = copy; } // Return the modified object
return target;
};

jQuery - v1.2.6 extend

在jQuery-V1.8.2中:

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;
target = arguments[1] || {};
// 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;
} 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;
};

jQuery - V1.8.2 extend

比较两个版本的jQuery,extend函数总体构架上基本没有变化,高版本中写代码更加规范了,很多var变量都前置(这是比较好的编码习惯,当然,也是为了方便压缩工具对代码进行压缩)。

jQuery.fn.extend就是把extend函数绑定到他的原型链中。这样一来,既可以作为静态函数在$上直接引用($.extend),也可以在$(obj)上使用extend。

注意,如果函数没有在原型链上绑定,是不能被“继承”的!

代码大概的意思就是:

  第一个参数是boolean类型 ---------> 深度递归复制
|
|
---------> 如果只有一个参数(除第一个boolean)---------> 将函数的this环境extend进去
|
|
---------> 将后面的参数extend到“第一个”参数中 ---------> 返回“第一个”参数

三、问题解释

  •  第一个问题中,
$.extend.apply( null, [ true, { "a" : 1, "b" : 2 } ] );

extend作为一个静态函数被调用,null被绑定,但是因为满足“只有一个”参数(boolean除外)的条件 , 将函数的this环境(window)extend进去,return的对象就是window对象,所以得到的结果是

window <- { "a" : 1, "b" : 2 }

即,window.a = 1

  • 第二个问题中,
$.extend.apply( null, [ true, { "a" : 1, "b" : 2 } ].concat( { "c" : 3, "d" : 4 } ) );

相当于传入三个参数,第一个是true,第二个是 匿名对象{ "a" : 1, "b" : 2 },第三个是匿名对象{ "c" : 3, "d" : 4 }, 此时的this环境是null(因为将函数绑定到null上面了)。

那么结果就是{ "a" : 1, "b" : 2, "c" : 3, "d" : 4 }, 此刻并不能在window中索引到a这个属性

如要想要访问,那便是null.a,但这种访问方式肯定是不对的。

由于没有变量来接收这个返回的值,所以被作为垃圾给回收了。

有兴趣的童鞋可以试试这个:

$.extend.apply( $, [ true, { "a" : 1, "b" : 2 } ] );
$.extend.apply( $, [ true, { "a" : 1, "b" : 2 } ].concat( { "c" : 3, "d" : 4 } ) );

把$作为当前的环境,看看a被绑定在那个元素上了~

 四、小结

  jQuery是一个非常优秀的JS库,也是前辈们学习JS后经验的总结和思想的结晶,从jQuery1.2版本到现在的2.0版本,代码风格上、函数处理方式上有比较明显的改变,很值得花些功夫去研究。学习的过程中多看看ta们的编码风格、编码规范,了解库的整体构架和实现原理,这样应该会有比较大的提升~

  我觉得前端这方面想独树一帜,就必须在代码中体现自己的思想。

解读jQuery中extend函数的更多相关文章

  1. 解析jQuery中extend方法--源码解析以及递归的过程《二》

    源码解析 在解析代码之前,首先要了解extend函数要解决什么问题,以及传入不同的参数,会达到怎样的效果.extend函数内部处理传入的不同参数,返回处理后的对象. extend函数用来扩展对象,增加 ...

  2. jQuery.fn.extend() 函数详解

    jQuery.fn.extend()函数用于为jQuery扩展一个或多个实例属性和方法(主要用于扩展方法). jQuery.fn是jQuery的原型对象,其extend()方法用于为jQuery的原型 ...

  3. jQuery中$.extend(true,object1, object2);深拷贝对象

    语法:jQuery.extend( [deep ], target, object1 [, objectN ] ) 深浅拷贝对应的参数就是[deep],是可选的,为true或false.默认情况是fa ...

  4. jQuery中$.extend

    $.fn是指jquery的命名空间,加上fn上的方法及属性,会对jquery实例每一个有效. 如扩展$.fn.abc(),即$.fn.abc()是对jquery扩展了一个abc方法,那么后面你的每一个 ...

  5. 详细解读Jquery各Ajax函数:$.get(),$.post(),$.ajax(),$.getJSON()

    一,$.get(url,[data],[callback]) 说明:url为请求地址,data为请求数据的列表(是可选的,也可以将要传的参数写在url里面),callback为请求成功后的回调函数,该 ...

  6. 详细解读Jquery各Ajax函数

    $.get(),$.post(),$.ajax(),$.getJSON() 一,$.get(url,[data],[callback]) 说明:url为请求地址,data为请求数据的列表,callba ...

  7. 详细解读Jquery各Ajax函数:$.get(),$.post(),$.ajax(),$.getJSON() —(转)

    一,$.get(url,[data],[callback]) 说明:url为请求地址,data为请求数据的列表(是可选的,也可以将要传的参数写在url里面),callback为请求成功后的回调函数,该 ...

  8. 解析jQuery中extend方法--用法《一》

    extend方法在jQuery中是一个很重要的方法,jQuey内部用它来扩展属性方法.常用语jQuery插件开发. jQuery提供了两个方法,$.extend和$.fn.extend,两个方法内部实 ...

  9. jQuery中jsonp函数实现

    由于浏览器中的同源策略,不同的域名,不同的协议,甚至不同的端口都无法请求数据.因此出现了浏览器跨域请求数据问题. Jsonp是解决跨域问题的一个非常流行的方法. JSONP(JSON with Pad ...

随机推荐

  1. C语言实现 字符串过滤并修改并返回个数

    基本问题:给定一个strContent,strWord,使用strWord 匹配strContent,匹配成功,将匹配部分全部替换为‘*’ ,并返回匹配成功个数.注意不能使用库函数. 例如:strCo ...

  2. MySQL pdo预处理能防止sql注入的原因

    MySQL pdo预处理能防止sql注入的原因: 1.先看预处理的语法 $pdo->prepare('select * from biao1 where id=:id'); $pdo->e ...

  3. vpython初探

    vpython 是python默认的3D模块,和python有一样的风格.与PyOpenGL相比,容易上手. vpython下载:vpython的官网(www.vpython.org).顺便说一句,官 ...

  4. Asp.net Mvc 身份验证、异常处理、权限验证(拦截器)实现代码

    本问主要介绍asp.net的身份验证机制及asp.net MVC拦截器在项目中的运用.现在让我们来模拟一个简单的流程:用户登录>权限验证>异常处理 1.用户登录 验证用户是否登录成功步骤直 ...

  5. javascript高级特性

    01_javascript相关内容02_函数_Arguments对象03_函数_变量的作用域04_函数_特殊函数05_闭包_作用域链&闭包06_闭包_循环中的闭包07_对象_定义普通对象08_ ...

  6. php mysql支持emoji表情方案

    将emoji转换成utf8 然后存储到数据库,但是 效率低 public function rrr($text) { $text = 'a

  7. k-sum问题

    给定一个数组,里面的是任意整数,可能有重复,再给定一个目标T,从数组中找出所有和为T的K个数,要求结果中没有重复. Note: Elements in a quadruplet (a,b,c,d) m ...

  8. Unity加载模块深度解析(纹理篇)

    在游戏和VR项目的研发过程中,加载模块所带来的效率开销和内存占用(即“加载效率”.“场景切换速度”等)经常是开发团队非常头疼的问题,它不仅包括资源的加载耗时,同时也包含场景物件的实例化和资源卸载等.在 ...

  9. 关于libsvm工具箱在64位matlab下的安装说明

    LIBSVM工具箱的安装 基本方法: 1.在网上下载LIBSVM工具箱. http://www.csie.ntu.edu.tw/~cjlin/libsvm/ 2.将LIBSVM工具箱所在目录添加到MA ...

  10. 关于L'Hopital法则

    1.首先需要使用 罗尔定理 函数f(x)在闭区间[a,b]连续在开区间(a,b)可微,如果f(a)=f(b),那么至少存在一点c使函数导数f'(c)=0 注意需要再(a,b)可微,如果函数有角点,断点 ...