上文我們說到的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有關的源碼。