jquery和zepto的擴(kuò)展方法extend

總結(jié)下jQuery(3.1.1)和zepto(1.1.6)到底是如何來(lái)開(kāi)放接口,使之可以進(jìn)行擴(kuò)展,兩者都會(huì)有類(lèi)型判斷,本文使用簡(jiǎn)單的類(lèi)型判斷,暫不考慮兼容。

類(lèi)型判斷

var class2type = {},toString = class2type.toString,$={};//判斷類(lèi)型function type(obj) {  return obj == null ? String(obj) : class2type[toString.call(obj)] || "object"}//對(duì)象function isObject(obj) {  return type(obj) == "object"}//字面量對(duì)象function isPlainObject(obj) {  return isObject(obj) && !isWindow(obj) && Object.getPrototypeOf(obj) == Object.prototype
}function isArray(arr){  return Array.isArray(arr) || arr instanceof Array}

zepto.extend

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開(kāi)發(fā)培訓(xùn)

zepto中的擴(kuò)展,我們可以看到,首先是定義了一個(gè)extend函數(shù),這個(gè)在內(nèi)部使用的函數(shù)有三個(gè)參數(shù)target,source,deep。target是將被擴(kuò)展的對(duì)象,source是擴(kuò)展的對(duì)象,deep代表是否深度擴(kuò)展。那么就直接看第三個(gè)參數(shù)了。
我們可以看到,在extend函數(shù)中,即使使用了深度擴(kuò)展,也會(huì)通過(guò)遞歸函數(shù)來(lái)重新擴(kuò)展,最后都會(huì)是targte[key]=source[key],而區(qū)別是:

//test1var test1 = {  name:"a",  item:{    name:"b",    nickname:"c"
  }
};//簡(jiǎn)單擴(kuò)展extend(test1,{name:"a",item:{name:"b",item:{name:"c"}}});
console.log(test1);

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開(kāi)發(fā)培訓(xùn)
可以看到,在沒(méi)有使用deep時(shí),會(huì)直接擴(kuò)展對(duì)象的第一層屬性,并直接覆蓋。但如果使用了deep:

//深度擴(kuò)展extend(test1,{name:"a",item:{name:"b",item:{name:"c"}}},true);
console.log(test1);

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開(kāi)發(fā)培訓(xùn)
現(xiàn)在擴(kuò)展對(duì)象時(shí)就不會(huì)修改原對(duì)象中不對(duì)應(yīng)的值。
然后是$.extend,這個(gè)是可以在外部使用的擴(kuò)展函數(shù),直接在$對(duì)象上定義的,zepto的插件擴(kuò)展可以不需要通過(guò)$.extend擴(kuò)展到zepto對(duì)象里,因?yàn)閦epto的dom.__proto__ = $.fn,zepto.Z.prototype = $.fn,且返回的是$。所以我們可以看見(jiàn)在zepto其他的模塊里,給zepto添加動(dòng)態(tài)方法時(shí),是這樣直接擴(kuò)展的:
電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開(kāi)發(fā)培訓(xùn)
回到$.extend函數(shù),這里在內(nèi)部使用arguments,所以該函數(shù)是不限參數(shù)的,如果想深度擴(kuò)展,只需要把首個(gè)參數(shù)設(shè)為true。首先是簡(jiǎn)單擴(kuò)展的:

var test2 = $.extend(test1,{name:"a",item:{name:"b",item:{name:"c"}}},{name:"d"});
console.log(test2);

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開(kāi)發(fā)培訓(xùn)

深度擴(kuò)展:

var test2 = $.extend(true,test1,{name:"a",item:{name:"b",item:{name:"c"}}},{name:"d",item:{name:"e"}});
console.log(test2);

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開(kāi)發(fā)培訓(xùn)

jQuery.extend 和jQuery.fn.extend

電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開(kāi)發(fā)培訓(xùn)

看jQuery的擴(kuò)展,得益jQuery返回的是一個(gè)真實(shí)的jQuery對(duì)象,其內(nèi)部使用jQuery.fn來(lái)劃分了作用域,所以擴(kuò)展上,因?yàn)閠his的不同,如果擴(kuò)展jQuery對(duì)象,extend是直接擴(kuò)展在jQuery本身上的,而fn.extend是擴(kuò)展在jQuery.prototype原型對(duì)象上。而實(shí)現(xiàn)函數(shù)其實(shí)是一樣的。

在jQuery中使用擴(kuò)展時(shí),如果除了第一個(gè)參數(shù)的boolean值之外,參數(shù)的長(zhǎng)度等于內(nèi)部定義的長(zhǎng)度,都會(huì)擴(kuò)展到j(luò)Query自身,而zepto想要擴(kuò)展到自身,可以將zepto對(duì)象設(shè)為第一個(gè)參數(shù)
電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開(kāi)發(fā)培訓(xùn)
jQuery在循環(huán)里加入了if ((options = arguments[i]) != null)所以當(dāng)給null或undefined賦值時(shí),直接返回?cái)U(kuò)展對(duì)象,而且因?yàn)樯厦娴腶rguments長(zhǎng)度判斷,不會(huì)擴(kuò)展到j(luò)Query上去。而zepto則直接報(bào)錯(cuò)target[key] = source[key]。
zepto:
電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開(kāi)發(fā)培訓(xùn)
電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開(kāi)發(fā)培訓(xùn)
jQuery:
電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開(kāi)發(fā)培訓(xùn)
電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開(kāi)發(fā)培訓(xùn)

jQuery中的extend語(yǔ)法與上面的zepto相同,在zepto里,最后對(duì)如果沒(méi)有proto做了兼容:
電腦培訓(xùn),計(jì)算機(jī)培訓(xùn),平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開(kāi)發(fā)培訓(xùn)

在jQuery中$.extend()與$.fn.extend()是不同也相同的,在上面的源碼里我們也看到了,jQuery.extend = jQuery.fn.extend,只是因?yàn)閮蓚€(gè)函數(shù)的this值指向不同,所以能夠使用的場(chǎng)景也不同,可以大致分為動(dòng)態(tài)和靜態(tài)。在使用jQuery的過(guò)程中,jQuery的最外層匿名函數(shù)里會(huì)執(zhí)行,返回一個(gè)jQuery對(duì)象,并與$一起綁在window上,所以引入文件之后已經(jīng)存在,而動(dòng)態(tài)指的是jQuery.fn.init(selector,context);所以需要先初始化再使用相應(yīng)方法。

小結(jié)

這里將一些瑣碎的知識(shí)點(diǎn)歸納了一下,事實(shí)上,zepto的擴(kuò)展與jQuery的擴(kuò)展在使用的方法上看起來(lái)一樣,但jQuery更細(xì)。了解兩者的區(qū)別能夠在需要兼容zepto和jQuery時(shí)不會(huì)犯未知錯(cuò)誤,也對(duì)擴(kuò)展插件有更好的幫助。本文使用demo(有源碼注釋):jQuery與zepto的extend