摘要:靜態屬性靜態方法目前支持靜態方法表示,類屬性及靜態屬性目前作為提案還未正式成為標準。在中,抽象類不能用來實例化對象,主要做為其它派生類的基類使用。不同于接口,抽象類可以包含成員的實現細節。中也是這樣規定的抽象類不允許直接被實例化。
嘗試重寫
在此之前,通過《JavaScript => TypeScript 入門》已經掌握了類型聲明的寫法。原以為憑著那一條無往不利的規則,就可以開開心心的重寫 JS 項目了。當我躍躍欲試去重寫一個 JS 項目時,發現阻礙重重。
在投靠 TS 時,TypeScript 允許將 JS 漸進式的過渡到 TS:
一些簡單的基本類型聲明的填充,比如:number, :string, :string[] 等等;
將一些稍復雜的、暫時還未提煉好的結構聲明為 any 類型;
改后綴為 .ts, 執行 tsc 編譯。
但一個明顯的問題是,一個 JS 文件中往往有很多模塊依賴,意味著要把所有這些模塊都重新做一次類型聲明,才能整體編譯通過。
所以,要想暢通無阻的重寫 JS,在上一篇入門的基礎上,還得強忍著沖動,繼續學習兩部分內容:
1、TS 類的寫法、特征
2、TS 模塊、命名空間
好在,它們和 ES6 其實有著很多重合的地方——要記得,TS 是 ES6 的超集。所以如果掌握了 ES6,我們只要挑差異,找增量,進行遷移學習,就能快速掌握上述內容。
ES6 的類ES6 的類的概念,和普遍編程語言的類概念一致,表示一種特有的數據結構。它既像一個函數(能被 new 調用),又像一個對象(包含了各種屬性、方法)。
class MyClass { constructor() { this.attr = "my attribute"; } foo(name) { console.log("hello " + name); } } let myclass = new MyClass();
類中的方法屬性被稱為 “成員”,這些成員大概被分成 3 種類別:
公有屬性、公有方法
私有屬性、私有方法
靜態屬性、靜態方法
在寫繼承時,我們并不希望在所有時候,這些屬性、方法都被繼承到子類;在訪問成員時,也不希望在任何時候,類實例的所有成員都無一例外可以被訪問;有時候我們希望與此相反,這樣能保持開放出去的信息簡潔干凈。
JS 很早就有這些概念,但到現在為止,ES6 并沒有處理好這個事情。
私有屬性、私有方法ES6 沒有直觀的表示私有屬性、私有方法的方案,只能通過變通的方式間接地表示。
const getKeys = Symbol("getKeys_"); const attr = Symbol("attr_"); class MyClass { constructor() { // 私有屬性 this[attr] = "private attribute"; } // 公有方法 foo(config) { return this[fn](config); } // 私有方法 [getKeys](config) { return Object.keys(config); } };
這僅僅是一個間接取巧的方式避免直接被訪問到,但很輕易就能繞過它:
let myclass = new MyClass(); let symbolsAttr = Object.getOwnPropertySymbols(myclass); let attr_ = myclass[symbolsAttr[0]]; // 即訪問到私有屬性 let symbolsFn = Object.getOwnPropertySymbols(myclass.__proto__); let getKeys_ = myclass[symbolsFn[0]]; // 即訪問到私有方法
私有方法、私有屬性的目的是不想開放過多的信息到外部。上面變通的方案雖然表面上達到了目的,但是不夠直觀,也不安全。
靜態屬性、靜態方法ES6 目前支持靜態方法表示,類屬性及靜態屬性目前作為提案還未正式成為標準。
class MyClass { name = "jeremy"; // ES6 不被支持,僅作為提案 static version = "1.0.0"; // ES6 不被支持,僅作為提案 constructor() { console.log(MyClass.version); // "1.0.0" } static get Version() { return MyClass.version; } }
區分這些成員身份,與動態類型、靜態類型語言沒有必然聯系,可以預見,在不久的將來,ES6 這方面將得到完善。
TS 的類鑒于 TS 是 ES6 的超集這一事實,TS 類當然也有私有屬性、私有方法,靜態屬性、靜態方法等這些身份的成員。在標記成員身份上,TS 與 Java 有很多相似之處。比如與繼承相關的訪問修飾符,以及其他限定作用的非訪問修飾符。
訪問修飾符
private
public
protected
非訪問修飾符
static
readonly
abstract
class User { readonly name: string; public age: number; private sex: string; protected marriage: string; constructor(name: string, sex: string) { this.name = name; this.sex = sex; } showAge() { console.log(`${this.name}, age ${this.age}`); } }訪問修飾符
1、當成員被標記成 private 時,它就不能在聲明它的類的外部訪問。
2、protected 修飾符與 private 修飾符的行為很相似,但有一點不同,protected 成員在派生類中仍然可以訪問
3、被聲明為 public 的類、方法、構造方法和接口能夠被任何其他類訪問。
class User { readonly name: string; public age: number; private sex: string; protected marriage: string; constructor(name: string, sex: string) { this.name = name; this.sex = sex; } showAge() { console.log(this.age); } } let a = new User("jerry", "male"); console.log(a.sex); // 編譯報錯:私有屬性不許在本類之外被訪問 console.log(a.marriage); // 編譯報錯:私有屬性不許在類之外被訪問 a.name = "jeremy"; // 編譯報錯:只讀屬性不許再次被寫入
訪問修飾符主要用在繼承的可訪問性上,繼承好比遺傳,用基因類比理解它們就很有意思:
private 私有基因——本體有效,不會被繼承,即子類中無法訪問到
protected 被保護基因——保護血統純正,只允許在繼承體系中訪問
public 公共基因——子類、其他類都能訪問到
有了訪問修飾符,每個成員都有扮演著與身份對應的角色,真正做到名副其實。
訪問修飾符和非訪問修飾符加起來有6個甚至更多,它們如何與類、接口一起搭配工作,考慮到組合情況非常多,此處不去細致的探究。可以參考 Java 的規則:
default (即缺省,什么也不寫): 在同一包(等同于JS中的模塊)內可見,不使用任何修飾符。使用對象:類、接口、變量、方法。
private : 在同一類內可見。使用對象:變量、方法。 注意:不能修飾類(外部類)
public : 對所有類可見。使用對象:類、接口、變量、方法
protected : 對同一包內的類和所有子類可見。使用對象:變量、方法。 注意:不能修飾類(外部類)。
當然更直觀的方式是上代碼 + 編譯。TS 的編譯工具有著非常友好、明確編譯錯誤提示。
class Demo { static private showSelf() {} } // 編譯錯誤提示 error TS1029: "private" modifier must precede "static" modifier.
當然,去查閱官方文檔也是一個好辦法。
非訪問修飾符非訪問修飾符不關心可訪問性,被它多帶帶標記的成員,在任何時候都能訪問到。目前至少有這些:
static
get
set
readonly
abstract
從字面上看,不難理解它們的用途。這里和 ES6 差別較大的是 abstract。
abstract 修飾符abstract 修飾符用來定義抽象類和在抽象類內部定義抽象方法。
在 Java 中,抽象類不能用來實例化對象,主要做為其它派生類的基類使用。 不同于接口,抽象類可以包含成員的實現細節。
TS 中也是這樣規定的:抽象類不允許直接被實例化。
還有一點很重要,抽象類中的抽象方法可以不包含具體實現,但必須在派生類中實現。
// 抽象類 abstract class User { readonly name: string; public age: number; private sex: string; protected marriage: string; constructor(name: string, sex: string) { this.name = name; this.sex = sex; } showAge() { console.log(this.age); } // 抽象方法 abstract showName(): void; } // let a = new User("jerry", "male"); // 編譯報錯: 抽象類不允許直接實例化
容易忽略的一個問題是,一個類中一旦出現抽象方法,那這個類整個應該被標記為 abstract。
class UserA extends User { constructor(name: string, sex: string) { super(name, sex); // console.log(this.sex); // 編譯報錯:私有變量不能被訪問 } // 抽象方法必須要在子類中實現 // 若無此方法,編譯報錯 showName() { console.log(this.name); } }
基本上,對 TS 類只需要掌握這些,深入的部分自然在實踐中繼續領悟。
對了,還有模塊、命名空間沒有梳理。因為碼文字的麻煩,只得留到后續再補。但是直接搬用 ES6 的模塊import, export 就完全夠用了。
So,這回真的去重寫了。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/89951.html
摘要:為了由簡入繁,不妨將這些類型劃分為基本類型復合類型。以下將漸進式的對的這些類型進行了解。實際上,有一種屬性描述對象,是通過獲取的。但無論如何,類型檢查是可以排除大部分錯誤的。在函數的類型聲明中,繼續來鞏固這條規則的寫法。 幾個月前把 ES6 的特性都過了一遍,收獲頗豐。現在繼續來看看 TypesScript(下文簡稱為 TS)。限于經驗,本文一些總結如有不當,歡迎指正。 概述 官網有這...
摘要:前言這個輪子已經有很多人造過了,為了不重復造輪子,我將本項目以三階段實現大家可以在中的查看純前端后端前端后端前端希望能給大家一個漸進學習的經驗。 前言 Vue+Socket.io這個輪子已經有很多人造過了,為了不重復造輪子,我將本項目以三階段實現(大家可以在github中的Releases查看): 純前端(Vuex) 后端+前端(JavaScript) 后端+前端(TypeScrip...
摘要:添加了可選的靜態類型注意并不是強類型和基于類的面向對象編程。類類型接口示例接口更注重功能的設計,抽象類更注重結構內容的體現模塊中引入了模塊的概念,在中也支持模塊的使用。 一:Typescript簡介 維基百科: TypeScript是一種由微軟開發的自由和開源的編程語言。它是JavaScript的一個嚴格超集,并添加了可選的靜態類型和基于類的面向對象編程。C#的首席架構師以及Delp...
摘要:現在,出現了更多本身支持或者通過插件支持語法智能提示糾錯甚至是內置編譯器的文本編輯器和。 TypeScript是什么 TypeScript是JavaScript的一個超集 TypeScript需要編譯為JavaScript才能運行(語法糖) TypeScript提供了類型系統,規范類似Java TypeScript提供了ES6的支持,也可以支持部分ES7草案的特性,不用擔心TypeS...
摘要:入門,第一個這是一門很新的語言,年前后正式公布,算起來是比較年輕的編程語言了,更重要的是它是面向程序員的函數式編程語言,它的代碼運行在之上。它通過編輯類工具,帶來了先進的編輯體驗,增強了語言服務。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺已經到來了,總結過去的 2017,相信小伙們一定有很多收獲...
閱讀 3702·2021-11-23 09:51
閱讀 1360·2021-11-10 14:35
閱讀 4008·2021-09-22 15:01
閱讀 1279·2021-08-19 11:12
閱讀 379·2019-08-30 15:53
閱讀 1690·2019-08-29 13:04
閱讀 3429·2019-08-29 12:52
閱讀 3055·2019-08-23 16:14