读Zepto源码之IOS3模块
IOS3 模块是针对 IOS 的兼容模块,实现了两个常用方法的兼容,这两个方法分别是 trim 和 reduce 。
读 Zepto 源码系列文章已经放到了github上,欢迎star: reading-zepto
源码版本
本文阅读的源码为 zepto1.2.0
GitBook
trim
if (String.prototype.trim === undefined) // fix for iOS 3.2
String.prototype.trim = function(){ return this.replace(/^\s+|\s+$/g, '') }
看注释, trim 是为了兼容 ios3.2 的。
也是常规的做法,如果 String 的 prototype 上没有 trim 方法,则自己实现一个。
实现的方式也简单,就是用正则将开头和结尾的空格去掉。^\s+ 这段是匹配开头的空格,\s+$ 是匹配结尾的空格。
reduce
// For iOS 3.x
// from https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce
if (Array.prototype.reduce === undefined)
Array.prototype.reduce = function(fun){
if(this === void 0 || this === null) throw new TypeError()
var t = Object(this), len = t.length >>> 0, k = 0, accumulator
if(typeof fun != 'function') throw new TypeError()
if(len == 0 && arguments.length == 1) throw new TypeError()
if(arguments.length >= 2)
accumulator = arguments[1]
else
do{
if(k in t){
accumulator = t[k++]
break
}
if(++k >= len) throw new TypeError()
} while (true)
while (k < len){
if(k in t) accumulator = fun.call(undefined, accumulator, t[k], k, t)
k++
}
return accumulator
}
用法与参数
要理解这段代码,先来看一下 reduce 的用法和参数:
用法:
arr.reduce(callback[, initialValue])
参数:
- callback: 回调函数,有如下参数
- accumulator: 上一个回调函数返回的值或者是初始值(
initialValue) - currentValue: 当前值
- currentIndex: 当前值在数组中的索引
- array: 调用
reduce的数组
- accumulator: 上一个回调函数返回的值或者是初始值(
- initialValue: 初始值,如果没有提供,则为数组的第一项。如果数组为空数组,而又没有提供初始值时,会报错
检测参数
if(this === void 0 || this === null) throw new TypeError()
var t = Object(this), len = t.length >>> 0, k = 0, accumulator
if(typeof fun != 'function') throw new TypeError()
if(len == 0 && arguments.length == 1) throw new TypeError()
首先检测是否为 undefined 或者 null ,如果是,则报类型错误。这里有一点值得注意的,判断是否为 undefined 时,用了 void 0 的返回值,因为 void 操作符返回的结果都为 undefined ,这是为了避免 undefined 被重新赋值,出现误判的情况。
接下来,将数组转换成对象,用变量 t 来保存,后面会看到,遍历用的是 for...in 来处理。为什么不直接用 for 来处理数组呢?因为 reduce 不会处理稀疏数组,所以转换要转换成对象来处理。
数组长度用 len 来保存,这里使用了无符号位右移操作符 >>> ,确保 len 为非负整数。
用 k 来保存当前索引,accumulator 为返回值。
接下来,检测回调函数 fun 是否为 function ,如果不是,抛出类型错误。
在数组为空,并且又没有提供初始值(即只有一个参数 fun)时,抛出类型错误。
accumulator初始值
if(arguments.length >= 2)
accumulator = arguments[1]
else
do{
if(k in t){
accumulator = t[k++]
break
}
if(++k >= len) throw new TypeError()
} while (true)
如果参数至少有两项,则 accumulator 的初始值很简单,就是 arguments[1] ,即 initialValue。
如果没有提供初始值,则迭代索引,直到找到在对象 t 中存在的索引。注意这里用了 do...while,所以最终结果,要么是报类型错误,要么 accumulator 能获取到值。
这段还巧妙地用了 ++k 和 k++ 。如果 k 在对象 t 中存在时,则赋值给 accumulator 后 k 再自增,否则用 k 自增后再和 len 比较,如果超出 len 的长度,则报错,因为不存在下一个可以赋给 accumulator 的值。
返回结果
while (k < len){
if(k in t) accumulator = fun.call(undefined, accumulator, t[k], k, t)
k++
}
return accumulator
要注意,如果没有提供初始值时,k 是自增后的值,即不再需要处理数组的第一个值。
到这里问题就比较简单了,就是 while 循环,用 accumulator 保存回调函数返回的值,在下一次循环时,再将 accumulator 作为参数传递给回调函数,直至数组耗尽,然后将结果返回。
系列文章
系列文章
- 读Zepto源码之代码结构
- 读Zepto源码之内部方法
- 读Zepto源码之工具函数
- 读Zepto源码之神奇的$
- 读Zepto源码之集合操作
- 读Zepto源码之集合元素查找
- 读Zepto源码之操作DOM
- 读Zepto源码之样式操作
- 读Zepto源码之属性操作
- 读Zepto源码之Event模块
- 读Zepto源码之IE模块
- 读Zepto源码之Callbacks模块
- 读Zepto源码之Deferred模块
- 读Zepto源码之Ajax模块
- 读Zepto源码之Assets模块
- 读Zepto源码之Selector模块
- 读Zepto源码之Touch模块
- 读Zepto源码之Gesture模块
附文
参考
License
署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0)
作者:对角另一面
读Zepto源码之IOS3模块的更多相关文章
- 读Zepto源码之Fx模块
fx 模块为利用 CSS3 的过渡和动画的属性为 Zepto 提供了动画的功能,在 fx 模块中,只做了事件和样式浏览器前缀的补全,没有做太多的兼容.对于不支持 CSS3 过渡和动画的, Zepto ...
- 读Zepto源码之fx_methods模块
fx 模块提供了 animate 动画方法,fx_methods 利用 animate 方法,提供一些常用的动画方法.所以 fx_methods 模块依赖于 fx 模块,在引入 fx_methods ...
- 读Zepto源码之Stack模块
Stack 模块为 Zepto 添加了 addSelf 和 end 方法. 读 Zepto 源码系列文章已经放到了github上,欢迎star: reading-zepto 源码版本 本文阅读的源码为 ...
- 读Zepto源码之Form模块
Form 模块处理的是表单提交.表单提交包含两部分,一部分是格式化表单数据,另一部分是触发 submit 事件,提交表单. 读 Zepto 源码系列文章已经放到了github上,欢迎star: rea ...
- 读Zepto源码之Data模块
Zepto 的 Data 模块用来获取 DOM 节点中的 data-* 属性的数据,和储存跟 DOM 相关的数据. 读 Zepto 源码系列文章已经放到了github上,欢迎star: reading ...
- 读Zepto源码之Callbacks模块
Callbacks 模块并不是必备的模块,其作用是管理回调函数,为 Defferred 模块提供支持,Defferred 模块又为 Ajax 模块的 promise 风格提供支持,接下来很快就会分析到 ...
- 读Zepto源码之Deferred模块
Deferred 模块也不是必备的模块,但是 ajax 模块中,要用到 promise 风格,必需引入 Deferred 模块.Deferred 也用到了上一篇文章<读Zepto源码之Callb ...
- 读Zepto源码之Ajax模块
Ajax 模块也是经常会用到的模块,Ajax 模块中包含了 jsonp 的现实,和 XMLHttpRequest 的封装. 读 Zepto 源码系列文章已经放到了github上,欢迎star: rea ...
- 读Zepto源码之Selector模块
Selector 模块是对 Zepto 选择器的扩展,使得 Zepto 选择器也可以支持部分 CSS3 选择器和 eq 等 Zepto 定义的选择器. 在阅读本篇文章之前,最好先阅读<读Zept ...
随机推荐
- MongoDB分布式集群搭建(分片加副本集)
# 环境准备 服务器 # 环境搭建 文件配置和目录添加 新建目录的操作要在三台机器中进行,为配置服务器新建数据目录和日志目录 mkdir -p $MONGODB_HOME/config/data mk ...
- Oracle DG测试failover和后续恢复报告
Oracle DG测试failover和后续恢复报告 一.概述 二.验证过程: 2.1 A库异常关闭 2.2 B库进行failover切换为新主库 2.3 要求C库成为新主库的备库 2.4 要求A库成 ...
- jsp页面附件上传暂存的处理
有没有遇到页面是新建一个新对象,对象里面需要上传附件,但是只有当对象保存时才将附件一同上传到数据库的情况? 这种情况的处理可以参考狐狸的思路: @jsp页面创建一个botton bn,该button的 ...
- MariaDB体验2----CSV文件导入
之前已经安装好MariaDB,现在需要将一份从Sql Server数据库里面导出的CSV文件导入进MariaDB,期间碰到了各种坑,这里记录一下. HeidiSQL的导入CSV文件的地方在“工具”栏, ...
- Spring Cloud中负载均衡器概览
在上篇文章中(RestTemplate的逆袭之路,从发送请求到负载均衡)我们完整的分析了RestTemplate的工作过程,在分析的过程中,我们遇到过一个ILoadBalancer接口,这个接口中有一 ...
- makefile初步制作,arm-linux- (gcc/ld/objcopy/objdump)详解
在linux中输入vi Makefile 来实现创建Makefile文件 注意:命令行前必须加TAB键 例如:将两个文件led.c和crt0.S汇编文件,制作一个Makefile文件 led.bin ...
- 【★】深入BGP原理和思想【第一部】
前言:学思科技术我想说,浅尝辄止,不是天才千万别深钻.和我研究高等数学一样,越深入就会发现越多的问题与不合理之处.尤其对于IT界,算法的最终解释权还是掌握在老外手中,所以对于有些细节,我们" ...
- 转:【Java并发编程】之二十二:并发新特性—障碍器CyclicBarrier(含代码)
转载请注明出处:http://blog.csdn.net/ns_code/article/details/17512983 CyclicBarrier(又叫障碍器)同样是Java5中加入的新特性,使用 ...
- 团队作业4——第一次项目冲刺 FiFtH DaY
项目冲刺--Penta Kill 很开心,小编今天LOL也拿到了五杀,感觉自己又可以去吹一年了. 不扯这些有的没的了,让我们来看看今天的任务吧~ Mission 看起来好像和昨天没有什么不同哦,其实是 ...
- 个人作业3——个人总结(Alphe)
小结: 1.软件工程的第一阶段终于结束了,说实话,每个人的课程都很紧张,在这么紧张的时期我们都每周抽出一些时间来开个小会总结或者计划软件工程的相关任何非常难得,大家的态度都诚恳认真,我亦是如此,只是我 ...