上文我们说到的zepto的结构,这次我们就看一下zepto如何封装我们常用的方法的。通过学习别人封装的方法,对自己也是一种提升
首先,我们所有返回的dom对象,所有的方法都封装在了源码中的$.fn
中,dom对象是通过原型继承来实现继承$.fn
中的方法,我们看一些我们常用的方法是如何封装的
map: function(fn){
//这里要通过$封装一下,这样才能继续调用后面的方法,实现连缀功能。
return $(
$.map(this,
function(el, i){ return fn.call(el, i, el) }
)
)
我么可以看出来,在$.fn中的map方法实际上是调用了
$.map方法,下面是$.map方法
$.map = function(elements, callback){
var value, values = [], i, key
if (likeArray(elements))
for (i = 0; i < elements.length; i++) {
value = callback(elements[i], i)
if (value != null) values.push(value)
}
else
for (key in elements) {
value = callback(elements[key], key)
if (value != null) values.push(value)
}
return flatten(values)
}
我们平时是这么调用map的
array.map(function(idnex,val){
//之所以这里我们的顺序是index,val,arr
//其实就是因为在$.map中我们在call里传的是就是index,val
//有经验的人应该知道 return this 返回的是val。这是因为call的原因,一会细说
return val;
})
function(el, i){ return fn.call(el, i, el) }
有人可能觉得这个call不是多余的么,根据代码来看fn(i,el)也OK也能实现功能啊,这样写的确可以实现,但是之所以用call是因为,这样我们就可以在回调中使用this,你可以试着吧上面的源码改掉,你会发现this指向的是window,这样非常不友好。
再看下each函数
each: function(callback){
emptyArray.every.call(this, function(el, idx){
return callback.call(el, idx, el) !== false
})
return this
},
each是这里面能代表大多数的例子,很简单,就是使用call来调用原生方法,就是在原生方法上进行了一层封装而已。因为every方法并不影响回调函数内的执行。所以调用原生的every来实现each功能。
在源码中很多方法在内部引用了each和map方法,所以还是有必要把这两个方法搞明白的。
还有一些平时用到的插件小方法,都可以在这里拿,这样就省去我们因为1-2个方法就去引入库的问题,我们完全可以自己写~~
比如看对象是否是空的
$.isEmptyObject = function(obj) {
var name
for (name in obj) return false
return true
}
for in循环连原型上的也一并遍历,所以能确定这是否是个空对象。
鉴别数据类型
function type(obj) {
return obj == null ?
String(obj) : // null undefined
class2type[toString.call(obj)] || "object"
}
$.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = name.toLowerCase()
function isFunction(value) { return type(value) == "function" }
这里面很多例如toString和slice大家可能觉得前面少一些,其实zepto在前面已经定义了这些基本变量了,
emptyArray = [], slice = emptyArray.slice, filter = emptyArray.filter toString = class2type.toString
顺带介绍下toString,借用别人的
Object.prototype.toString.call(null);//”[object Null]”
Object.prototype.toString.call(undefined);//”[object Undefined]”
Object.prototype.toString.call(“abc”);//”[object String]”
Object.prototype.toString.call(123);//”[object Number]”
Object.prototype.toString.call(true);//”[object Boolean]”
2.判断原生引用类型:
函数类型
Function fn(){console.log(“test”);}
Object.prototype.toString.call(fn);//”[object Function]”
日期类型
var date = new Date();
Object.prototype.toString.call(date);//”[object Date]”
数组类型
var arr = [1,2,3];
Object.prototype.toString.call(arr);//”[object Array]”
源码中还有很多小插件,大家可以自己拿到源码看看,都不是很难哟~~,以后再看看关于dom有关的源码。