- 原文地址:What's the longest keyword sequence in Javascript?
- 原文做者:Leo Horie
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:xionglong58
- 校對者:Endone, Jingyuan0000
最近有幾個關於使用 Javascript 編寫最長關鍵字序列的挑戰。前端
但問題是:android
讓咱們試試能不能作的更好。ios
(可是咱們首先要回顧一些基礎規則)git
@arjunb_msft 提出的最長 15 個關鍵字的程序github
function *f() {
if (1);
else do return yield delete true instanceof typeof void new class extends false in this {}; while (1)
}
複製代碼
不幸的是,他的方法裏使用了保留字 true
和 false
,而二者實際上不是關鍵字。在 Chrome 中運行程序也會拋出一個錯誤:「Uncaught SyntaxError: Unexpected token in」。編程
@bluepnume 提出 15 個關鍵字的方案是:後端
async function* foo() {
return yield delete void await null in this instanceof typeof new class extends async function () {} {}
}
複製代碼
這段程序能夠在 Chrome 中運行,可是程序中使用了 null
,這也不是一個關鍵字。async
雖然有些賣弄,若是咱們從第二個解決方案中剔除 null
,並結合第一個解決方案,能夠獲得一個不一樣的 15 個關鍵字長度的解決方案:編程語言
async function* foo() {
if (0);
else do return yield delete void await this instanceof typeof new class extends async function () {} {}; while (0)
}
複製代碼
哦耶!oop
雖然這樣作沒什麼意思,但賣弄知識卻頗有趣。
但不用擔憂,由於在下面的討論中 Bterlson 做了這樣的補充:
this
、null
和undefined
能夠認爲是關鍵字,即便它們在技術上不是關鍵字。這使得比賽更有趣(加上編輯們把它們標記成關鍵字,因此這麼說也行得通)
從技術層面講,this
其實是一個關鍵字。可是,Bterlson 對 null
和 undefined
不是關鍵字的認定倒是正確的。
在餘下部分,咱們能夠看到 true
和 false
也被看成關鍵字使用。這就給咱們帶來了一個問題:若是可使用非關鍵字標記,那麼對於這個挑戰,哪些標記更合適?
null
、true
和 false
的共同點是它們都是隻包含字母的字面量(顯然,包含字符和數字的字面量是不容許的)。
因爲可使用 null 字符和 boolean 字符,咱們能夠輕鬆地復現出先前的序列,並構建 17 個單詞長度的序列:
async function* foo() {
if (0);
else do return yield await delete void typeof null instanceof this in new class extends async function () {} {}; while (0);
}
複製代碼
那 undefined
呢?它其實是一個標識符。若是容許 ASI,那咱們就可使用任意標識符去構造一個無限序列,但這就索然無味了,也失去了挑戰的樂趣。
a
b
c
// boooring
複製代碼
我倒認爲這項挑戰的意義在於僅使用相似關鍵字的標記完成挑戰(即便這些相似關鍵字的詞在技術層面不能算做規範的關鍵字)。
下面是一些看起來像關鍵字但實際上不是關鍵字的標記:
let x
for (foo of bar) {}
class { static foo() {} }
import {foo as bar} from 'baz'
{get foo() {}, set foo() {}}
複製代碼
若是你不喜歡仔細研究編程語言諸多的規範,並且不能一眼看出哪些標記是關鍵字,哪些不是關鍵字,那麼下面的標記均可以看成是關鍵字:let
、of
、static
、as
、from
、get
、set
。它們看起來也確實像關鍵字。
咱們可能認爲不能夠往上面的列表中添加 NaN
和 Infinity
之類的東西,是由於它們與 undefined
屬於同一個類型,都是標識符(標識符老是指向相同的值),也多是因爲只容許使用小寫字符。無論怎樣,咱們將它們排除在外。咱們也應該排除 atguments
,由於在語法規範中它沒有做爲標記出現,所以它實際上只是一個 magic 變量,而不是關鍵字。
另外一個咱們須要排除是 new.target
,由於它中間有一個「.」。
一些標記例如 enum
和 public
是保留字,它們看起來很是像關鍵字,特別是若是你熟悉像 Java 這樣的語言。問題是,它們在語法中幾乎到處都會自動變成語法錯誤,因此即便咱們容許使用它們,也不能真正地使用它們...
// the party poopers
let enum // SyntaxError
interface Bar {} // SyntaxError
package Baz; // SyntaxError
class {
private foo() {} // SyntaxError
}
複製代碼
既然咱們已經理清了規則,咱們接下來能作什麼呢?
固然有不少啦
因爲一向的向後兼容性問題,在某些狀況下,許多「關鍵字」 充當...呃,不能稱它們爲關鍵詞。咱們以前說過濫用 ASI 和標識符很無聊,但你知道嗎?在 Javascript 他們倒是有效的語法。
var undefined
typeof let
複製代碼
這固然不是無聊的,並且很是有但願,因此以娛樂的名義,咱們必須容許它。
最後還有一個小細節要談。雖然上面的代碼片斷頗有趣,並且讓人眼花繚亂,但它有一個問題:它跨越了兩行。很不幸,但咱們須要 ASI 將這兩個語句分開,因此咱們沒法將它們放在同一行。
或者這樣作:
輸入一個段落分隔符(\u2029
),若是正確呈現,它看起來以下:
什麼都看不見?這就對了!這是一個隱形變量。
如今,有了上面的知識儲備,咱們能夠提出本身的解決方案:
async function* foo() {
from: set: while (0) {
if (0)
throw as
else this
null
continue from
false
break set
true
var let
debugger
do return yield await delete void typeof get instanceof static in new class of extends async function undefined () {} {}; while (0);
}
}
複製代碼
你沒看錯,這就是在 Chrome 上解析和運行有效的 Javascript 程序。這但是在一行中有 32 個關鍵字的序列!
固然,並非全部 32 個詞都是關鍵字,這多是 ASI 有史以來最嚴重的濫用,可是,這仍然有挑戰意義。另外,我很開心,這纔是最重要的!
那麼,你以爲呢?你能作一個更長的序列嗎?你能弄明白爲何這在語法上是有效的嗎?這是做弊嗎?Gists [譯者注:原文發佈在 gist 上]是有史以來最被濫用的博客平臺嗎?
若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。