成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

精讀《Optional chaining》

cncoder / 2228人閱讀

摘要:由于具備一定的使用場(chǎng)景,而且支持方式零成本改寫為即可,所以就支持它吧不支持的特性下面三個(gè)特性不支持,原因是沒什么使用場(chǎng)景安全的安全的上面兩者的結(jié)合首先看一個(gè)對(duì)象,如果出來(lái)的結(jié)果是,那這個(gè)返回值使用起來(lái)也沒有意義。

1. 引言

備受開發(fā)者喜愛的特性 Optional chaining 在 2019.6.5 進(jìn)入了 stage2,讓我們?cè)敿?xì)讀一下草案,了解一下這個(gè)特性的用法以及討論要點(diǎn)。

借著這次精讀草案,讓我們了解一下一個(gè)完整草案的標(biāo)準(zhǔn)文檔結(jié)構(gòu)是怎樣的。

一個(gè)新特性的文檔,首先要描述 起因 是什么,也就是為什么要增加這個(gè)特性,大家不會(huì)沒有理由的就增加一個(gè)特性。其次是其他語(yǔ)言是否有現(xiàn)成的實(shí)現(xiàn)版本,參考他們并進(jìn)行歸納總結(jié),可以增加思考角度的全面性。

第三點(diǎn)就是 語(yǔ)法介紹,也就進(jìn)入了新特性的正題,這里要詳細(xì)介紹所有可能的使用情況。第四點(diǎn)是 語(yǔ)義,也就是詮釋語(yǔ)法的含義。

然后是可選的 是否有不支持的情況,對(duì)于不支持的點(diǎn)是否有意而為之,為什么?此處一般會(huì)留下討論的 ISSUE。然后是 暫不考慮的點(diǎn),是由于性價(jià)比低、使用場(chǎng)景少,或者實(shí)現(xiàn)成本高的原因,為什么某些已經(jīng)想到的點(diǎn)暫不考慮,這里也會(huì)留下討論的 ISSUE。

后面一般還有 “正在討論的點(diǎn)”、“FAQ”、“草案進(jìn)度”、“參考文獻(xiàn)”、“相關(guān)問(wèn)題”、“預(yù)先討論資料” 等內(nèi)容。

2. 概述&精讀

首先讓我們回顧一下什么是 “Optional chaining”。

起因介紹

當(dāng)訪問(wèn)一個(gè)深層樹形結(jié)構(gòu)的對(duì)象時(shí),我們總需要判斷中間節(jié)點(diǎn)屬性是否存在:

var street = user.address && user.address.street;

而且很多 API 返回的屬性都可能為 Null,而我們往往只想獲取非 Null 時(shí)的結(jié)果:

var fooInput = myForm.querySelector("input[name=foo]")
var fooValue = fooInput ? fooInput.value : undefined
筆者這里補(bǔ)充,在人機(jī)交互的領(lǐng)域,可能為 Null 的情況很多。首先是交互行為模塊很多,行為復(fù)雜,很容易導(dǎo)致數(shù)據(jù)分散且難以預(yù)測(cè)(可能為空),僅是 DOM 元素就需要太多兼容,因?yàn)?DOM 被修改的實(shí)際太多了,大家都在共享一個(gè)可變的結(jié)構(gòu);其次是交互過(guò)程中間狀態(tài)很多,出現(xiàn)狀態(tài)殘缺的可能性也很大,就拿 SQL 解析為例:后端只要檢測(cè) Query 是否正確就可以了,但前端的 SQL 編輯器需要在輸入不完整的情況下給出提示,也就是在語(yǔ)法樹錯(cuò)誤的情況下給出提示,因此需要進(jìn)行容錯(cuò)。

而 Optional chaining 可以解決為了容錯(cuò)而寫過(guò)多重復(fù)代碼的問(wèn)題:

var street = user.address?.street
var fooValue = myForm.querySelector("input[name=foo]")?.value

正如上面的例子:如果 user.addressundefined,那 street 拿到的就是 undefined,而不是報(bào)錯(cuò)。

配合另一個(gè)在 stage2 的新特性 Nullish Coalescing 做默認(rèn)值處理非常方便:

// falls back to a default value when response.setting is missing or nullish
// (response.settings == null) or when respsonse.setting.animationDuration is missing
// or nullish (response.settings.animationDuration == null)
const animationDuration = response.settings?.animationDuration ?? 300;

?? 號(hào)可以理解為 “默認(rèn)值場(chǎng)景下的 ||”:

const response = {
  settings: {
    nullValue: null,
    height: 400,
    animationDuration: 0,
    headerText: "",
    showSplashScreen: false
  }
};

const undefinedValue = response.settings?.undefinedValue ?? "some other default"; // result: "some other default"
const nullValue = response.settings?.nullValue ?? "some other default"; // result: "some other default"
const headerText = response.settings?.headerText ?? "Hello, world!"; // result: ""
const animationDuration = response.settings?.animationDuration ?? 300; // result: 0
const showSplashScreen = response.settings?.showSplashScreen ?? true; // result: false

0 || 1 的結(jié)果是 1,因?yàn)?0 判定為 false,而 || 在前面的變量為 false 型才繼續(xù)執(zhí)行,而我們想要的是 “前面的對(duì)象不存在時(shí)才使用后面的值”。?? 則代表了 “前面的對(duì)象不存在” 這個(gè)含義,即便值為 0 也會(huì)認(rèn)為這個(gè)值是存在的。

Optional chaining 也可以用在方法上:

iterator.return?.()

或者試圖調(diào)用某些未被實(shí)現(xiàn)的方法:

if (myForm.checkValidity?.() === false) { // skip the test in older web browsers
    // form validation fails
    return;
}

比如某個(gè)舊版本瀏覽器不支持 myForm.checkValidity 方法,則不會(huì)報(bào)錯(cuò),而是返回 false。

已有實(shí)現(xiàn)調(diào)研

Optional chaining 在 C#、Swift、CoffeeScript、Kotlin、Dart、Ruby、Groovy 已經(jīng)實(shí)現(xiàn)了,且實(shí)現(xiàn)方式均有差異,可以看到每個(gè)語(yǔ)言在實(shí)現(xiàn)語(yǔ)法時(shí)都是有取舍的,但是大方向基本是相同的。

想了解其他語(yǔ)言是如何實(shí)現(xiàn) Optional chaining 的讀者可以 點(diǎn)擊閱讀原文。

這些語(yǔ)言實(shí)現(xiàn) Optional chaining 的差異基本在 語(yǔ)法、支持范圍、邊界情況處理 等不同,所以如果你每天要在不同語(yǔ)言之間切換工作,看似相同的語(yǔ)法,但不同的細(xì)節(jié)可能把你繞暈(所以會(huì)的語(yǔ)言多,只會(huì)讓你變成一個(gè)速記字典,滿腦子都是哪些語(yǔ)言在哪些語(yǔ)法討論傾向哪一邊,選擇了哪些特性這些毫無(wú)意義的結(jié)論,如果不想記這些,基礎(chǔ)語(yǔ)法都沒有掌握怎么好意思說(shuō)會(huì)這門語(yǔ)言呢?所以學(xué) JS 就夠了)。

語(yǔ)法

Optional Chaining 的語(yǔ)法有三種使用場(chǎng)景:

obj?.prop       // optional static property access
obj?.[expr]     // optional dynamic property access
func?.(...args) // optional function or method call

也就是將 . 替換為 ?.,但要注意第二行與第三行稍稍有點(diǎn)反直覺,比如在函數(shù)調(diào)用時(shí),需要將 func(...args) 寫為 func?.(...args)。至于為什么語(yǔ)法不是 func?(...args) 這種簡(jiǎn)潔一點(diǎn)的表達(dá)方式,在 FAQ 中有提到這個(gè)例子:

obj?[expr].filter(fun):0 引擎難以判斷 obj?[expr] 是 Optional Chaning,亦或這是一個(gè)普通的三元運(yùn)算語(yǔ)句。

可見,要支持 ?. 這個(gè)看似簡(jiǎn)單的語(yǔ)法,在整個(gè) JS 語(yǔ)法體系中要考慮的邊界情況很多。

即便是 ?. 這樣完整的用法,也需要注意 foo?.3:0 這種情況,不能將 foo?. 解析為 Optional chanining,而要將其解析為 foo? .3 : 0,這需要解析引擎支持 lookahead 特性。

語(yǔ)義

當(dāng) ?. 前面的變量值為 nullundefined 時(shí),?. 返回的結(jié)果為 undefined。

a?.b                          // undefined if `a` is null/undefined, `a.b` otherwise.
a == null ? undefined : a.b

a?.[x]                        // undefined if `a` is null/undefined, `a[x]` otherwise.
a == null ? undefined : a[x]

a?.b()                        // undefined if `a` is null/undefined
a == null ? undefined : a.b() // throws a TypeError if `a.b` is not a function
                              // otherwise, evaluates to `a.b()`

a?.()                        // undefined if `a` is null/undefined
a == null ? undefined : a()  // throws a TypeError if `a` is neither null/undefined, nor a function
                             // invokes the function `a` otherwise
短路

所謂短路,就是指引入了 Optional chaining 后,某些看似一定會(huì)執(zhí)行的語(yǔ)句在特定情況下會(huì)短路(終止執(zhí)行),比如:

a?.[++x]         // `x` is incremented if and only if `a` is not null/undefined
a == null ? undefined : a[++x]

第一個(gè)例子,如果 a 時(shí) null/undefined,就不會(huì)執(zhí)行 ++x

原因是這段代碼部分等價(jià)于 a == null ? undefined : a[++x],如果 a == null 為真,自然不會(huì)執(zhí)行 a[++x] 這個(gè)語(yǔ)句。但由于 Optional chaining 使這個(gè)語(yǔ)句變得 “簡(jiǎn)潔了”,雖然帶來(lái)了便利,但也可能導(dǎo)致看不清完整的執(zhí)行邏輯,引發(fā)誤判。

所以看到 ?. 語(yǔ)句時(shí),一定要反射性的思考一下,這個(gè)語(yǔ)句會(huì)觸發(fā) “短路”。

長(zhǎng)“短路”

Optional chaining 在 JS 的規(guī)范中,作用域僅限于調(diào)用處??聪旅娴睦樱?/p>

a?.b.c(++x).d  // if `a` is null/undefined, evaluates to undefined. Variable `x` is not incremented.
               // otherwise, evaluates to `a.b.c(++x).d`.
a == null ? undefined : a.b.c(++x).d

可以看到 ?. 僅在 a?. 這一層生效,而不是對(duì)后續(xù)的 b.c、c(++x).d 繼續(xù)生效。而對(duì)于 C+ 與 CoffeeScript,這個(gè)語(yǔ)法是對(duì)后續(xù)所有 get 生效的(這里再次提醒,不要用 CoffeeScript 了,因?yàn)閷?duì)于相同語(yǔ)法,語(yǔ)義都發(fā)生了變化,對(duì)你與你的同事都是巨大的理解負(fù)擔(dān),或者說(shuō)沒有人愿意注意,為什么代碼在 CoffeeScript 里不報(bào)錯(cuò),而轉(zhuǎn)移到 JS 就報(bào)錯(cuò)了,是因?yàn)?Optional chaining 語(yǔ)義不一致造成的。)。

正因?yàn)?Optional chaining 在 JS 語(yǔ)法中僅對(duì)當(dāng)前位置起保護(hù)作用,因此一個(gè)調(diào)用語(yǔ)句中允許出現(xiàn)多個(gè) ?. 調(diào)用:

a?.b[3].c?.(x).d
a == null ? undefined : a.b[3].c == null ? undefined : a.b[3].c(x).d
  // (as always, except that `a` and `a.b[3].c` are evaluated only once)

上面這段代碼,對(duì) a?.b、c?.(x) 的訪問(wèn)與調(diào)用是安全的,而對(duì)于 b[3]、 b[3].c、c?.(x).d 的調(diào)用是不安全的。

在 FAQ 環(huán)節(jié)也提到了,為什么不學(xué)習(xí) C# 與 CoffeeScript 的語(yǔ)義,將安全保護(hù)從 a?. 之后就一路 “貫穿” 下去?

原因是 JS 對(duì) Optional chaining 的理解不同導(dǎo)致的。Optional chaining 僅僅是安全訪問(wèn)保護(hù),不代表 try catch,也就是它不會(huì)捕獲異常,舉一個(gè)例子:

a?.b()

這個(gè)調(diào)用,在 a.b 不是一個(gè)函數(shù)時(shí)依然會(huì)報(bào)錯(cuò),原因就是 Optional chaining 僅提供了對(duì)屬性訪問(wèn)的安全保護(hù),不代表對(duì)整個(gè)執(zhí)行過(guò)程進(jìn)行安全保護(hù),該拋出異常還是會(huì)拋出異常,因此 Optional chaining 沒有必要對(duì)后面的屬性訪問(wèn)安全性負(fù)責(zé)。

筆者認(rèn)為 TC39 對(duì)這個(gè)屬性的理解是合理的,否則用 try catch 就能代替 Optional chaining 了。讓一個(gè)特性僅實(shí)現(xiàn)分內(nèi)的功能,是每個(gè)前端從業(yè)者都要具備的思維能力。

PS:筆者再多提一句,在任何技術(shù)設(shè)計(jì)領(lǐng)域,這個(gè)概念都適用。想想你設(shè)計(jì)的功能,寫過(guò)的函數(shù),如果為了圖方便,擴(kuò)大了其功能,終究會(huì)帶來(lái)整體設(shè)計(jì)的混亂,適得其反。
邊界情況 - 分組

我們知道,JS 代碼可以通過(guò)括號(hào)的方式進(jìn)行分組,分組內(nèi)的代碼擁有更高的執(zhí)行優(yōu)先級(jí)。那么在 Optional chaining 場(chǎng)景下考慮這個(gè)情況:

(a?.b).c
(a == null ? undefined : a.b).c

與不帶括號(hào)的進(jìn)行對(duì)比:

a?.b.c
a == null ? undefined : a.b.c

我們會(huì)發(fā)現(xiàn),由于括號(hào)提高了優(yōu)先級(jí),導(dǎo)致在 anull/undefined 時(shí),解析出了 undefined.c 這個(gè)必定報(bào)錯(cuò)的荒謬語(yǔ)法。因此我們不要試圖為 Optional chaining 進(jìn)行括號(hào)分組,這樣會(huì)打破邏輯順序,使安全保護(hù)不但不生效,反而導(dǎo)致報(bào)錯(cuò)。

Optional delete

中文大概可以翻譯為 “安全刪除” 吧,也就是 JS 的 Optional chaining 支持下面的使用方式:

delete a?.b
a == null ? true : delete a.b

這樣不論 b 是否存在,得到的都是 b 刪除成功的信號(hào)(返回值 true)。

至于為什么要支持 Optional delete,草案里也有提到,筆者認(rèn)為非常有意思:

討論重點(diǎn)應(yīng)該是 “我們?yōu)槭裁床恢С?Optional delete”,而不是 “我們?yōu)槭裁匆С?Optional delete”,有點(diǎn)像反證法的思路。由于 Optional delete 具備一定的使用場(chǎng)景,而且支持方式零成本(改寫為 a == null ? true : delete a.b 即可),所以就支持它吧!

不支持的特性

下面三個(gè)特性不支持,原因是沒什么使用場(chǎng)景:

安全的 construction:new a?.()

安全的 template literal:a?.`string`

上面兩者的結(jié)合:new a?.b(), a?.b`string`

首先看 new 一個(gè)對(duì)象,如果 new 出來(lái)的結(jié)果是 undefined,那這個(gè)返回值使用起來(lái)也沒有意義。

對(duì)于第二個(gè)安全的 template literal 來(lái)說(shuō),比如下面的語(yǔ)法:

a?.b
`c`

會(huì)被解析為

a == null ? undefined : a.b`c`

那么對(duì)于下面這種翻譯結(jié)果:

a == null ? undefined : a.b `c`

目前不會(huì)有人這么寫代碼,因?yàn)檫@種語(yǔ)法的使用場(chǎng)景一般都是 “前面的屬性必定存在時(shí)的簡(jiǎn)化語(yǔ)法”,比如 styled-components 的:

div`
  width: 300px;
`

而如果解析為:

(a == null ? undefined : a?.b) `c`

則更不會(huì)有人愿意嘗試這種寫法,所以安全的 template literal 這種需求是不存在的,自然第三種需求也是不存在的。

下面一個(gè)不支持的特性,雖然有一定使用場(chǎng)景,但依然被否定的:

安全的賦值:a?.b = c

討論 ISSUE

筆者總結(jié)一下,一共有這幾種令人煩惱的地方,導(dǎo)致大家不想支持 安全賦值 特性:

短路特性導(dǎo)致的理解成本:

比如 a?.b = c(),如果 anull/undefined,那么函數(shù) c() 就不會(huì)被執(zhí)行,這種語(yǔ)法太違背開發(fā)者的常識(shí),如果支持這個(gè)特性帶來(lái)的理解負(fù)擔(dān)會(huì)很大。

連帶考慮場(chǎng)景很多:

如果支持了這種看似簡(jiǎn)單的賦值場(chǎng)景,那么至少還有下面五種賦值場(chǎng)景需要考慮到:

簡(jiǎn)單賦值: a?.b = c

聚合賦值: a?.b += c, a?.b >>= c

自增,自減: a?.b++, --a?.b

解構(gòu)賦值: { x: a?.b } = c, [ a?.b ] = c

for 循環(huán)中的臨時(shí)賦值: for (a?.b in c), for (a?.b of c)

總和這幾種考慮,支持安全賦值會(huì)帶來(lái)更多靈活的用法,導(dǎo)致代碼復(fù)雜度陡增(想想你的同事大量使用上面的后四種例子,你絕對(duì)想要找他決斗,因?yàn)檫@種寫法和亂用 window 變量一樣,在 JS 允許的框架內(nèi)寫出難以維護(hù)的邏輯,像是鉆了法律的孔子),因此 TC39 決定不支持這種用法,從源頭上杜絕被濫用。

以上不支持的功能點(diǎn)會(huì)在靜態(tài)編譯時(shí)被禁止,但以后也許會(huì)重新討論。

另外對(duì)于 Class 的私有變量是否支持 a?.#b a?.#b() 還在討論中,這取決于私有成員變量草案是否能最終落地。

暫不討論的點(diǎn)

目前有兩個(gè) Optional chaining 功能點(diǎn)暫不討論,分別是 Optional spread 與 Optional destructuring

對(duì)于 Optional spread,建議是:

const arr = [...?listOne, ...?listTwo];
foo(...?args);

但由于可以結(jié)合 Nullish Coalescing 達(dá)到同樣的效果:

foo(...args ?? [])

所以暫時(shí)不深入討論,因?yàn)榇嬖谝饬x不大。

對(duì)于 Optional destructuring,建議是:

// const baz = obj?.foo?.bar?.baz; 
const { baz } = obj?.foo?.bar?;

也就是對(duì)于解構(gòu)用法,在最后一個(gè)位置添加 ?,使其能安全的解構(gòu)。

但由于基于這個(gè)特性會(huì)演變出太多的使用變體:

?const {foo ?: {bar ?: {baz}}} = obj?

或者

const {
  foo?: {
    bar?: { baz }
  }
} = obj;

對(duì)開發(fā)者的理解成本壓力較大,畢竟 Optional chaining 的出發(fā)點(diǎn)只是 ?. 這么簡(jiǎn)單。而且對(duì)于默認(rèn)值,我們又有 ?? 語(yǔ)法可以快速滿足,因此這個(gè)特性的討論也被擱置了。

余下的 Q&A

大部分 Q&A 在上面的解讀都有提及,下面列出剩余的兩個(gè) Q&A:

為什么語(yǔ)法是 ?. 而不是 .? ?

原因是與三元運(yùn)算符沖突了,思考下面的用法:

1.?foo : bar

在 js 中,1. 等價(jià)于 1,那么這就是一個(gè)標(biāo)準(zhǔn)的三元運(yùn)算表達(dá)式,因此 .? 語(yǔ)法會(huì)產(chǎn)生歧義,只能選擇 ?.

為什么 null?.b 的結(jié)果不是 null 呢?

由于 . 表達(dá)式不關(guān)心 . 前面對(duì)象的類型,因?yàn)樗哪康氖窃L問(wèn) . 后面的屬性,因此不會(huì)因?yàn)?null?.b 就返回 null,而是統(tǒng)一返回 undefined。

最后,需要 TC39 最終審核后,Optional chaining 才能進(jìn)入 Stage3,我們拭目以待吧!

3. 總結(jié)

寫一篇 JS 特性草案的完整解讀真的很累,以后也許很少有機(jī)會(huì)這么完整的解讀草案了,但希望借著這次解讀 Optional chaining 的機(jī)會(huì),讓大家理解 TC39 是如何制定草案的,草案都在討論什么,怎么討論的,流程有哪些。

同時(shí),還希望讓大家意識(shí)到,為一個(gè)語(yǔ)言添加一個(gè)看似簡(jiǎn)單的新特性有多么的不容易,一個(gè)簡(jiǎn)單的 ?. 語(yǔ)法就牽涉到與三元運(yùn)算符、分組、解構(gòu)等等已存在語(yǔ)法的交織與沖突,所以想要安全又妥當(dāng)?shù)奶砑右粋€(gè)新特性,參與討論的人必須對(duì) JS 語(yǔ)言有完整全面的理解,同時(shí)也要對(duì)邊界情況考慮的很周全,懂得對(duì)語(yǔ)法融會(huì)貫通。

最后,希望大家可以意識(shí)到,JS 這么重量級(jí)的語(yǔ)言,一個(gè)新的語(yǔ)法特性其實(shí)也是這么三言兩語(yǔ)討論下來(lái)的,其中不乏有一些拍腦袋的地方、對(duì)于“即可也可”的情況,稍稍結(jié)合一些具體案例就定下來(lái)其中一種的現(xiàn)象也是存在的,甚至對(duì)于某些規(guī)范點(diǎn)根本不存在一個(gè)完美的 “真理”,比如為什么語(yǔ)法是 ?. 而不是 a&.b(Ruby 使用的就是 &.),認(rèn)清了這種情況存在,就不會(huì)執(zhí)著于 “語(yǔ)法的學(xué)習(xí)”,而轉(zhuǎn)向更底層,更有用的 “語(yǔ)義的學(xué)習(xí)”,并能通過(guò)閱讀 TC39 的草案了解其他語(yǔ)言的實(shí)現(xiàn)差異,從而快速掌握其他語(yǔ)言的語(yǔ)法。

討論地址是:精讀《Optional chaining》 · Issue #165 · dt-fe/weekly

如果你想?yún)⑴c討論,請(qǐng) 點(diǎn)擊這里,每周都有新的主題,周末或周一發(fā)布。前端精讀 - 幫你篩選靠譜的內(nèi)容。

關(guān)注 前端精讀微信公眾號(hào)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/104761.html

相關(guān)文章

  • 精讀《syntax-parser 源碼》

    摘要:引言是一個(gè)版語(yǔ)法解析器生成器,具有分詞語(yǔ)法樹解析的能力。實(shí)現(xiàn)函數(shù)用鏈表設(shè)計(jì)函數(shù)是最佳的選擇,我們要模擬調(diào)用棧了。但光標(biāo)所在的位置是期望輸入點(diǎn),這個(gè)輸入點(diǎn)也應(yīng)該參與語(yǔ)法樹的生成,而錯(cuò)誤提示不包含光標(biāo),所以我們要執(zhí)行兩次。 1. 引言 syntax-parser 是一個(gè) JS 版語(yǔ)法解析器生成器,具有分詞、語(yǔ)法樹解析的能力。 通過(guò)兩個(gè)例子介紹它的功能。 第一個(gè)例子是創(chuàng)建一個(gè)詞法解析器 my...

    yuanxin 評(píng)論0 收藏0
  • 精讀《手寫 SQL 編譯器 - 錯(cuò)誤提示》

    摘要:總結(jié)做語(yǔ)法解析器錯(cuò)誤提示功能時(shí),再次刷新了筆者三觀,原來(lái)我們以為的必然,在編譯器里對(duì)應(yīng)著那么多可能。語(yǔ)法解析器為了讓報(bào)錯(cuò)符合人們的第一直覺,對(duì)錯(cuò)誤信息做了過(guò)濾,只保留剩余數(shù)最短的那條錯(cuò)誤信息。 1 引言 showImg(https://segmentfault.com/img/remote/1460000016244315?w=1522&h=272); 編譯器除了生成語(yǔ)法樹之外,還要在...

    王陸寬 評(píng)論0 收藏0
  • 精讀《Typescript 3.2 新特性》

    摘要:引言發(fā)布了幾個(gè)新特性,主要變化是類型檢查更嚴(yán)格,對(duì)一些時(shí)髦功能拓展了類型支持。精讀這次改動(dòng)意圖非常明顯,是為了跟上的新語(yǔ)法。基本可以算是對(duì)社區(qū)的回饋。討論地址是精讀新特性如果你想?yún)⑴c討論,請(qǐng)點(diǎn)擊這里,每周都有新的主題,周末或周一發(fā)布。 1 引言 Typescript 3.2 發(fā)布了幾個(gè)新特性,主要變化是類型檢查更嚴(yán)格,對(duì) ES6、ES7 一些時(shí)髦功能拓展了類型支持。 2 概要 下面挑一...

    cucumber 評(píng)論0 收藏0
  • 精讀《手寫 SQL 編譯器 - 語(yǔ)法樹》

    摘要:返回的語(yǔ)法樹作為結(jié)果被傳遞到文法中,其結(jié)果可能是。每個(gè)元素的子節(jié)點(diǎn)全部執(zhí)行完畢,才會(huì)生成當(dāng)前節(jié)點(diǎn)的語(yǔ)法樹。更多討論討論地址是精讀手寫編譯器語(yǔ)法樹如果你想?yún)⑴c討論,請(qǐng)點(diǎn)擊這里,每周都有新的主題,周末或周一發(fā)布。 1 引言 重回 手寫 SQL 編輯器 系列。之前幾期介紹了 詞法、文法、語(yǔ)法的解析,以及回溯功能的實(shí)現(xiàn),這次介紹如何生成語(yǔ)法樹。 基于 《回溯》 一文介紹的思路,我們利用 JS ...

    Caicloud 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

cncoder

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<