IOS3
模块是针对 IOS
的兼容模块,实现了两个经常使用方法的兼容,这两个方法分别是 trim
和 reduce
。 javascript
读 Zepto 源码系列文章已经放到了github上,欢迎star: reading-zeptojava
本文阅读的源码为 zepto1.2.0ios
《reading-zepto》git
if (String.prototype.trim === undefined) // fix for iOS 3.2 String.prototype.trim = function(){ return this.replace(/^\s+|\s+$/g, '') }
看注释, trim
是为了兼容 ios3.2
的。github
也是常规的作法,若是 String
的 prototype
上没有 trim
方法,则本身实现一个。数组
实现的方式也简单,就是用正则将开头和结尾的空格去掉。^\s+
这段是匹配开头的空格,\s+$
是匹配结尾的空格。微信
// 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])this
参数:
callback: 回调函数,有以下参数
initialValue
)reduce
的数组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
)时,抛出类型错误。
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
做为参数传递给回调函数,直至数组耗尽,而后将结果返回。
署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0)
最后,全部文章都会同步发送到微信公众号上,欢迎关注,欢迎提意见:
做者:对角另外一面