jQuery 源码分析6: jQuery 基本静态方法(二)
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 基本静态方法(二)的更多相关文章
- jQuery源码分析之=>jQuery的定义
最近写前段的代码比较多,jQuery是用的最多的一个对象,但是之前几次看了源码,都没搞清楚jQuery是怎么定义的,今天终于看明白怎么回事了.记录下来,算是一个新的开始吧. (文中源码都是jQuery ...
- jQuery 源码分析4: jQuery.extend
jQuery.extend是jQuery最重要的方法之一,下面看看jQuery是怎样实现扩展操作的 // 如果传入一个对象,这个对象的属性会被添加到jQuery对象中 // 如果传入两个或多个对象,所 ...
- jQuery 源码分析3: jQuery.fn/ jQuery.prototype
// 建立方法实例,提高方法访问的速度(避免在原型链上搜索) var deletedIds = []; var slice = deletedIds.slice; var concat = delet ...
- jquery源码分析(七)——事件模块 event(二)
上一章节探讨了事件的一些概念,接下来看下jQuery的事件模块. jQuery对事件的绑定分别有几个API:.bind()/.live()/.delegate()/.on()/click(), 不管是 ...
- jQuery 源码分析5: jQuery 基本静态方法(一)
jQuery在初始化过程中会为自己扩展一些基本的静态方法和属性,以下是jQuery 1.11.3版本 239 ~ 564行间所扩展的静态属性和方法 jQuery.extend({ // 为每个jQ ...
- jQuery 源码分析2: jQuery.fn.init
//jQuery.fn.intit 中使用到的外部变量: // 判断是否为HTML标签或#id rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w ...
- 六.jQuery源码分析之jQuery原型属性和方法
97 jQuery.fn = jQuery.prototype = { 98 constructor: jQuery, 99 init: function( selector, context, ro ...
- jQuery源码分析系列
声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...
- [转] jQuery源码分析-如何做jQuery源码分析
jQuery源码分析系列(持续更新) jQuery的源码有些晦涩难懂,本文分享一些我看源码的方法,每一个模块我基本按照这样的顺序去学习. 当我读到难度的书或者源码时,会和<如何阅读一本书> ...
随机推荐
- 第2组UI组件:TextView及其子类
1 TextView及其子类的继承关系 TextView直接继承自View,是EditView与Button两个类的父类,如下为TextView各子类继承关系. 2 个UI的样式图 CheckedTe ...
- Linux使用netstat命令查看并发连接数[转]
转自:http://www.cnblogs.com/wayne173/p/5652043.html Linux使用netstat命令查看并发连接数 我们的网站部署在linux的服务器上,特别是we ...
- ALV 插入可编辑的空行
在FCAT 中 设置需要的字段为 可以编辑,然后LOOP 显示 ALV 的内表,将不需要的行设置为 不可编辑 1. 在ALV用的内表中添加控制 style 的 内表 TYPES:BEGIN OF TY ...
- UITableViewcell autolayout下动态高度
项目中最经常使用的一个UI就是UITableView了.iOS7.8进一步优化了复用机制,用起来相当爽.配合Autolayout,适配工作减轻了非常多. 曾经做适配工作都是在heightForRow里 ...
- 安装Windows SDK7.1时发生的一个错误(附解决办法)
A problem occurred while installing selected Windows SDK components. Installation of the "Micro ...
- IOS debug网络PonyDebugger 实践篇
引言: PonyDebugger是一个很给力的iOS调试工具,它的监视器安装在Chrome浏览器下做为插件使用,通过监视器和PonyDebugger的iOS SDK相辅相成,可以很好的监视App的运 ...
- [AngularJS - app] AngularJS Location-picker app
From: http://rangle.io/blog/two-ways-to-build-a-location-picker-for-a-mobile-angularjs-application/ ...
- android119 侧滑菜单
MainActivity.java package com.heima52.slidemenu; import com.heima52.slidemenu.view.SlideMenu; import ...
- php中body下出现莫名空白字符
php中body下出现莫名空白字符,出现原因 1. 模板前面有莫名格式空格,删不掉,必须把模板里面东西复制出来,新建一个文件弄进去,覆盖原有的 2.docutype前面出现代码,也会导致此问题(有可能 ...
- 【转】cocos2d-x 2.0版本 自适应屏幕分辨率
http://codingnow.cn/cocos2d-x/975.html 我使用的版本是cocos2d-2.0-x-2.0.4,cocos2dx-2.0版本对多分辨率适配提供了很好的支持,使用起来 ...