jQuery.extend({

 // 遍历obj的所有值
// args 这参数只能内部调用的会用到
// 注意到,如果回调函数调用失败会直接跳出并中止遍历
// 当有args数组时,使用apply调用,否则使用call调用
each: function( obj, callback, args ) {
var value,
i = 0,
length = obj.length,
isArray = isArraylike( obj );
if ( args ) { // 内部调用时才会有args
if ( isArray ) { // obj是Array for ( ; i < length; i++ ) {
value = callback.apply( obj[ i ], args );
if ( value === false ) {
break;
}
}
} else { // obj是Object for ( i in obj ) { value = callback.apply( obj[ i ], args ); if ( value === false ) { break; } } }
// 最常用的each使用方式
} else {
if ( isArray ) { // obj是Array
for ( ; i < length; i++ ) {
value = callback.call( obj[ i ], i, obj[ i ] ); // 回调函数会获取i 和 对应的属性
if ( value === false ) {
break;
}
}
} else { // obj是Object
for ( i in obj ) {
value = callback.call( obj[ i ], i, obj[ i ] );
if ( value === false ) {
break;
}
}
}
}
return obj;
}, // 支持: Android<4.1, IE<9
// rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g
// 删除 BOM and NBSP
trim: function( text ) {
return text == null ?
"" :
( text + "" ).replace( rtrim, "" );
}, // results参数仅限内部调用
// 将arr变成一个Array
// 如果有results,arr会合并到results后面
// 如果arr是'string',则会转换为[arr]然后合并到Array上
makeArray: function( arr, results ) {
var ret = results || [];
if ( arr != null ) {
if ( isArraylike( Object(arr) ) ) {
jQuery.merge( ret,
typeof arr === "string" ?
[ arr ] : arr
);
} else {
push.call( ret, arr );
}
}
return ret;
}, // 判断elem是否在arr这个数组上
// i是检索的起始index
inArray: function( elem, arr, i ) {
var len;
if ( arr ) {
if ( indexOf ) {
return indexOf.call( arr, elem, i ); // 调用Array.indexOf
}
len = arr.length;
i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; // 如果i<0,则设i为len+i
for ( ; i < len; i++ ) {
// 跳过对稀疏数组的访问?
// Skip accessing in sparse arrays
if ( i in arr && arr[ i ] === elem ) {
return i;
}
}
}
return -1;
}, // 把second合并到first上
merge: function( first, second ) {
var len = +second.length,
j = 0,
i = first.length;
while ( j < len ) {
first[ i++ ] = second[ j++ ];
}
// 支持: IE<9
// 如果类数组对象没有length,因此.length不是一个数字,例如NodeLists
if ( len !== len ) {
while ( second[j] !== undefined ) {
first[ i++ ] = second[ j++ ];
}
}
first.length = i;
return first;
}, // 筛选遍历数组
// callback用于判断是否符合
// invert表示与callback的结果相反,即希望保留callback返回值为false的元素
grep: function( elems, callback, invert ) {
var callbackInverse,
matches = [],
i = 0,
length = elems.length,
callbackExpect = !invert; // invert == true, 表示希望callback返回false
// 遍历数组,只保留通过筛选的元素
for ( ; i < length; i++ ) {
callbackInverse = !callback( elems[ i ], i );
if ( callbackInverse !== callbackExpect ) {
matches.push( elems[ i ] );
}
}
return matches;
}, // arg参数只在内部调用时使用
map: function( elems, callback, arg ) {
var value,
i = 0,
length = elems.length,
isArray = isArraylike( elems ),
ret = [];
// 遍历数组,将其转换成新的值并放到ret数组中
if ( isArray ) {
for ( ; i < length; i++ ) {
value = callback( elems[ i ], i, arg );
if ( value != null ) {
ret.push( value );
}
}
// 遍历对象的属性,将其转换成新的值并放到ret数组中
} else {
for ( i in elems ) {
value = callback( elems[ i ], i, arg );
if ( value != null ) {
ret.push( value );
}
}
}
// 如果存在嵌套的数组,将其展开
return concat.apply( [], ret );
}, // 对象的全局GUID计数器
guid: 1, // Bind a function to a context, optionally partially applying any arguments.
// 为一个function绑定一个上下文环境,
proxy: function( fn, context ) {
var args, proxy, tmp;
// 处理: $.proxy(context, name)
if ( typeof context === "string" ) {
tmp = fn[ context ]; // 从参数context提取一个function
context = fn; // 将上下文设置成参数context
fn = tmp; // 将绑定function对象设置为conext[nam]
} // 确保fn是一个可调用对象
// 如果不可调用,返回undefined
if ( !jQuery.isFunction( fn ) ) {
return undefined;
}
// 模拟上下文绑定
args = slice.call( arguments, 2 ); // 截取fn所需要的参数
proxy = function() {
return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
};
// 为唯一的句柄设置guid,这个guid应该与原理fn的guid一样,使得它可以被移除
proxy.guid = fn.guid = fn.guid || jQuery.guid++;
return proxy;
}, // 新建一个时间对象并返回
now: function() {
return +( new Date() );
}, // jQuery不会在内核中使用,但其他项目会将一些属性设置到support中
support: support });
 
 
总结:
  • jQuery.extend在进行扩展的时候,是使用到了深拷贝,这是教科书式的用法,对Object和Array对象进行递归合并,将其中所有的属性都作拷贝。这样做的原因是在JavaScript里,对右值为Object和Array的赋值操作是执行引用而非拷贝,因此必须遍历Object和Array的属性以实现深拷贝;
  • 方法重载的技巧再次出现,如jQuery.proxy。重载的实现实际上要对参数类型、参数数量进行判断,以进行不同的处理;
  • 为了绑定函数方法的上下文环境,我们可以使用jQuery.proxy,而.proxy的实现使用到了function.apply(conext, args);
  • jQuery.grep的实现也是比较巧妙,添加一个形参invert来进行反向选择,即可以利用一个callback作出双向选择,这也是一个简单而巧妙的技巧。

jQuery 源码分析6: jQuery 基本静态方法(二)的更多相关文章

  1. jQuery源码分析之=>jQuery的定义

    最近写前段的代码比较多,jQuery是用的最多的一个对象,但是之前几次看了源码,都没搞清楚jQuery是怎么定义的,今天终于看明白怎么回事了.记录下来,算是一个新的开始吧. (文中源码都是jQuery ...

  2. jQuery 源码分析4: jQuery.extend

    jQuery.extend是jQuery最重要的方法之一,下面看看jQuery是怎样实现扩展操作的 // 如果传入一个对象,这个对象的属性会被添加到jQuery对象中 // 如果传入两个或多个对象,所 ...

  3. jQuery 源码分析3: jQuery.fn/ jQuery.prototype

    // 建立方法实例,提高方法访问的速度(避免在原型链上搜索) var deletedIds = []; var slice = deletedIds.slice; var concat = delet ...

  4. jquery源码分析(七)——事件模块 event(二)

    上一章节探讨了事件的一些概念,接下来看下jQuery的事件模块. jQuery对事件的绑定分别有几个API:.bind()/.live()/.delegate()/.on()/click(), 不管是 ...

  5. jQuery 源码分析5: jQuery 基本静态方法(一)

    jQuery在初始化过程中会为自己扩展一些基本的静态方法和属性,以下是jQuery 1.11.3版本 239 ~ 564行间所扩展的静态属性和方法   jQuery.extend({ // 为每个jQ ...

  6. jQuery 源码分析2: jQuery.fn.init

    //jQuery.fn.intit 中使用到的外部变量: // 判断是否为HTML标签或#id rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w ...

  7. 六.jQuery源码分析之jQuery原型属性和方法

    97 jQuery.fn = jQuery.prototype = { 98 constructor: jQuery, 99 init: function( selector, context, ro ...

  8. jQuery源码分析系列

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...

  9. [转] jQuery源码分析-如何做jQuery源码分析

    jQuery源码分析系列(持续更新) jQuery的源码有些晦涩难懂,本文分享一些我看源码的方法,每一个模块我基本按照这样的顺序去学习. 当我读到难度的书或者源码时,会和<如何阅读一本书> ...

随机推荐

  1. js为select添加option

    <select id="shi"> function loadInfo(){ var shengId=document.getElementById("she ...

  2. Ajax调用WebService(一)

    Ajax调用WebService(一) http://www.cnblogs.com/leslies2/archive/2011/01/26/1934889.html 分类: Ajax 使用技术 We ...

  3. Linux 下 scp 传输文件脚本

    脚本执行效果: (1).远程传输本地 /ora_exp/dmp/CWDB_RAMS_* 文件至 11.4.24.21 的 /ora_exp/dmp 目录下.   脚本编写步骤: 假设 oracle 用 ...

  4. JavaScript要点 (二) 使用误区

    赋值运算符应用错误 注:赋值语句返回变量的值. 在 JavaScript 程序中如果你在 if 条件语句中使用赋值运算符的等号 (=) 将会产生一个错误结果, 正确的方法是使用比较运算符的两个等号 ( ...

  5. PHP中各种Hash算法性能比较

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  6. AS问题解决系列3—iCCP: Not recognizing known sRGB profile

    http://my.oschina.net/1pei/blog/479162 摘要 本文解决了Android Studio 1.2.2下编译期间出现的libpng warning: iCCP: Not ...

  7. 12.1 文档相关 Webbrowser 该文档已被修改,是否保存修改结果

       附件:http://files.cnblogs.com/xe2011/Webbrowser_Document_IsModified.rar   该文档已被修改,是否保存修改结果?是:保存修改结果 ...

  8. Centos部署nagios+apache实现服务器监控

    1.Nagios介绍 nagios是 一款功能强大的网络监视工具,它可以有效的监控windows.linux.unix主机状态以及路由器交换机的网络设置,打印机工作状态等,并将状态出 现异常的服务及时 ...

  9. POJ 1329 三角外接圆

    Circle Through Three Points Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3169   Acce ...

  10. const形参和实参

    当形参是const时,必须要注意关于顶层const的讨论.如前所述,顶层const的作用于对象本身: const int ci=42;  //不能改变ci,const是顶层的 int i=ci:   ...