$.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. aa3

    var geoCoordMap = { "海门":[121.15,31.89], "鄂尔多斯":[109.781327,39.608266], "招远 ...

  2. 使用my exclipse对数据库进行操作(4)

    四.删除 public class class4 { public static void main(String[] args) { // TODO Auto-generated method st ...

  3. 如何写出优雅兼备可读性的javascript代码

    即或是最简单的需求,不同的程序员也会写出不一样的代码: 需求:充值程序过虑不符合条件的充值金额,即只能充入100.200.500.1000金额,其它过虑: 1.菜鸟程序员可能会这样写,虽然可读性强,代 ...

  4. Python小练习二

    # 以正确的宽度在居中的"盒子"内打印一个句子 # 注意,整数除法运算符(//)只能用在Python 2.2及后续版本,在之前的版本中,只使用普通除法(/) sentence = ...

  5. 开园第一篇 - 论移动开发环境 IOS与Android的差异

    首先,在真正写技术之前做个自我简介.本人08年开始学c语言 一年后,转vc++.开始接触MFC MFC做了两年.转眼11年了我考上了一个不知名的大专.搞C++发现没有市场了因为当时酷狗腾讯的软件已经日 ...

  6. 使用django-admin.py 时出错

    我在安装好django后,运行django-admin.py 时出现两处错误: 一.当你在dos命令下输入django-admin.py 时不会运行,而是以记事本的方式打开了. 解决办法:找到你的dj ...

  7. JQuery按回车提交数据

    引入JQuery文件 <script src="JS/jquery-1.9.1.js" type="text/javascript"></sc ...

  8. spring AOP应用

    转自:http://wb284551926.iteye.com/blog/1887650 最近新项目要启动,在搭建项目基础架构的时候,想要加入日志功能和执行性能监控的功能,想了很多的想法,最后还是想到 ...

  9. JS变量和函数的一些理解

    今日看了下JS变量的一些文章,有些感触,把自己总结的一些写出来. JS初始化的过程1.JS解释器执行代码之前,创建全局变量2.用预定义的值和函数来初始化全局对象中的属性,3.搜索函数外的var声明,创 ...

  10. Android中Button、ImageButton、ImageView背景设置区别

    Button与ImageButton实际两者无关,Button继承自TextView,不支持src;ImageButton继承自ImageView.同一张图片在不设置大小,默认显示时,使用Button ...