1. 程式人生 > >科普:"Field提案"是什麼東東?

科普:"Field提案"是什麼東東?

上次摻和JavaScript的事,是說JavaScript語言有值的問題;再往前一年,就是在“紅綠燈大戰”中討論Promise了。這細數起來,都是兩三年前的舊事了。

但我還是跟進JavaScript的。最新近的事,是持續地討論這個所謂“TC39提案”的事情。本以為真關心的人並不多,但前兩天連老宋都轉了篇貼子過來,“這幫人要把js折騰成啥樣子啊”,老宋說。

“啥樣子?”

1. 導致太下大亂的“Field提案”

“Field提案”全稱是“proposal-class-fields”(在這裡),是試圖在類宣告中新增“Fields”的一項語言設計。提案基本的想法是這樣:

// 在類中宣告欄位(Field)
class Counter { x = 0; foo() { console.log(this.x); // 0 } }

這看起來並沒有什麼大不了,畢竟之前在類中只能宣告方法,新方案可以直接為this.x賦個初值,大家都很happy。

但“欄位(Field)”是什麼?沒人鳥這個問題。

後來這個方案擴充套件了,提供了公開欄位(Public fields)、私有欄位(Private fields)等特性,並整合了種種有關於“類”的提案的思想,還提出了向前相容類裝飾器(decorators)等願景,搖身一變,成了一個巨無霸方案。同時,也不可避免地在社群掀起了軒然大波:多達120餘條issues,其中#100

高達300餘條討論,Git issues折了好幾回才能載入完。

話說,我就是被這個issues入坑的。

那麼,現在這個巨無霸的方案又在講什麼呢?它說起來就是提供了兩個語法:

// 在類中宣告私有欄位(private field)
class Counter {
  #x = 100;
  foo() {
    console.log(this.#x);  // 100
  }
}

然而這樣一來,即便連最初的提案者都跳出來反對了,包括BE大神也反對。即便如此,都擋不住這輛戰車轟隆隆開進到了Stage 3(階段3是提案即將正式寫入規範前的最後一個階段)。而且一併拖上的還有另外兩個方案,稱為“靜態成員與方法(

Static class fields and private static methods)”,以及“私有方法與存取器(Private instance methods and accessors)”。這兩個提案推動的語法是這樣:

// 物件欄位
class Counter {
  // 宣告私有欄位(private fields)
  #xValue = 100;

  // 宣告和使用存取器(accessors for private name '#x')
  get #x() { return #xValue; }
  set #x(value) {
    this.#xValue = value; 
  }

  // 私有方法
  #foo() {
    this.#x++;
  }
}

// 類(靜態)欄位
class Counter2 {
  // 宣告類私有欄位(class private fields)
  static #x = 100;

  // 訪問類私有欄位
  static foo2() {
    console.log(Counter2.#x);
  }

  // 類私有方法
  static #foo2() {
    Counter2.foo2();
  }
}

等等,這還不夠,又還有一份與此相關的提案進入了Stage 2。是這種所謂“未來的裝飾器”:

class Counter {
  @observed #x = 0;

  @bound
  #clicked() {
    this.#x++;
  }
}

還有……

如果你想深入瞭解一點細節,在這裡:

2. 但是,問題是?

難道沒有人注意到麼,到現在為止,誰也沒有(或許也是不敢)說清楚:

Fields是什麼?

如果一個欄位不是屬性(property),那麼所謂“公開欄位”在語義上跟屬性又有什麼區別?如果它是屬性,那麼它為什麼不在屬性表中,而是一個“私有名(private names in scope over the same body of code)”呢?

所以,打蛇就得打七寸。沒人說得清這個問題,還沒有人敢說,所以你看,我跑去git裡面提issues了(在這裡)。往深底裡,人家能跟你分析規範的每一步,但往這概念上一問就沒人說話了。

所以呢,以後跟人吵架,就不要動刀動槍,開口就問:你從哪裡來?要往哪裡去?人活著是為了什麼?等等這些,就很好了。

回到正題。為什麼沒人討論Fields是什麼呢?不是的,並不是沒有。而是隻要一討論,這個問題的答案就明顯會是“No Fields”,這個答案有人專門寫過,在這裡:

這是本“Fields提案”提及到的幾個相關/類似提案之一。而它的觀點之一就是“沒有欄位”,對“Fields”提出了概念層面的質問。關於這個問題的進一步分析,我在上面的提及的issues裡面也講了,或者也可以看看中文版(在這裡)。

3. 更多的聲音

終於有人無法忍受巨大冗長的#100了,於是@mbrowne在@littledan的倡議下開了#150這個新主題。對大家的觀點做了提煉,從@hax的主要觀點開始:

  1. TC39極大地低估了該標準導致社群分裂(community break)的風險,這對所有人來說都是有害的。
  2. TC39現在的議事流程完全無法阻止災難。
  3. 一些TC39的成員和支持者基於迴圈論證和雙重標準來驅逐別人的意見和競爭性提案。

隨後總結的部分觀點包括(#100裡的討論者太多了,作者一時半會兒大概也數不過來):

  • 明顯的語法混淆與歧義 @hax @rdking
  • 向TC39表達不滿,對提案長期目標或效果置疑 @rdking @bdistin
  • 否定"Fields"這一概念,建議在"Property"的概念基礎上實現相關特性 @hax @rdking @mbrowne @shannon @aimingoo
  • 否定“不可探測(Undetectability)”這一需求,認為它並不能提供足夠的保護性 @rdking
  • 新的語法或語言特性與既有體驗之間的衝突,例如動態語言特性;或對語法的長期影響置疑 @rdking @bdistin @mbrowne @shannon
  • 語法不友好,在概念表達上存在多重指向;推薦啟用private關鍵字 @hax @rdking @mbrowne @aimingoo
  • 推薦Symbol.private或者其它 @Igmat @shannon

喜大普奔的是,幾乎所有批評者都表達了對@hax前三條主要觀點的贊同,TC39被嚴重打臉。