根據第一篇總體框架,能夠知道$()方法返回的Z函數的實例化;而Z的原型又指向$.fn;因此通過$()處理過的對象,均可以使用$.fn中的方法;
這一篇就記錄一下讀$.fn的筆記;css
zepto.Z.prototype = Z.prototype = $.fn
//判斷一個元素是否匹配給定的選擇器 zepto.matches = function(element, selector) { //若是selector,element沒值或者element是普通節點 if (!selector || !element || element.nodeType !== 1) return false var matchesSelector = element.matches || element.webkitMatchesSelector || element.mozMatchesSelector || element.oMatchesSelector || element.matchesSelector if (matchesSelector) return matchesSelector.call(element, selector) // fall back to performing a selector: var match, parent = element.parentNode, temp = !parent if (temp) (parent = tempParent).appendChild(element) match = ~zepto.qsa(parent, selector).indexOf(element) temp && tempParent.removeChild(element) return match }
若是瀏覽器支持matchesSelector
方法,則用此方法進行判斷
html
若是瀏覽器不支持matchesSelector
,則定義match
和parent
變量,其中parent
爲element
的父元素,若是沒有父元素,則建立一個div
容器看成其父元素java
tempParent = document.createElement('div'),
node
match = ~zepto.qsa(parent, selector).indexOf(element)
web
qsa()
函數以前已經說明,若element
不存在zepto.qsa(parent, selector).
中,則返回-1,~-1即爲0,即match
最終的值爲false
數組
若element
存在,則返回非零的值,轉換爲布爾值爲true
瀏覽器
constructor: zepto.Z,
app
var person = function(name){ this.name = name; } var siva = new Person('Siva'); siva .__proto__ == person.prototype //true person.prototype.constructor == person //true
因爲zepto.Z.prototype = $.fn
;所以$.fn的構造函數即爲zepto.Z
框架
forEach: emptyArray.forEach,
dom
reduce: emptyArray.reduce, push: emptyArray.push, sort: emptyArray.sort, splice: emptyArray.splice, indexOf: emptyArray.indexOf,
get: function(idx){ //若是不傳參,將Z對象轉爲數組, slice.call()在第三篇已經提到過;數組自有的slice; //若是傳參小於0,就將傳的參數轉換爲idx加上傳入對象的長度;即爲倒數返回; //例如傳入的值爲-1;則選取最後一個元素 return idx === undefined ? slice.call(this) : this[idx >= 0 ? idx : idx + this.length] },
在分析這句話以前,咱們先看看get的用法;
//將Z對象集合轉換成數組 toArray: function(){ return this.get() },
get()
concat: function(){ var i, value, args = [] for (i = 0; i < arguments.length; i++) { value = arguments[i] //若是其中傳入的參數爲Z對象,則將其轉爲數組;並將值傳給arg args[i] = zepto.isZ(value) ? value.toArray() : value } //apply方法將this強制綁定到調用concat的對象身上 //若是調用concat的是Z對象,則將其轉換成數組 return concat.apply(zepto.isZ(this) ? this.toArray() : this, args) },
Zepto
對象集合造成一個新數組。若是參數是一個數組,那麼這個數組中的元素將會合併到Zepto對象集合中。arguments
爲傳入的參數組合;
這個方法並無像上面的reduce,push,sort,splice,等直接複製Array.prototype的屬性,是由於調用此事件的對象並不必定爲數組,若是調用的對象爲$();
則是類數組對象,而不是真正的數組,若是直接調用數組的concat
,則會將$();
看成數組的一個item合併起來,因此此方法須要從新封裝
slice: function(){ //同上,將this強制綁定到調用的對象身上; return $(slice.apply(this, arguments)) },
ready: function(callback){ //判斷dom是否ready,若是已經ready,直接執行函數 if (readyRE.test(document.readyState) && document.body) callback($) //不然註冊監聽器; else document.addEventListener('DOMContentLoaded', function(){ callback($) }, false) return this },
readyRE = /complete|loaded|interactive/,
size: function() { return this.length },
each: function(callback){ emptyArray.every.call(this, function(el, idx){ return callback.call(el, idx, el) !== false }) //可使用鏈式操做 return this },
every
,當callback
的值返回false
的時候就會停止循環;eq: function(idx){ return idx === -1 ? this.slice(idx) : this.slice(idx, + idx + 1) },
first: function(){ var el = this[0] return el && !isObject(el) ? el : $(el) },
return el && !isObject(el) ? el : $(el)
若是集合中第一個數據爲對象的話返回自己,不然轉換成zepto對象last: function(){ var el = this[this.length - 1] return el && !isObject(el) ? el : $(el) },
add: function(selector,context){ return $(uniq(this.concat($(selector,context)))) },
uniq = function(array){ return filter.call(array, function(item, idx){ return array.indexOf(item) == idx }) }
uniq
中的filter
在以前已經定義;filter = emptyArray.filter
,即爲Array.prototype.filter
Array.prototype.filter
的用法java var words = ["spray", "limit", "elite", "exuberant", "destruction", "present"]; var longWords = words.filter(function(word){ return word.length > 6; }) // Filtered array longWords is ["exuberant", "destruction", "present"]
uniq
的做用是給數組去重,若是數組中的數據在數組中的位置不等於索引值,說明這個數據在數組中出現過兩次以上,咱們再利用filter
函數,只取出位置和索引值相同的那個;
map: function(fn){ return $($.map(this, function(el, i){ return fn.call(el, i, el) })) },
remove: function(){ return this.each(function(){ if (this.parentNode != null) this.parentNode.removeChild(this) }) },
is: function(selector){ return this.length > 0 && zepto.matches(this[0], selector) },
match
在開頭已經寫過了;not: function(selector){ var nodes=[] //當selector爲函數時,可是safari下的typeof odeList也是function, //因此這裏須要再加一個判斷selector.call !== undefined if (isFunction(selector) && selector.call !== undefined) this.each(function(idx){ //當selector.call(this,idx)返回結果爲false,記錄; if (!selector.call(this,idx)) nodes.push(this) }) else { //當selector爲字符串的時候,篩選知足selector的記錄; var excludes = typeof selector == 'string' ? this.filter(selector) : //當selector爲類數組,將其變爲數組,不然,執行$() (likeArray(selector) && isFunction(selector.item)) ? slice.call(selector) : $(selector) this.forEach(function(el){ //篩選出不在excludes中的數據 if (excludes.indexOf(el) < 0) nodes.push(el) }) } //以上獲得的是數組,將其轉換成zepto對象; return $(nodes) },
attr: function(name, value){ var result //若是name爲字符串的時候,且只有一個參數 return (typeof name == 'string' && !(1 in arguments)) ? //調用者第一個對象的節點屬性爲普通元素,若是有這個屬性,就返回這個屬性值,不然返回undefined; //獲取屬性 (0 in this && this[0].nodeType == 1 && (result = this[0].getAttribute(name)) != null ? result : undefined) : //修改屬性 this.each(function(idx){ if (this.nodeType !== 1) return //若是name是一個對象,則遍歷,設置屬性; if (isObject(name)) for (key in name) setAttribute(this, key, name[key]) //若是不是對象,利用funcArg獲取返回值 else setAttribute(this, name, funcArg(this, value, idx, this.getAttribute(name))) }) },
dom
的屬性;attr(name) ⇒ string attr(name, value) ⇒ self attr(name, function(index, oldValue){ ... }) ⇒ self attr({ name: value, name2: value2, ... }) ⇒ self
var form = $('form') form.attr('action') //=> 讀取值 form.attr('action', '/create') //=> 設置值 form.attr('action', null) //=> 移除屬性 form.attr({ action: '/create', method: 'post' })// 多個屬性:
setAttribute
function setAttribute(node, name, value) { value == null ? node.removeAttribute(name) : node.setAttribute(name, value) }
* 當傳入的`value`爲空的時候,去除屬性,不然設置屬性爲`value`
funcArg
function funcArg(context, arg, idx, payload) { return isFunction(arg) ? arg.call(context, idx, payload) : arg }
* 當`arg`爲函數的時候,將參數傳入arg函數內,不然返回本身
removeAttr: function(name){ return this.each(function(){ this.nodeType === 1 && name.split(' ').forEach(function(attribute){ setAttribute(this, attribute) }, this)}) },
prop: function(name, value){ name = propMap[name] || name //若是傳入value值 return (1 in arguments) ? this.each(function(idx){ this[name] = funcArg(this, value, idx, this[name]) }) : //不然沒有value,返回第一條數據的name (this[0] && this[0][name]) },
dom
元素的屬性值。它在讀取屬性值的狀況下優先於 attr
,由於這些屬性值會由於用戶的交互發生改變,如checked
和 selected
。prop(name) ⇒ value prop(name, value) ⇒ self prop(name, function(index, oldValue){ ... }) ⇒ self
propMap
propMap = { 'tabindex': 'tabIndex', 'readonly': 'readOnly', 'for': 'htmlFor', 'class': 'className', 'maxlength': 'maxLength', 'cellspacing': 'cellSpacing', 'cellpadding': 'cellPadding', 'rowspan': 'rowSpan', 'colspan': 'colSpan', 'usemap': 'useMap', 'frameborder': 'frameBorder', 'contenteditable': 'contentEditable' },
removeProp: function(name){ name = propMap[name] || name return this.each(function(){ delete this[name] }) },
DOM
節點中刪除一個屬性。className
和maxLength
屬性;由於瀏覽器禁止;pluck: function(property){ return $.map(this, function(el){ return el[property] }) },
null
或undefined
值得過濾掉。$.map
在第二篇已經提到過;