Zepto核心模块之工具方法拾遗

原创 我的小苹果 随笔 Zepto源码分析 222阅读 2018-03-28 10:04:38 举报

前言

平时开发过程中经常会用类似eachmapforEach之类的方法,Zepto本身也把这些方法挂载到$函数身上,作为静态方法存在,既可以给Zepto的实例使用,也能给普通的js对象使用。今天我们主要针对其提供的这些api做一些源码实现分析。

源码仓库
原文链接

<!-- more -->

具体各个api如何使用可以参照英文文档Zepto.js 中文文档Zepto.js

1. $.camelCase

该方法主要是将连字符转化成驼峰命名法。例如可以将a-b-c这种形式转换成aBC,当然连字符的数量可以是多个,a---b-----c => aBC,具体实现已经在这些Zepto中实用的方法集说过了,可以点击查看。而其代码也只是将camelize函数赋值给了$.camelCase

2. $.contains

$.contains(parent, node) ⇒ boolean该方法主要用来检测parent是否包含给定的node节点。如果parent和node为同一节点,则返回false。

举例

源码

用了document.documentElement.contains做判断,如果浏览器支持该方法,就用node.contains重新包了一层得到一个函数,差别就在于如果传入的两个节点相同,那么原生的node.contains返回true,具体用法可以查看MDN Node.contains但是$.contains返回false

如果原生不支持就需要我们自己写一个方法了。主要逻辑还是通过一个while循环,判断传入的node节点的父节点是否为parent,如果一个循环下来,还不是最后才返回false

其实这里应该是可以做一个优化的,一进来的时候就先判断两个节点是否为同一节点,不是再进行后续的判断

3. $.each

用来遍历数组或者对象,类似原生的forEach但是不同的是,可以中断循环的执行,并且服务对象不局限于数组。

举例

需要注意的是,此时回调函数中的this指向的就是数组或者对象的某一项。这样主要是方便内部的一些其他方法在遍历dom节点的时候,this很方便地就指向了对应的dom

源码实现

likeArray已经在这些Zepto中实用的方法集说过了,可以点击查看。

4. $.extend

Zepto中提供的拷贝方法,默认为浅拷贝,如果第一个参数为布尔值则表示深拷贝。

源码实现

可以看到首先对第一个参数是否为布尔值进行判断,有意思的是,只要是布尔值都表示深拷贝,你传true或者false都是一个意思。接着就是对多个source参数进行遍历调用内部方法extend

接下来我们主要来看内部方法extend

整体实现其实还挺简单的,主要是遇到对象或者数组的时候,并且指定为深赋值,则递归调用extend本身,从而完成复制过程。

5. $.grep

其实就是数组的原生方法filter,最终结果得到的是一个数组,并且只包含回调函数中返回 true 的数组项

直接看源码实现

通过call形式去调用原生的数组方法 filter,过滤出符合条件的数据项。

6. $.inArray

返回数组中指定元素的索引值,没有找到该元素则返回-1,fromIndex是一个可选的参数,表示从哪个地方开始往后进行查找。

$.inArray(element, array, [fromIndex]) ⇒ number

举例

源码实现

可见其内部也是调用的原生indexOf方法。

7. $.isArray

判断obj是否为数组。

我们知道判断一个值是否为对象,方式其实挺多的,比如下面的这几种方式

而Zepto中就是采用的第二种方式

如果支持isArray方法就用原生支持的,否则通过instanceof判断,其实不太清楚为什么第二种方式,我们都知道这是有缺陷的,在有iframe场景下,就会出现判断不准确的情况.

8. $.isFunction

判断一个值是否为函数类型

源码实现

主要还是通过内部方法type来实现的,详情可以点击这些Zepto中实用的方法集查看。

9. $.isNumeric

如果传入的值为有限数值或一个字符串表示的数字,则返回ture。

举例

源码

首先val经过Number函数转化,得到num,然后获取val的类型得到type

我们来回顾一下Number(val)的转化规则,这里截取一张图。

Number转化规则

看起来转化规则非常复杂,但是有几点我们可以确定,

  1. 如果输入的是数字例如1,1.3那转化后的还是数字,
  2. 如果输入的是字符串数字类型例如'123', '12.3'那转化后的也是数字
  3. 如果输入的是空字符串''那转化后得到的是0
  4. 如果输入是类似字符串'123aaa',那转化后得到的是NaN

所以再结合下面的判断

  1. 通过val != null排除掉nullundefined
  2. 通过type != 'boolean'排除掉,truefalse
  3. 通过isFinite(num)限定必须是一个有限数值
  4. 通过!isNaN(num)排除掉被Number(val)转化为NaN的值
  5. (type != 'string' || val.length), val为字符串,并且字符串的长度大于0,排除''空字符串的场景。

以上各种判断下来基本就满足了这个函数原来的初衷要求。

9. $.isPlainObject

测试对象是否是“纯粹”的对象,这个对象是通过 对象常量("{}") 或者 new Object 创建的,如果是,则返回true

10. $.isWindow

如果object参数为一个window对象,那么返回true

该两个方法在这些Zepto中实用的方法集也聊过了,可以点击查看一下。

11. $.map

和原生的map比较相似,但是又有不同的地方,比如这里的map得到的记过有可能不是一一映射的,也就是可能得到比原来数组项数更多的数组,以及这里的map是可以用来遍历对象的。

我们先看几个例子

运行结果如下

可以看出

  1. resultArr1resultArr3的区别是$.mapundefinednull给过滤掉了。
  2. resultArr2resultArr4的区别是$.map把回调函数的返回值给铺平了。

接下来看看源码是怎么实现的。

从源码实现上可以看出因为value != null以及flatten(values)造成了上述差异。

12. $.noop

其实就是引用一个空的函数,什么都不处理,那它到底有啥用呢?

比如。我们定义了几个变量,他未来是作为函数使用的。

如果直接这样

宿主环境就不必为我们创建多个匿名函数了。

其实还有一种可能用的不多的场景,在判断一个变量是否是undefined的时候,可以用到。因为函数没有返回值,默认返回undefined,也就是排除了那些老式浏览器undefined可以被修改的情况

13. $.parseJSON

原生JSON.parse方法的别名,接收的是一个字符串对象,返回一个对象。

源码实现

14. $.trim

删除字符串首尾的空白符,如果传入nullundefined返回空字符串

源码实现

15. $.type

获取JavaScript 对象的类型。可能的类型有: null undefined boolean number string function array date regexp object error.

该方法内部实现其实就是内部的type函数,并且已经在这些Zepto中实用的方法集聊过了,可以点击查看。

结尾

Zepto大部分工具方法或者说静态方法就是这些了,欢迎大家指正其中的错误和问题。

参考资料

读zepto源码之工具函数

MDN trim

MDN typeof

MDN isNaN

MDN Number

MDN Node.contains

文章记录

  1. 原来你是这样的jsonp(原理与具体实现细节)
  2. 谁说你只是"会用"jQuery?
  3. 向zepto.js学习如何手动触发DOM事件
  4. mouseenter与mouseover为何这般纠缠不清?
  5. 这些Zepto中实用的方法集
评论 ( 1 )
最新评论
UncleLance 2018-03-29 11:57:04 1F

现成的WEB开发视频在此~~
CSS3带过渡动画效果的垂直导航菜单: http://www.iqiyi.com/w_19rwrlxval.html
觉得好的可以进qq群:143046757一起交流哦~