自制前端前端框架 Day14. 回顧并理清思路

  1. 寫(xiě)到這兒的時(shí)候其實(shí)思路就有點(diǎn)亂了,很大部分的原因是之前的代碼寫(xiě)了太久猪落,有的地方確實(shí)忘了仍秤。所以今天打算趁機(jī)總結(jié)一下回顧一下。
  2. 寫(xiě)這個(gè)parser的原因是實(shí)現(xiàn)前端的表達(dá)式部分临燃。
  3. parser的流程是拿到表達(dá)式,表達(dá)式肯定是個(gè)字符串,解析字符串膜廊,生成token乏沸。
  4. 然后在AST構(gòu)建階段,通過(guò)消耗token來(lái)構(gòu)建AST爪瓜。
  5. compile階段是通過(guò)AST的節(jié)點(diǎn)類(lèi)型選擇相應(yīng)的流程進(jìn)行編譯蹬跃,歸根結(jié)底是編譯出一個(gè)字符串,并且用這個(gè)字符串生成一個(gè)Function铆铆。

數(shù)字和字符串和true,false,null

  1. 無(wú)論是整數(shù)還是小數(shù)蝶缀,還是科學(xué)計(jì)數(shù),還是字符串還是布爾值算灸,都會(huì)生成一個(gè)token扼劈,這個(gè)token和其他token不同的是,這個(gè)token有一個(gè)value屬性菲驴。這種token稱(chēng)為constants類(lèi)型的token荐吵。
  2. 構(gòu)建AST的時(shí)候,先檢測(cè)這個(gè)token是不是其他的token赊瞬,如果都不符合先煎,才會(huì)認(rèn)為這個(gè)token是一個(gè)constants類(lèi)型的token,進(jìn)入處理constants的流程巧涧。
  3. constants會(huì)將這種token轉(zhuǎn)化成Literal類(lèi)型的節(jié)點(diǎn)薯蝎,Literal類(lèi)型的節(jié)點(diǎn)有一個(gè)value屬性。
  4. 在編譯階段谤绳,Literal類(lèi)型的節(jié)點(diǎn)會(huì)返回它的value屬性占锯。

數(shù)組

  1. 數(shù)組會(huì)生成中括號(hào)和引號(hào)等token,中括號(hào)和引號(hào)這類(lèi)token是屬于identifier類(lèi)型的token缩筛。
  2. 構(gòu)建AST時(shí)消略,如果遇到中括號(hào)的token,說(shuō)明是一個(gè)數(shù)組瞎抛,需要進(jìn)入數(shù)組流程艺演。
  3. 在數(shù)組流程里面,會(huì)生成一個(gè)ArrayExpression類(lèi)型的節(jié)點(diǎn)桐臊,這個(gè)節(jié)點(diǎn)有elements屬性胎撤,用于存儲(chǔ)數(shù)組內(nèi)容。
  4. 編譯的時(shí)候断凶,遇到這個(gè)ArrayExpression節(jié)點(diǎn)伤提,會(huì)把elements屬性中的內(nèi)容都遍歷出來(lái),返回一個(gè)字符串懒浮。
case ASTBuilder.ArrayExpression:
      var elements = [];
      for (var i = 0; i < ast.elements.length; i++) {
        elements.push(this.recurse(ast.elements[i]))
      }
      return "[" + elements.join(',') + "]";

對(duì)象

  1. 對(duì)象就如同數(shù)組飘弧,會(huì)生成大括號(hào)以及冒號(hào)等token识藤。
  2. AST階段砚著,遇到大括號(hào)的時(shí)候會(huì)進(jìn)入對(duì)象流程次伶,最后得到一個(gè)ObjectExpression節(jié)點(diǎn),這個(gè)節(jié)點(diǎn)有一個(gè)properties屬性稽穆,用于記錄對(duì)象的屬性值冠王。
    3.編譯階段,還是會(huì)以字符串的形式處理ObjectExpression節(jié)點(diǎn)舌镶。
case ASTBuilder.ObjectExpression:
      var properties = [];
      for (var i = 0; i < ast.properties.length; i++) {
        var key = ast.properties[i].key.name;
        var value = this.escape(ast.properties[i].value.value);
        properties.push(key + ":" + value);
      }
      return "{" + properties.join(',') + "}";

尋找屬性部分

  1. 遇到parse('name')這種不是字符串也不是值的時(shí)候柱彻,產(chǎn)生identifier類(lèi)型token。
  2. 產(chǎn)生的AST節(jié)點(diǎn)是MemberExpression餐胀。
  3. 編譯遇到MemberExpression節(jié)點(diǎn)哟楷,檢測(cè)節(jié)點(diǎn)的object屬性和property屬性。
  4. property屬性可以進(jìn)行另一次primary流程否灾,找到一個(gè)token卖擅。
  5. object屬性可能是一個(gè)ast樹(shù)。需要遍歷墨技。不管怎樣惩阶,object總會(huì)返回一個(gè)變量。拿這個(gè)圖來(lái)說(shuō):
image.png

最深入的節(jié)點(diǎn)是紅色部分user扣汪,identifier類(lèi)型断楷,在這里會(huì)檢測(cè)scope和local,返回一個(gè)變量v0崭别。
然后是綠色部分冬筒,也是一個(gè)object,返回一個(gè)變量是v1=v0.student茅主。
最后到外層返回的是v2 = v1.name舞痰。在program部分得到的結(jié)果就是
return v2

如果是中括號(hào)分割的MemberExpression,則產(chǎn)生的變量為v1=v0[student]...以此類(lèi)推暗膜。

方法調(diào)用部分

0.假設(shè)是這樣的代碼:

var scope = {
      user:{
        name: 'wangji',
        getName: function () {
          return this.name;
        }
      }
    }
    var fn = parse('user.getName()');
    expect(fn(scope)).toBe('wangji');
  1. 遇到帶括號(hào)的identifier匀奏,代表是方法調(diào)用。
  2. AST階段產(chǎn)生的是CallExpression節(jié)點(diǎn)学搜。這個(gè)節(jié)點(diǎn)有callee屬性娃善,代表方法調(diào)用時(shí)候的上下文,arguments屬性瑞佩,代表方法調(diào)用時(shí)候的參數(shù)聚磺,這里記錄的是實(shí)參。
  3. 難度在于解析方法中的this關(guān)鍵字炬丸。
  4. 思路是在遇到CallExpression的時(shí)候瘫寝,recurse的時(shí)候傳入一個(gè)context對(duì)象蜒蕾,這個(gè)對(duì)象有name屬性用來(lái)記錄方法名(getName),left屬性用來(lái)記錄方法所屬的對(duì)象(scope.user)
  5. 編譯的時(shí)候編譯CallExpression的callee屬性時(shí)候,傳入一個(gè)context空對(duì)象焕阿,經(jīng)過(guò)一系列編譯后咪啡,往里面不斷填充內(nèi)容,成為所需要的context對(duì)象暮屡。
  6. 這個(gè)callee屬性是一個(gè)MemberExpression節(jié)點(diǎn)撤摸,于是編譯它的object屬性,這個(gè)object屬性返回一個(gè)變量v1=scope.user褒纲;記錄下來(lái)context.context=v1.
  7. 然后把v1和property屬性組裝准夷,變成v0=v1.getName;返回v0。
  8. 這時(shí)候callee成為了v0莺掠。檢測(cè)context對(duì)象衫嵌,發(fā)現(xiàn)是有內(nèi)容的,所以callee變成v1.getName
  9. 最終執(zhí)行的函數(shù)是scope.user.getName()
    10.如果不加context對(duì)象彻秆,最終執(zhí)行的是v0&&vo()

其核心在于函數(shù)調(diào)用時(shí)候的所在上下文楔绞,如果直接調(diào)用v0(),那么v0里面的this是與window對(duì)象綁定的掖棉,如果調(diào)用的是v1.getName墓律,那么getName里面的this是與v1綁定的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末幔亥,一起剝皮案震驚了整個(gè)濱河市耻讽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌帕棉,老刑警劉巖针肥,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異香伴,居然都是意外死亡慰枕,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)即纲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)具帮,“玉大人,你說(shuō)我怎么就攤上這事低斋》涮” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵膊畴,是天一觀的道長(zhǎng)掘猿。 經(jīng)常有香客問(wèn)我,道長(zhǎng)唇跨,這世上最難降的妖魔是什么稠通? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任衬衬,我火速辦了婚禮,結(jié)果婚禮上改橘,老公的妹妹穿的比我還像新娘滋尉。我一直安慰自己,他們只是感情好唧龄,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布兼砖。 她就那樣靜靜地躺著奸远,像睡著了一般既棺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上懒叛,一...
    開(kāi)封第一講書(shū)人閱讀 49,816評(píng)論 1 290
  • 那天丸冕,我揣著相機(jī)與錄音,去河邊找鬼薛窥。 笑死胖烛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的诅迷。 我是一名探鬼主播佩番,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼罢杉!你這毒婦竟也來(lái)了趟畏?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤滩租,失蹤者是張志新(化名)和其女友劉穎赋秀,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體律想,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡猎莲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了技即。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片著洼。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖而叼,靈堂內(nèi)的尸體忽然破棺而出身笤,到底是詐尸還是另有隱情,我是刑警寧澤澈歉,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布展鸡,位于F島的核電站,受9級(jí)特大地震影響埃难,放射性物質(zhì)發(fā)生泄漏莹弊。R本人自食惡果不足惜涤久,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望忍弛。 院中可真熱鬧响迂,春花似錦、人聲如沸细疚。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)疯兼。三九已至然遏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間吧彪,已是汗流浹背待侵。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留姨裸,地道東北人秧倾。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像傀缩,于是被迫代替她去往敵國(guó)和親那先。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理赡艰,服務(wù)發(fā)現(xiàn)售淡,斷路器,智...
    卡卡羅2017閱讀 134,633評(píng)論 18 139
  • 目標(biāo)很簡(jiǎn)單 想想現(xiàn)在是個(gè)什么情況瞄摊。token解析肯定沒(méi)問(wèn)題勋又,進(jìn)入primary流程,遇到usertoken的時(shí)候生...
    蚊子爸爸閱讀 242評(píng)論 0 0
  • 端午的第一天我毛都沒(méi)干换帜,除了睡覺(jué)就是晃悠楔壤,還花了兩三個(gè)小時(shí)在玩游戲。唯獨(dú)看了看spring和mybatis惯驼,感覺(jué)也...
    蚊子爸爸閱讀 284評(píng)論 -1 1
  • 回顧思路 昨天把思路縷了一下蹲嚣。假設(shè)這樣編譯這樣一個(gè)字符串parse('user.student.name'),那首...
    蚊子爸爸閱讀 316評(píng)論 0 0
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,773評(píng)論 6 342