模块是针对
- IOS3
的兼容模块,实现了两个常用方法的兼容,这两个方法分别是
- IOS
和
- trim
。
- reduce
读 Zepto 源码系列文章已经放到了github上,欢迎star: reading-zepto
本文阅读的源码为 zepto1.2.0
《reading-zepto》
- 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+$
- // 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])
参数:
)
- 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
来源: http://www.cnblogs.com/hefty/p/7613505.html