摘要:今天看到寫的中的和都錯(cuò)了,覺得很有意思,所以也研究了一下。但既然用,就是為了用它的靜態(tài)檢查,所以要充分關(guān)注編譯錯(cuò)誤提示。很遺憾,同樣的錯(cuò)誤。的正式名稱是,即那么,現(xiàn)在來說說的結(jié)果。因此在我實(shí)際工作中遇到類似問題的概率非常低,不糾結(jié)
今天看到 @justjavac 寫的《ES6 中的 this & super:babel 和 typescript 都錯(cuò)了》,覺得很有意思,所以也研究了一下。
借用 @justjavac 的示例代碼,略做修改,然后在幾種語言中跑了一下,結(jié)果
語言(版本) | 輸出1 | 輸出2 | 輸出3 |
---|---|---|---|
ES6 | 3 | undefined | 3 |
Babel | 2 | undefined | 2 |
TypeScript (?) | 2 | 3 | 2 |
C# | 3 | 3 | 3 |
Java | 3 | 3 | 3 |
是的,我加入了 C# 和 Java 的運(yùn)行結(jié)果,畢竟它們是真正的 OOP 語言。另外請注意到,我在 TypeScript 后面加了個(gè)問號 (?),因?yàn)閷?shí)際上 TypeScript 雖然編譯成了對應(yīng)的 JS,但是轉(zhuǎn)譯過程中是會(huì)報(bào)錯(cuò)的:
index.ts (20,15): Only public and protected methods of the base class are accessible via the "super" keyword. (2340) index.ts (22,27): Only public and protected methods of the base class are accessible via the "super" keyword. (2340)
下面,我從 C#/Java 說起
C# / Java對于 C#/Java 這樣的真正的 OOP 語言來說,super.x 和 this.x 其實(shí)是一個(gè)東西,因?yàn)樵谧宇愔袥]有重新定義這個(gè)成員 x。以 C# 代碼為例
using System; public class Program { public static void Main() { var t = new ColorPoint(); t.test(); } } class Point { public int x; protected void getValue() { Console.WriteLine(this.x); } } class ColorPoint : Point { public ColorPoint() { this.x = 2; base.x = 3; Console.WriteLine(this.x); Console.WriteLine(base.x); } public void test() { this.getValue(); } }
上面這段代碼是為了與下面這段代碼進(jìn)行比較——假如我們在子類中重新定義 x 呢?
class ColorPoint : Point { public new int x; public ColorPoint() { this.x = 2; base.x = 3; Console.WriteLine(this.x); Console.WriteLine(base.x); } public void test() { this.getValue(); } }
它的輸出是 2、3、3,為什么?
this.x 是 2 好理解,super.x 是 3 也好理解。而 getValue() 中實(shí)際取的是父類中的 x,似乎有點(diǎn)不好理解——
其實(shí)也不難理解,因?yàn)樽宇愔兄匦露x了 x,它和父類中的 x 就不是同一個(gè)東西了,只是正好名稱相同而已。
另一個(gè)方面來理解:子類中重新定義 x,而不是重載(也不可能重載字段,只有方法和屬性可以重載),那么 getValue() 就不會(huì)順著虛函數(shù)鏈去找到最近的一個(gè)定義,也就不會(huì)取到子類中的賦值。
TypeScript在 TypeScript 的 Playground 中運(yùn)行下面的代碼確實(shí)可以得到 2、3、2:
class Point { public x: number; protected getValue() { console.log(this.x); } } class ColorPoint extends Point { constructor() { super(); this.x = 2; super.x = 3; console.log(this.x); console.log(super.x); } test() { this.getValue(); } } const t = new ColorPoint(); t.test();
問題在于,不管是在 Playground 還是 VSCode 還是 vsc(編譯器),都會(huì)得到錯(cuò)誤提示
Only public and protected methods of the base class are accessible via the "super" keyword.
這里提到了用 super 的兩個(gè)條件,一個(gè)是 public 或 protected 修飾,二個(gè)是 methods。第二個(gè)條件就是關(guān)鍵所在:TypeScript 中只能通過 super 調(diào)用方法,所以 super.x 從語法上來說就是錯(cuò)的!我不知道 Anders Hejlsberg 為什么要在語法錯(cuò)誤的情況仍然輸出結(jié)果——也許是為了容錯(cuò)性。但既然用 TypeScript,就是為了用它的靜態(tài)檢查,所以要充分關(guān)注編譯錯(cuò)誤提示。
現(xiàn)在來試驗(yàn)一下介于 field 和 method 之間的情況,使用 getter/setter 語法的屬性。
class Point { private _x: number; public get x(): number { return this._x; } public set x(value: number) { this._x = value; } protected getValue() { console.log(this.x); } }
很遺憾,同樣的錯(cuò)誤。就這一點(diǎn)來說,我覺得 TypeScript 還有待進(jìn)步。
ES6 / ES2015 / BabelES6 的正式名稱是 ECMAScrip 2015,即 ES2015
那么,現(xiàn)在來說說 ES6 的結(jié)果 3、undefined、3。
……
可是,我除了說不能理解之外,還能說什么呢?
既然 super.x = 3 都可以起作用,憑什么 console.log(super.x) 就取不到值?從這一點(diǎn)上來說,Babel 的結(jié)果 (2、undefined、2) 反而更符合邏輯。
小結(jié)ES6 的結(jié)果我不能理解,也許能從 ECMAScript 2015 Language Specification 中找到答案,不過我沒耐心去閱讀這個(gè)長而枯燥的英文文檔——如果有人找到了答案,麻煩告訴我一聲,萬分感謝!
不管怎么說,我用 TypeScript 的時(shí)間比較多,而且忠實(shí)于編譯器的錯(cuò)誤提示。因此在我實(shí)際工作中遇到類似問題的概率非常低,不糾結(jié) ^_^!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/88281.html
摘要:工具軟件欲先攻其事必先利其器,用好工具是做好開發(fā)的基礎(chǔ)??蚣苣壳白盍餍泻唵我子茫絹碓蕉嗳擞迷?jīng)很流行,現(xiàn)在有點(diǎn)衰退狀態(tài)管理后端渲染開發(fā)工具依賴管理,應(yīng)用打包,任務(wù)管理,編輯器擴(kuò)展,,移動(dòng)端有了前端的知識(shí)后,我們還可以開發(fā)手機(jī)。 2019年即將到來,各位同學(xué)2018年辛苦了。 不管大家2018年過的怎么樣,2019年還是要繼續(xù)加油的! 在此我整理了個(gè)人認(rèn)為在2019仍是或者將成為主流的...
摘要:是的超級,遵循最新的規(guī)范相當(dāng)于包含了的語法。表示方法沒有返回任何類型類型表示的是那些永不存在的值的類型,例如異常錯(cuò)誤寫法錯(cuò)誤三函數(shù)內(nèi)容概述函數(shù)的定義可選參數(shù)默認(rèn)參數(shù)剩余參數(shù)函數(shù)重載箭頭函數(shù)。 一、Typescript 介紹、環(huán)境搭建 1.1 Typescript 介紹 1.TypeScript 是由微軟開發(fā)的一款開源的編程語言,像后端 java、C#這樣的面向?qū)ο笳Z言可以讓 js 開發(fā)...
摘要:當(dāng)你陷在一個(gè)中大型項(xiàng)目中時(shí)應(yīng)用日趨成為常態(tài),沒有類型約束類型推斷,總有種牽一發(fā)而動(dòng)全身的危機(jī)和束縛??傮w而言,這些付出相對于代碼的健壯性和可維護(hù)性,都是值得的。目前主流的都為的開發(fā)提供了良好的支持,比如和。參考資料中文文檔 文章博客地址:http://pinggod.com/2016/Typescript/ TypeScript 是 JavaScript 的超集,為 JavaScrip...
摘要:不過,相對于靜態(tài)類型檢查帶來的好處,這些代價(jià)是值得的。當(dāng)然少不了的模塊化標(biāo)準(zhǔn),雖然到目前為止和大部分瀏覽器都還不支持它。本身支持兩種模塊化方式,一種是對的模塊的微小擴(kuò)展,另一種是在發(fā)布之前本身模仿的命名空間。有一種情況例外。 TypeScript 帶來的最大好處就是靜態(tài)類型檢查,所以在從 JavaScript 轉(zhuǎn)向 TypeScript 之前,一定要認(rèn)識(shí)到添加類型定義會(huì)帶來額外的工作量...
摘要:將轉(zhuǎn)換成常見的使用實(shí)現(xiàn)的基于迭代器的迭代。處停止迭代器基于鴨子模型接口這里使用語法僅僅為了說明問題使用支持為了使用迭代器屬性需要引入。生成器是迭代器的子類,包含了附加的與。 原文地址:http://babeljs.io/docs/learn-...本文基于Luke Hoban精妙的文章《es6features》,請把star獻(xiàn)給他,你可以在此嘗試這些特性REPL。 概述 ECMAScr...
閱讀 1914·2023-04-26 02:51
閱讀 2965·2021-09-10 10:50
閱讀 3233·2021-09-01 10:48
閱讀 3751·2019-08-30 15:53
閱讀 1916·2019-08-29 18:40
閱讀 470·2019-08-29 16:16
閱讀 2099·2019-08-29 13:21
閱讀 1873·2019-08-29 11:07