zepto源码解读(二)——zpeto.init()——(4)$.each()函数 / likeArray函数
$.each()函数是我们非常常见的一个API,他的用法大家都基本了解,如下:
$.each $.each(collection, function(index, item){ ... }) ⇒ collection 遍历数组元素或以key-value值对方式遍历对象。回调函数返回 false 时停止遍历。 $.each(['a', 'b', 'c'], function(index, item){ console.log('item %d is: %s', index, item) }) var hash = { name: 'zepto.js', size: 'micro' } $.each(hash, function(key, value){ console.log('%s: %s', key, value) })
可以获得遍历数组或者对象并作对应的处理,那么它是如何工作的呢?我们从源码入手来看一看:
1 $.each = function(elements, callback){ 2 var i, key 3 if (likeArray(elements)) { 4 for (i = 0; i < elements.length; i++) 5 if (callback.call(elements[i], i, elements[i]) === false) return elements 6 } else { 7 for (key in elements) 8 if (callback.call(elements[key], key, elements[key]) === false) return elements 9 } 10 11 return elements 12 }
代码分为两条路线:1.对象通过了likeArray()函数,证明它是个类数组,则执行第一条if中的语句。
2.对象没通过第一条函数,但是可以通过 in 来遍历到(证明是键值类型的对象),就执行else中的语句。
两条路线的执行语句都没什么毛病,但是 likeArray()方法是怎么实现的呢?什么又是类数组呢?
JavaScript中,数组是一个特殊的对象,其property名为正整数,且其length属性会随着数组成员的增减而发生变化,同时又从Array构造函数中继承了一些用于进行数组操作的方法。而对于一个普通的对象来说,如果它的所有property名均为正整数,同时也有相应的length属性,那么虽然该对象并不是由Array构造函数所创建的,它依然呈现出数组的行为,在这种情况下,这些对象被称为“类数组对象”。以下是一个简单的类数组对象:
var o = {0:42, 1:52, 2:63, length:3} console.log(o);
与普通对象不同的是,类数组对象拥有一个特性:可以在类数组对象上应用数组的操作方法。比如,在ECMAScript 5标准中,可以用以下方法来将上面的对象o合并成字符串:
console.log(Array.prototype.join.call(o));//"42,52,63"
也可以在类数组对象上使用slice()方法获取子数组:
console.log(Array.prototype.slice.call(o, 1, 2));//[52]
在浏览器环境中,document.getElementsByTagName()语句返回的就是一个类数组对象。在function调用中,function代码内的arguments变量(保存传入的参数)也是一个类数组对象。在ECMAScript 5标准中,字符串string就是一个只读的类数组对象。
好了,搞清楚类数组是什么了,那么我们来看看这个likeArray()函数是如何实现判断类数组的:
1 function likeArray(obj) { 2 var length = !!obj && 'length' in obj && obj.length, 3 type = $.type(obj) 4 5 return 'function' != type && !isWindow(obj) && ( 6 'array' == type || length === 0 || 7 (typeof length == 'number' && length > 0 && (length - 1) in obj) 8 ) 9 }
先定义length并给他赋值,这个值是obj中的length;
第三行取得obj的type值,用于判断其对象类型;
type应该不等于function,不等于window对象,
等于对象,0
或者length===0(关于这句,我也不太明白,于是做实验,发现传入空对象会返回false,于是我给空对象传入一个length属性为0,返回true。)
或者length是一个数字或者遍历length-1可以在obj中找到。
最后三点满足其一,就可以判断这个对象是类数组对象;
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· 继承的思维:从思维模式到架构设计的深度解析
· 如何在 .NET 中 使用 ANTLR4
· 后端思维之高并发处理方案
· 理解Rust引用及其生命周期标识(下)
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· 当职场成战场:降职、阴谋与一场硬碰硬的抗争
· ShadowSql之.net sql拼写神器
· Excel百万数据如何快速导入?
· 无需WebView,Vue也能开发跨平台桌面应用