TypeScript與JavaScript的區(qū)別分析
TypeScript是微軟開發(fā)的一個開源的編程語言,通過在JavaScript的基礎上添加靜態(tài)類型定義構建而成。由于JavaScript語言本身的局限性,難以勝任大型項目的開發(fā)和維護。因此微軟開發(fā)了TypeScript ,使得其能夠勝任大型項目的開發(fā)。TypeScript通過TypeScript編譯器或Babel轉譯為JavaScript代碼,可運行在任何瀏覽器,任何操作系統(tǒng)。
TypeScript可以使用JavaScript中的所有代碼和編程概念,TypeScript是為了使JavaScript的開發(fā)變得更加容易而創(chuàng)建的。推薦先精通JS的的前提下再學習TS,這樣更有利于同時學習兩門語言。
TypeScript優(yōu)勢
與JavaScript相比,TypeScript有很多好處。
TS 使代碼重構變得更加容易,并且更強調(diào)顯式類型,使開發(fā)人員能夠掌握各種組件的交互方式。由于它支持編譯時調(diào)試,對于處理大型復雜應用程序的團隊來說,有一定的好處。
為任何項目設置TypeScript都是容易的。一些框架,如Angular,默認使用TypeScript。因此,在我看來TypeScript更勝一籌。
什么時候應該將項目遷移到TypeScript?
當代碼的大小、復雜性和出錯率增加時,需要在編譯過程中確定具體問題時,就可以使用TypeScript。
TypeScript 還具有接口和訪問修飾符,允許開發(fā)人員在單個代碼庫上進行協(xié)作和交互。因此,最好在項目一開始就使用TypeScript。
但是你如果喜歡像Ember.js或Glimmer.js這樣的框架,那你就不會喜歡TypeScript,這些框架的首選是JavaScript。
TypeScript 與 JavaScript 的區(qū)別
TypeScript 是 JavaScript 的超集,擴展了 JavaScript 的語法,因此現(xiàn)有的 JavaScript 代碼可與 TypeScript 一起工作無需任何修改,TypeScript 通過類型注解提供編譯時的靜態(tài)類型檢查。
TypeScript 可處理已有的 JavaScript 代碼,并只對其中的 TypeScript 代碼進行編譯。
TS一般用于大型項目,就像微信小程序底層庫是用TS實現(xiàn)的,而微信小程序自身即應用層卻是以JS來實現(xiàn)的。
復雜性是一個需要考慮的關鍵因素。JavaScript 非常適合更簡單的應用程序,因為它可以在所有平臺(跨平臺)上運行并且非常輕量級。另外,與JS的最小開銷相比,編譯TS代碼需要的時間和CPU資源對項目而言會更麻煩。
TypeScript 其實就是類型化的 JavaScript,它不僅支持 JavaScript 的所有特性,還在 JavaScript 的基礎上添加了靜態(tài)類型注解擴展。從某種意義上來說,TypeScript 其實就是 JavaScript 的超集。在 TypeScript 中,我們不僅可以輕易復用 JavaScript 的代碼、最新特性,還能使用可選的靜態(tài)類型進行檢查報錯,使得編寫的代碼更健壯、更易于維護。比如在開發(fā)階段,我們通過 TypeScript 代碼轉譯器就能快速消除很多低級錯誤(如 typo、類型等)。
TypeScript基本語法
在語法層面,缺省類型注解的 TypeScript 與 JavaScript 完全一致。因此,我們可以把 TypeScript 代碼的編寫看作是為 JavaScript 代碼添加類型注解。在 TypeScript 語法中,類型的標注主要通過類型后置語法來實現(xiàn)。
let num = 1;
示例中的語法同時符合 JavaScript 語法和 TypeScript 語法。而 TypeScript 語法與 JavaScript 語法的區(qū)別在于,我們可以在 TypeScript 中顯式聲明變量num僅僅是數(shù)字類型,也就是說只需在變量num后添加: number類型注解即可
let num: number = 1;
TypeScript原始類型
在 JavaScript 中,原始類型指的是非對象且沒有方法的數(shù)據(jù)類型,它包括 string、number、bigint、boolean、undefined 和 symbol 這六種 (null 是一個偽原始類型,它在 JavaScript 中實際上是一個對象,且所有的結構化類型都是通過 null 原型鏈派生而來)。在 JavaScript 語言中,原始類型值是最底層的實現(xiàn),對應到 TypeScript 中同樣也是最底層的類型。
1.字符串
在 JavaScript 中,我們可以使用string表示 JavaScript 中任意的字符串(包括模板字符串)
let firstname: string = 'Captain'; // 字符串字面量 let familyname: string = String('S'); // 顯式類型轉換 let fullname: string = `my name is ${firstname}.${familyname}`; // 模板字符串
2.數(shù)字
number類型表示 JavaScript 已經(jīng)支持或者即將支持的十進制整數(shù)、浮點數(shù),以及二進制數(shù)、八進制數(shù)、十六進制數(shù)
/** 十進制整數(shù) */ let integer: number = 6; /** 十進制整數(shù) */ let integer2: number = Number(42); /** 十進制浮點數(shù) */ let decimal: number = 3.14; /** 二進制整數(shù) */ let binary: number = 0b1010; /** 八進制整數(shù) */ let octal: number = 0o744; /** 十六進制整數(shù) */ let hex: number = 0xf00d; /** 如果使用較少的大整數(shù),那么我們可以使用bigint類型來表示 */ let big: bigint = 100n;
3.布爾值
boolean表示 True 或者 False
/** TypeScript 真香 為 真 */ let TypeScriptIsGreat: boolean = true; /** TypeScript 太糟糕了 為 否 */ let TypeScriptIsBad: boolean = false;
4.Symbol原始類型
我們可以通過Symbol構造函數(shù),創(chuàng)建一個獨一無二的標記
let sym1: symbol = Symbol(); let sym2: symbol = Symbol('42');
當然,TypeScript 還包含 Number、String、Boolean、Symbol 等類型(注意區(qū)分大小寫)。
let sym: symbol = Symbol('a'); let sym2: Symbol = Symbol('b'); sym = sym2 // ok or fail? sym2 = sym // ok or fail? let str: String = new String('a'); let str2: string = 'a'; str = str2; // ok or fail? str2 = str; // ok or fail?
實際上,我們壓根使用不到 Number、String、Boolean、Symbol 類型,因為它們并沒有什么特殊的用途。這就像我們不必使用 JavaScript Number、String、Boolean 等構造函數(shù) new 一個相應的實例一樣。
{ let mustBeNum = 1; } { let mustBeNum: number = 1; }
下面,我們對上面的示例稍做一下修改
{ let mustBeNum = 'badString'; } { let mustBeNum: number = 'badString'; }
如果變量所處的上下文環(huán)境特別復雜,在開發(fā)階段就能檢測出低級類型錯誤的能力將顯得尤為重要,而這種能力主要來源于 TypeScript 實現(xiàn)的靜態(tài)類型檢測。
5.靜態(tài)類型檢測
在編譯時期,靜態(tài)類型的編程語言即可準確地發(fā)現(xiàn)類型錯誤,這就是靜態(tài)類型檢測的優(yōu)勢。在編譯(轉譯)時期,TypeScript 編譯器將通過對比檢測變量接收值的類型與我們顯示注解的類型,從而檢測類型是否存在錯誤。如果兩個類型完全一致,顯示檢測通過;如果兩個類型不一致,它就會拋出一個編譯期錯誤,告知我們編碼錯誤,具體示例如下代碼所示:
const trueNum: number = 42; const fakeNum: number = "42"; // ts(2322) Type 'string' is not assignable to type 'number'.
TypeScript引用類型
1.數(shù)組
因為 TypeScript 的數(shù)組和元組轉譯為 JavaScript 后都是數(shù)組,所以這里我們把數(shù)組和元組這兩個類型整合到一起介紹,也方便你更好地對比學習。
2.數(shù)組類型(Array)
在 TypeScript 中,我們也可以像 JavaScript 一樣定義數(shù)組類型,并且指定數(shù)組元素的類型。
/** 子元素是數(shù)字類型的數(shù)組 */ let arrayOfNumber: number[] = [1, 2, 3]; /** 子元素是字符串類型的數(shù)組 */ let arrayOfString: string[] = ['x', 'y', 'z'];
3.元組類型(Tuple)
元組最重要的特性是可以限制數(shù)組元素的個數(shù)和類型,它特別適合用來實現(xiàn)多值返回。我們熟知的一個使用元組的場景是 React Hooks(關于 React Hooks 的簡介請點擊這里查看),例如 useState 示例:
import { useState } from 'react' function useCount() { const [count, setCount] = useState(0); return ....; }
4. any
any 指的是一個任意類型,它是官方提供的一個選擇性繞過靜態(tài)類型檢測的作弊方式。我們可以對被注解為 any 類型的變量進行任何操作,包括獲取事實上并不存在的屬性、方法,并且 TypeScript 還無法檢測其屬性是否存在、類型是否正確。比如我們可以把任何類型的值賦值給 any 類型的變量,也可以把 any 類型的值賦值給任意類型(除 never 以外)的變量,如下代碼所示:
let anything: any = {}; anything.doAnything(); // 不會提示錯誤 anything = 1; // 不會提示錯誤 anything = 'x'; // 不會提示錯誤 let num: number = anything; // 不會提示錯誤 let str: string = anything; // 不會提示錯誤
5. unknown
unknown 是 TypeScript 3.0 中添加的一個類型,它主要用來描述類型并不確定的變量。比如在多個 if else 條件分支場景下,它可以用來接收不同條件下類型各異的返回值的臨時變量,如下代碼所示:
let result: unknown; if (x) { result = x(); } else if (y) { result = y(); } ...
6. void、undefined、null
考慮再三,我們還是決定把 void、undefined 和 null “三廢柴”特殊類型整合到一起介紹。依照官方的說法,它們實際上并沒有太大的用處,尤其是在本專欄中強烈推薦并要求的 strict 模式下,它們是名副其實的“廢柴”。首先我們來說一下 void 類型,它僅適用于表示沒有返回值的函數(shù)。即如果該函數(shù)沒有返回值,那它的類型就是 void。在 strict 模式下,聲明一個 void 類型的變量幾乎沒有任何實際用處,因為我們不能把 void 類型的變量值再賦值給除了 any 和 unkown 之外的任何類型變量。然后我們說說 undefined 類型 和 null 類型,它們是 TypeScript 值與類型關鍵字同名的唯二例外。但這并不影響它們被稱為“廢柴”,因為單純聲明 undefined 或者 null 類型的變量也是無比雞肋,示例如下所示:
let undeclared: undefined = undefined; // 雞肋 let nullable: null = null; // 雞肋
undefined 的最大價值主要體現(xiàn)在接口類型上,它表示一個可缺省、未定義的屬性。這里分享一個稍微有點費解的設計:我們可以把 undefined 值或類型是 undefined 的變量賦值給 void 類型變量,反過來,類型是 void 但值是 undefined 的變量不能賦值給 undefined 類型。
const userInfo: { id?: number; } = {}; let undeclared: undefined = undefined; let unusable: void = undefined; unusable = undeclared; // ok undeclared = unusable; // ts(2322)
而 null 的價值我認為主要體現(xiàn)在接口制定上,它表明對象或?qū)傩钥赡苁强罩?。尤其是在前后端交互的接口,比?Java Restful、Graphql,任何涉及查詢的屬性、對象都可能是 null 空對象,如下代碼所示:
const userInfo: { name: null | string } = { name: null };
7. never
never 表示永遠不會發(fā)生值的類型,這里我們舉一個實際的場景進行說明。首先,我們定義一個統(tǒng)一拋出錯誤的函數(shù),代碼示例如下:
function ThrowError(msg: string): never { throw Error(msg); }
以上函數(shù)因為永遠不會有返回值,所以它的返回值類型就是 never。同樣,如果函數(shù)代碼中是一個死循環(huán),那么這個函數(shù)的返回值類型也是 never,如下代碼所示。
function InfiniteLoop(): never { while (true) {} }
never 是所有類型的子類型,它可以給所有類型賦值,如下代碼所示。
let Unreachable: never = 1; // ts(2322) Unreachable = 'string'; // ts(2322) Unreachable = true; // ts(2322) let num: number = Unreachable; // ok let str: string = Unreachable; // ok let bool: boolean = Unreachable; // ok
8. object
object 類型表示非原始類型的類型,即非 number、string、boolean、bigint、symbol、null、undefined 的類型。然而,它也是個沒有什么用武之地的類型,如下所示的一個應用場景是用來表示 Object.create 的類型。
declare function create(o: object | null): any; create({}); // ok create(() => null); // ok create(2); // ts(2345) create('string'); // ts(2345)
TypeScript 類型檢測無法做到絕對智能,畢竟程序不能像人一樣思考。有時會碰到我們比 TypeScript 更清楚實際類型的情況,比如下面的例子:
const arrayNumber: number[] = [1, 2, 3, 4]; const greaterThan2: number = arrayNumber.find(num => num > 2); // 提示 ts(2322)
小結
TypeScript 其實就是添加了類型注解的 JavaScript,它并沒有任何顛覆性的變動。因此,學習并掌握 TypeScript 一定會是一件極其容易的事情。
到此這篇關于TypeScript與JavaScript的區(qū)別分析的文章就介紹到這了,更多相關TypeScript與JavaScript的區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
ts?類型體操?Chainable?Options?可鏈式選項示例詳解
這篇文章主要為大家介紹了ts?類型體操?Chainable?Options?可鏈式選項示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-09-09TypeScript與JavaScript的區(qū)別分析
TypeScript可以使用JavaScript中的所有代碼和編程概念,TypeScript是為了使JavaScript的開發(fā)變得更加容易而創(chuàng)建的。推薦先精通JS的的前提下再學習TS,這樣更有利于同時學習兩門語言。2022-12-12TypeScript數(shù)據(jù)結構棧結構Stack教程示例
這篇文章主要為大家介紹了TypeScript數(shù)據(jù)結構棧結構Stack教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02PureScript與JavaScript中equality設計的使用對比分析
這篇文章主要為大家介紹了PureScript中的equality與JavaScript中的equality設計對比分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-11-11Typescript是必須要學習嗎?如何學習TS全棧開發(fā)
Typescript目前在前端,網(wǎng)站,小程序中的位置基本無可替代,同時也可以構建完美的CLI應用。在移動,桌面,后端方面,性能不是要求很高的情況下完全可以勝任,并且在區(qū)塊鏈,嵌入式,人工智能方面也開始茁壯成長。2022-12-12