$.each
遍歷數組元素或以key-value值對方式遍歷對象。回調函數返回 false 時停止遍歷。
關於爲什麼使用它,而不使用原生的 forEach 方法,我的看法是
$.each = function (elements, callback) {
var i, key
// 如果是一個類數組的形式,那麼就以數組的形式遍歷
if (likeArray(elements)) {
for (i = 0; i < elements.length; i++)
// 通過 call 形式調用,callback 函數,傳入的參數是元素位置
// 與元素本身,如果回調返回 false 時,那麼停止遍歷
if (callback.call(elements[i], i, elements[i]) === false) return elements
} else {
// 如果不是一個類數組,那麼就用對象的形式遍歷
for (key in elements)
// 通過 call 形式調用,callback 函數,傳入的參數是元素位置
// 與元素本身,如果回調返回 false 時,那麼停止遍歷
if (callback.call(elements[key], key, elements[key]) === false) return elements
}
return elements
}
$.map
通過遍歷集合中的元素,返回通過迭代函數的全部結果(注:是一個新數組,從而保證了原數組的數據安全性),null 和 undefined 將被過濾掉。
$.map = function (elements, callback) {
var value, values = [], i, key
// 如果是一個類數組的形式,那麼就以數組的形式遍歷
if (likeArray(elements))
for (i = 0; i < elements.length; i++) {
// 調用 callback ,傳入參數是 元素與元素位置,返回值賦值給value
// 如果 value 不爲 null 或者 undefined 那麼 將 value 的值 push 到 values 中
// PS:說句題外話,這個代碼風格值得一噴
// 如果按照 $.each 的寫法,那麼回調的調用方式應該是 callback.call(elements[i], elements[i], 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)
}
// 將 values 數組展開並返回(差不多有點有則改之,無則加勉的意思)
return flatten(values)
}
關於 flatten函數 詳細內容我在上篇博文已經解釋了,請對照 Zepto源碼二之輔助函數閱讀
$.trim
除去字符串左右空格,如果是 null 或者 undefined 那麼返回空串,否則調用字符串原生trim方法。
因爲zepto主要是爲移動端設計的,所以通常使用的是webkit內核,所以不用考慮 IE8 不兼容 trim 而要自己寫 trim 函數。直接調用即可。
$.trim = function (str) {
return str == null ? "" : String.prototype.trim.call(str)
}
// 在一般兼容IE8的項目中,我們可以拓展String原型,不過這是題外話
String.prototype.trim = function(){
this.replace(/(^+)|(+$)/g,'')
}
$.parseJSON
格式化JSON。
直接調用瀏覽器方法。
if (window.JSON) $.parseJSON = JSON.parse
$.contains
檢查父節點是否包含給定的dom節點,如果兩者是相同的節點,則返回 false。
先檢查瀏覽器是否包含 contains 方法。如果包含的話,那麼直接調用該方法。否則使用自己編寫的 polyfill 方法。
$.contains = document.documentElement.contains ?
function (parent, node) {
// 直接判斷兩個元素是否是同一個元素,然後再直接調用元素方法查看 node 是不是 parent 的子孫元素
return parent !== node && parent.contains(node)
} :
function (parent, node) {
// 當 node 存在,且 node 存在父元素的時候,把 node 的父元素賦值給 node
// 然後對比 node 是不是與傳入的 parent相等,如果相等那麼說明 node 是 parent 的 子元素。如果不等那麼循環操作,一直對比到 html 元素爲止。
// 這樣如果有相等就可以判斷 parent 是 node 的祖先元素。
// 如果一直找不到的話,那就說明 parent 中不包含 node。 那麼返回 false
while (node && (node = node.parentNode))
if (node === parent) return true
return false
}
$.type
獲取JavaScript 對象的類型。可能的類型有: null undefined boolean number string function array date regexp object error。
$.type = type
關於 type 函數 詳細內容我在上篇博文已經解釋了,請對照 Zepto源碼二之輔助函數閱讀
$.isFunction
如果object是function,則返回ture。
$.isFunction = isFunction
關於 isFunction函數 詳細內容我在上篇博文已經解釋了,請對照 Zepto源碼二之輔助函數閱讀
$.isWindow
如果object參數爲一個window對象,那麼返回true。這在處理iframe時非常有用,因爲每個iframe都有它們自己的window對象,使用常規方法obj === window校驗這些objects的時候會失敗。
$.isWindow = isWindow
關於 isWindow函數 詳細內容我在上篇博文已經解釋了,請對照 Zepto源碼二之輔助函數閱讀
$.isArray
如果object是array,則返回ture。
$.isArray = isArray
關於 isArray函數 詳細內容我在上篇博文已經解釋了,請對照 Zepto源碼二之輔助函數閱讀
$.isPlainObject
測試對象是否是“純粹”的對象,這個對象是通過 對象常量(”{}”) 或者 new Object 創建的,如果是,則返回true。
$.isPlainObject = isPlainObject
關於 isPlainObject函數 詳細內容我在上篇博文已經解釋了,請對照 Zepto源碼二之輔助函數閱讀
$.isEmptyObject
$.isEmptyObject = function (obj) {
var name
// 如果使用 for..in 循環能遍歷出屬性那麼說明,參數有屬性,即非空對象,那麼返回 false 否則返回 true
for (name in obj) return false
return true
}
$.isNumeric
如果該值爲有限數值或一個字符串表示的數字,則返回ture。
$.isNumeric = function (val) {
// 先將 val 轉化成一個 Number 對象,再檢查 val 的類型
// null undefined 肯定非數字,返回 false
// boolean 的值只有 false ,true 肯定非數字,返回false
// 不是字符串類型,但是有length屬性,那麼說明是類數組或者數組,肯定非數字,返回false
// 通過 isNaN ,isFinite 檢測,那麼說明它是一個數字,返回false
// 沒如果不能通過上述的所有條件,那麼肯定不是一個數字,返回false
var num = Number(val), type = typeof val
return val != null && type != 'boolean' &&
(type != 'string' || val.length) &&
!isNaN(num) && isFinite(num) || false
}
$.noop
引用一個空函數(什麼都不處理)。
$.noop = function () { }
$.inArray
返回數組中指定元素的索引值,如果沒有找到該元素則返回-1。
$.inArray = function (elem, array, i) {
return emptyArray.indexOf.call(array, elem, i)
}
// 題外話
// 在ES6版本中,我們已經可以使用 Array.indexOf() 來檢測元素位置
// 在ES7中我們可以使用 Array.includes() 來檢測元素是否存在於數組中
$.camelCase
將一組字符串變成“駱駝”命名法的新字符串,如果該字符已經是“駱駝”命名法,則不變化。
$.camelCase = camelize
關於 camelize函數 詳細內容我在上篇博文已經解釋了,請對照 Zepto源碼二之輔助函數閱讀
$.grep
獲取一個新數組,新數組只包含回調函數中返回 ture 的數組項。
$.grep = function (elements, callback) {
// 直接使用 filter 函數來過濾參數
return filter.call(elements, callback)
}
關於 filter函數 詳細內容我在上篇博文已經解釋了,請對照 [Zepto源碼二之輔助函數](http://blog.csdn.net/qq_17347575/article/details/78973466)閱讀
$.extend
通過源對象擴展目標對象的屬性,源對象屬性將覆蓋目標對象屬性。
function extend(target, source, deep) {
// 對源對象進行遍歷
for (key in source)
// 如果是深度遍歷,那麼還要判斷該屬性是否是對象或者數組。
// 在對象與數組的情況要深層遞歸遍歷
if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
// 先判斷是對象還是數組,根據情況創建,方便後期賦值
if (isPlainObject(source[key]) && !isPlainObject(target[key]))
target[key] = {}
if (isArray(source[key]) && !isArray(target[key]))
target[key] = []
// 遞歸調用
extend(target[key], source[key], deep)
}
// 簡單的把 源對象的屬性值賦值給 目標對象。如果是深度遍歷的情況,那說明已經遍歷到最深的一層了
// 如果是非深度遍歷,那就表示是最外層複製
// 過濾了undefined 。且都是按引用賦值
else if (source[key] !== undefined) target[key] = source[key]
}
$.extend = function (target) {
var deep, args = slice.call(arguments, 1)
// 從這個 if 判斷中可以看出,$.extend的兩種調用方式
// $.extend(deep,target,source)
// $.extend(target,source,deep)
if (typeof target == 'boolean') {
deep = target
target = args.shift()
}
// 使用 forEach 方法來調用匿名函數
// 匿名函數的具體職責是調用 extend 方法
args.forEach(function (arg) { extend(target, arg, deep) })
return target
}