王運(yùn) 倪靜
摘 要:隨著互聯(lián)網(wǎng)的普及,前端技術(shù)也得到了迅速發(fā)展。為了深入了解前端開(kāi)發(fā)中的框架設(shè)計(jì)原理,以Zepto前端框架為例,利用Javascript原型鏈的相關(guān)知識(shí),采用原生Javascript與框架對(duì)比的方法剖析了框架整體設(shè)計(jì)思路,細(xì)致分析了框架的大致架構(gòu),重構(gòu)了Zepto對(duì)象原型,并封裝了可能用到的所有方法。利用這種從宏觀到微觀的研究視角,最終呈現(xiàn)了一個(gè)框架的整體細(xì)致構(gòu)造及其與底層原生Javascript的聯(lián)系,以便于開(kāi)發(fā)者熟悉框架設(shè)計(jì)原理,更好地設(shè)計(jì)出自己的框架。
關(guān)鍵詞:Javascript;前端框架;原型;Zepto
DOI:10.11907/rjdk.172716
中圖分類(lèi)號(hào):TP319
文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1672-7800(2018)004-0124-03
Abstract:In order to gain a better understanding of the framework design principles in front-end development, we take the front-end framework of Zepto as an example, use Javascript prototype chain, native Javascript and frame comparison method to analyze the framework of the overall design ideas. We have detailed analysis of the framework of the general structure, reconstruct Zepto object prototype, and encapsulate all the methods that will be used. Based on the micro-to-micro perspective, we present a framework of the overall structure and its relationship with the underlying native Javascript, which help developers familiarize framework design principles to better establish their frameworks.
Key Words:Javascript; front frame; prototype; Zepto
0 引言
近幾年隨著前端領(lǐng)域的迅速發(fā)展,出現(xiàn)了多種類(lèi)型的框架[1],目前市場(chǎng)上的主流框架(庫(kù))有jQuery、Vue、React與Angular等。但這幾種框架的代碼量太大,架構(gòu)體系也比較繁瑣,所以本文選取一種成熟且經(jīng)典的框架,即Zepto進(jìn)行分析[2]。該框架雖然出現(xiàn)時(shí)間較早,但作為設(shè)計(jì)框架的例子進(jìn)行分析是十分適合的。首先,其架構(gòu)與當(dāng)前熱門(mén)的jQuery很相似;其次,其代碼量簡(jiǎn)短,可方便進(jìn)行更透徹的分析。而框架的所有內(nèi)容都是對(duì)底層知識(shí)的封裝,采用原生Javascript與其對(duì)比的方法進(jìn)行分析,可起到事半功倍的效果[3]。
1 Zepto簡(jiǎn)介
Zepto在5年前是一款十分熱門(mén)的框架,其應(yīng)用領(lǐng)域在于移動(dòng)端,與jQuery框架十分相似。Zepto框架大量參考了jQuery的API,簡(jiǎn)化了對(duì)部分瀏覽器的兼容,例如IE。因此,可以說(shuō)它是為移動(dòng)端量身打造的[4],但其核心模塊只有不到一千行的代碼,相對(duì)于jQuery一萬(wàn)多行的代碼量,其無(wú)論是分析還是編寫(xiě)都方便許多。同時(shí),它也是眾多前端開(kāi)發(fā)者分析框架對(duì)象的首選。
2 Javascript原型
在原生Javascript的知識(shí)體系中,上下文環(huán)境、作用域、原型鏈、同步與單線程是重點(diǎn),也是難點(diǎn)。在介紹Zepto設(shè)計(jì)原理前,先對(duì)Javascript原型進(jìn)行分析,這也是Zepto的設(shè)計(jì)基礎(chǔ)。每創(chuàng)建一個(gè)新函數(shù),都會(huì)根據(jù)一組特定規(guī)則為該函數(shù)創(chuàng)建一個(gè)prototype屬性,該屬性指向函數(shù)的原型對(duì)象。在默認(rèn)情況下,所有原型對(duì)象都會(huì)自動(dòng)獲得一個(gè)constructor(構(gòu)造函數(shù))屬性,該屬性包含一個(gè)指向prototype屬性所在函數(shù)的指針[10]。
圖1展示了Person構(gòu)造函數(shù)、Person原型屬性以及Person現(xiàn)有兩個(gè)實(shí)例間的關(guān)系。在此,Person.prototype指向原型對(duì)象,而Person.prototype.constructor又指向Person。原型對(duì)象中除包含constructor屬性外,還包括后來(lái)添加的屬性。Person的每個(gè)實(shí)例,如person1和person2都包含一個(gè)內(nèi)部屬性,該屬性?xún)H指向Person.prototype。也即是說(shuō),它們與構(gòu)造函數(shù)沒(méi)有直接關(guān)系[5]。因此,可以在構(gòu)造函數(shù)的原型對(duì)象中定義公共的屬性或方法,例如圖1中的name、age、job和sayName,這些方法與屬性是任何一個(gè)通過(guò)構(gòu)造函數(shù)產(chǎn)生的實(shí)例所能共享的。此外,在每個(gè)實(shí)例中,還可以添加額外的屬性與方法,這時(shí)添加的屬性與方法是每個(gè)實(shí)例單獨(dú)享有的[11]。
3 Zepto設(shè)計(jì)原理
先分析一個(gè)簡(jiǎn)單的html頁(yè)面,代碼如下:
var MYMp = MYM(‘p); //MYMp是數(shù)組
var MYMspan = MYM(‘span); //MYMspan是數(shù)組
通過(guò)API可以知道MYMp.addClass是一個(gè)函數(shù),這是一般數(shù)組不具備的,在控制臺(tái)輸出MYMp instanceof Array為false,也驗(yàn)證了MYMp不是一個(gè)常規(guī)數(shù)組的實(shí)例。與通常遇到的不同,正如原型里提到的,通過(guò)函數(shù)new輸出的內(nèi)容,都會(huì)有個(gè)指針指向該函數(shù)的原型對(duì)象,而將原型對(duì)象重構(gòu)后,即可獲得大量所需的方法。Zepto正是采用該方式對(duì)原型對(duì)象進(jìn)行了改造。因此,每一個(gè)看似數(shù)組的內(nèi)容可以同時(shí)具備數(shù)組與非數(shù)組的方法。這也是Zepto的核心設(shè)計(jì)理念,即重定義原型對(duì)象內(nèi)容[6]。
4 Zepto源碼分析
Zepto框架主要架構(gòu)如下:
varZepto = (function(){
var MYM, zepto = { }
//省略N行代碼
function Z(dom, selector){
vari, len=dom?dom.length : 0
for(i=0; i
}
對(duì)于zepto.Z函數(shù),代碼如下所示:
function Z(dom, selector){
var i, len = dom ? dom.length : 0
for(i=0; i this[i] = dom[i] this.length = len this.selector = selector || ‘ } } zepto.Z = function(dom, selector){ return new Z(dom, selector) } MYM.fn = { //…多種屬性 } zepto.Z.prototype = Z.prototype = MYM.fn 這里對(duì)構(gòu)造函數(shù)Z進(jìn)行了實(shí)例化,Z函數(shù)與之前提到的原型密切相關(guān),將原型函數(shù)進(jìn)行重構(gòu),會(huì)獲得許多自定義的屬性與方法。MYM.fn函數(shù)是Z函數(shù)原型的出處,里面封裝了一系列原生Javascript的內(nèi)容,將其與原生Javascript對(duì)比可發(fā)現(xiàn),slice、each等方法都可以在原生方法中找到對(duì)應(yīng)部分,同時(shí)考慮到兼容問(wèn)題,整個(gè)原型對(duì)象即可完整呈現(xiàn)。至此,整個(gè)Zepto框架組合完畢,詳細(xì)的屬性方法可在API文檔中查看。 5 結(jié)語(yǔ) 縱觀互聯(lián)網(wǎng)浪潮中的前端領(lǐng)域,其發(fā)展十分迅速,各種組件庫(kù)、框架應(yīng)運(yùn)而生,因此前端也變得越來(lái)越復(fù)雜。但這一切變化都是建立在Html+CSS+Javascript上,而這些底層技術(shù)的變化相對(duì)緩慢[8]。本文分析了框架的設(shè)計(jì)原理與設(shè)計(jì)架構(gòu),將其中的封裝方法與原生Javascript方法進(jìn)行對(duì)比,并闡述了此類(lèi)框架設(shè)計(jì)的核心要點(diǎn)[9]。當(dāng)然,在分析過(guò)程中也存在一些不足,如沒(méi)有將封裝方法與原生方法進(jìn)行一一比對(duì),框架代碼未能全部展現(xiàn)出來(lái)等,將在后續(xù)工作中進(jìn)一步改進(jìn)。 參考文獻(xiàn): [1] 王悅.基于Extjs4的Web前端框架設(shè)計(jì)與應(yīng)用[D].青島:中國(guó)海洋大學(xué),2015. [2] 王保平.對(duì)JavaScript框架的再思考[J].程序員,2008(11):24. [3] 樊紅珍.JavaScript框架jQuery和ExtJS的對(duì)比研究[J].現(xiàn)代計(jì)算機(jī)月刊,2011(1):23-24. [4] 李紅.主流Javascript框架比較與分析[J].鞍山師范學(xué)院學(xué)報(bào),2015(4):40-47. [5] 司徒正美.JavaScript框架設(shè)計(jì)[M].北京:人民郵電出版社,2014. [6] 歐查德,LM. JavaScript框架高級(jí)編程:應(yīng)用Prototype、YUI、Ext JS、Dojo、MooTools[M].北京:清華大學(xué)出版社,2011. [7] 栗新雨.兩款jQuery前端框架(DWZ和MiniUI)之比較[J].計(jì)算機(jī)光盤(pán)軟件與應(yīng)用,2013(20):276. [8] 姜艷.一種基于JavaScript框架的混合應(yīng)用開(kāi)發(fā)技術(shù)[J].網(wǎng)絡(luò)新媒體技術(shù),2016,5(4):59-64. [9] 代慶梅.淺析JavaScript MVC框架在Web開(kāi)發(fā)中的應(yīng)用[J].電腦知識(shí)與技術(shù):學(xué)術(shù)交流,2014(4):2242-2245. [10] 彭敦陸,杜雪鋒.基于Web服務(wù)的組件集成技術(shù)在客戶(hù)關(guān)系管理中的應(yīng)用[J].上海理工大學(xué)學(xué)報(bào),2004,26(1):71-75. [11] 蔣偉良,徐福緣.ADO方案與胖客戶(hù)環(huán)境下的交互HTML數(shù)據(jù)庫(kù)設(shè)計(jì)[J].上海理工大學(xué)學(xué)報(bào),1999(2):184-187. [12] JENSEN S H, MLLER A, THIEMANN P. Type analysis for JavaScript[J]. Lecture Notes in Computer Science, 2009,5673:238-255. [13] GUHA A, SAFTOIU C, KRISHNAMURTHI S. The essence of JavaScript[J]. Lecture Notes in Computer Science, 2015,6183:126-150. (責(zé)任編輯:黃 健)