TypeScript中三斜線指令的實現(xiàn)
三斜線指令是一系列指令的統(tǒng)稱,它是從TypeScript早期版本就開始支持的編譯指令。目前,已經(jīng)不推薦繼續(xù)使用三斜線指令,因為可以使用模塊來取代它的大部分功能。
正如其名,三斜線指令是以三條斜線開始,并包含一個XML標簽。從JavaScript語法的角度上來看,三斜線指令相當(dāng)于一條單行注釋。若一個文件中使用了三斜線指令,那么在三斜線指令之前只允許使用單行注釋、多行注釋和其他三斜線指令。若某個三斜線指令出現(xiàn)在可執(zhí)行語句之后,那么該三斜線指令將不生效。示例如下:
let count; /// <reference path="lib.ts" /> count = add(1, 2);
此例第3行是一個三斜線指令,而第1行是一條變量聲明語句,因此第3行的三斜線指令將不生效。下面將其修改為正確的使用方式,示例如下:
/// <reference path="lib.ts" /> let count = add(1, 2);
經(jīng)過修改后,在第1行的三斜線指令之前沒有可執(zhí)行語句和聲明,因此該三斜線指令會生效。
1、/// <reference path=“” />
該指令用于聲明TypeScript源文件之間的依賴關(guān)系。在編譯一個文件時,編譯器會同時將該文件中使用“///<reference path=“” />”三斜線指令引用的文件添加到編譯文件列表。
在“/// <reference path=“” />”三斜線指令中,?“path”屬性定義了依賴文件的路徑。若指定的路徑是一個相對路徑,則相對于的是當(dāng)前文件的路徑。
假設(shè)當(dāng)前工程目錄結(jié)構(gòu)如下:
C:\app |-- index.ts `-- lib.ts
其中,?“index.ts”文件依賴于“lib.ts”文件。
“lib.ts”文件內(nèi)容如下:
function add(x: number, y: number): number {
return x + y;
}
“index.ts”文件內(nèi)容如下:
/// <reference path="lib.ts" /> let count = add(1, 2);
在“C:\app”目錄下運行tsc命令來編譯“index.ts”文件。示例如下:
tsc index.ts
由于“index.ts”文件依賴于“lib.ts”文件,所以在編譯“index.ts”文件時,編譯器不但會將“index.ts”文件添加到編譯文件列表,還會將“lib.ts”文件添加到編譯文件列表。
此時,?“C:\app”目錄的結(jié)構(gòu)如下:
C:\app |-- index.js |-- index.ts |-- lib.js `-- lib.ts
1.1、–outFile編譯選項
使用“–outFile”編譯選項能夠?qū)⒕幾g生成的“.js”文件合并為一個文件。但需要注意的是,該編譯選項不支持合并使用了CommonJS模塊和ES6模塊模式的代碼,只有將“–module”編譯選項設(shè)置為None、System或AMD時才有效。
在合并生成代碼的過程中,?“/// <reference path=“”/>”三斜線指令可以作為排序文件的一種手段。
假設(shè)當(dāng)前工程目錄結(jié)構(gòu)如下:
C:\app |-- index.ts |-- lib1.ts `-- lib2.ts
“lib1.ts”文件的內(nèi)容如下:
const a = 'lib1';
“lib2.ts”文件的內(nèi)容如下:
const b = 'lib2';
“index.ts”文件的內(nèi)容如下:
/// <reference path="lib2.ts" /> /// <reference path="lib1.ts" /> const index = 'index';
在“C:\app”目錄下運行tsc命令來編譯“index.ts”文件,并將編譯后的文件合并為“main.js”?。示例如下:
tsc index.ts --outFile main.js
合并后的“main.js”文件內(nèi)容如下:
var b = 'lib2'; var a = 'lib1'; /// <reference path="lib2.ts" /> /// <reference path="lib1.ts" /> var index = 'index';
在“index.ts”文件中,我們先聲明了對“lib2.ts”文件的依賴,后聲明了對“lib1.ts”文件的依賴。在合并后的文件中,?“lib2.ts”文件內(nèi)容將出現(xiàn)在“lib1.ts”文件內(nèi)容之上,在最后的是“index.ts”文件的內(nèi)容。
1.2、–noResolve編譯選項
在默認情況下,編譯器會檢查三斜線指令中引用的文件是否存在,并將它們添加到編譯文件列表。若啟用了“–noResolve”編譯選項,則編譯器將忽略所有的三斜線指令。此時,三斜線指令中引用的文件既不會被添加到編譯文件列表,也不會影響“–outFile”的結(jié)果。
假設(shè)當(dāng)前工程目錄結(jié)構(gòu)如下:
C:\app |-- index.ts |-- lib1.ts `-- lib2.ts
“lib1.ts”文件的內(nèi)容如下:
const a = 'lib1';
“lib2.ts”文件的內(nèi)容如下:
const b = 'lib2';
“index.ts”文件的內(nèi)容如下:
/// <reference path="lib2.ts" /> /// <reference path="lib1.ts" /> const index = 'index';
在“C:\app”目錄下運行tsc命令來編譯“index.ts”文件,同時將編譯后的文件合并為“main.js”?,并啟用“–noResolve”編譯選項。示例如下:
tsc index.ts --outFile main.js --noResolve
合并后的“main.js”文件內(nèi)容如下:
/// <reference path="lib2.ts" /> /// <reference path="lib1.ts" /> var index = 'index';
通過以上運行結(jié)果能夠看到,三斜線指令中引用的“lib1.ts”和“lib2.ts”文件在編譯過程中被忽略了
1.3、 注意事項
在使用“/// <reference path=“” />”三斜線指令時,有以下兩個注意事項:
- “path”屬性必須指向一個存在的文件,若文件不存在則會報錯。
- “path”屬性不允許指向當(dāng)前文件。
例如,如下的“index.ts”文件中兩處對三斜線指令的使用均有錯誤:
/// <reference path="unknown.ts" /> // ~~~~~~~~~~ // 編譯錯誤:文件未找到 /// <reference path="index.ts" /> // ~~~~~~~~~~ // 編譯錯誤:文件不能引用自身
2、/// <reference types=“” />
該三斜線指令用來定義對某個DefinitelyTyped聲明文件的依賴,或者說是對安裝在“node_modules/@types”目錄下的某個聲明文件的依賴。在“/// <reference types=“”/>”三斜線指令中,?“types”屬性的值是聲明文件安裝包的名稱,也就是安裝到“node_modules/@types”目錄下的文件夾的名字。
例如,我們使用如下命令安裝了DefinitelyTyped提供的jQuery聲明文件:
npm install @types/jquery
在安裝后,工程目錄結(jié)構(gòu)如下:
C:\lib
|-- index.d.ts
`-- node_modules
`-- @types
`-- jquery
|-- index.d.ts
`-- package.jsonjQuery聲明文件被安裝在了“C:\lib\node_modules@types\jquery”目錄下。因此,?“jquery”這個名字就是可以在“/// <referencetypes=“” />”三斜線指令中使用的名字。
“C:\lib\index.d.ts”文件的內(nèi)容如下:
/// <reference types="jquery" /> declare var settings: JQuery.AjaxSettings;
注意,我們應(yīng)該只在聲明文件(.d.ts)中使用“/// <reference types=“” />”三斜線指令,而不應(yīng)該在“.ts”文件中使用該指令。在.ts文件中,我們應(yīng)該使用“–types”編譯選項和“–typeRoots”編譯選項來設(shè)置引用的聲明文件。
3、/// <reference lib=“” />
該三斜線指令用于定義對語言內(nèi)置的某個聲明文件的依賴。在前文介紹過,當(dāng)我們在計算機中安裝TypeScript語言時,也會同時安裝一些內(nèi)置的聲明文件。這些聲明文件位于TypeScript安裝目錄下的lib文件夾中,它們描述了JavaScript語言的標準API。內(nèi)置的聲明文件列表如下:
lib.d.ts lib.es2018.full.d.ts lib.dom.d.ts lib.es2018.intl.d.ts lib.dom.iterable.d.ts lib.es2018.promise.d.ts lib.es2015.collection.d.ts lib.es2018.regexp.d.ts lib.es2015.core.d.ts lib.es2019.array.d.ts lib.es2015.d.ts lib.es2019.d.ts lib.es2015.generator.d.ts lib.es2019.full.d.ts lib.es2015.iterable.d.ts lib.es2019.object.d.ts lib.es2015.promise.d.ts lib.es2019.string.d.ts lib.es2015.proxy.d.ts lib.es2019.symbol.d.ts lib.es2015.reflect.d.ts lib.es2020.d.ts lib.es2015.symbol.d.ts lib.es2020.full.d.ts lib.es2015.symbol.wellknown.d.ts lib.es2020.string.d.ts lib.es2016.array.include.d.ts lib.es2020.symbol.wellknown.d.ts lib.es2016.d.ts lib.es5.d.ts lib.es2016.full.d.ts lib.es6.d.ts lib.es2017.d.ts lib.esnext.array.d.ts lib.es2017.full.d.ts lib.esnext.asynciterable.d.ts lib.es2017.intl.d.ts lib.esnext.bigint.d.ts lib.es2017.object.d.ts lib.esnext.d.ts lib.es2017.sharedmemory.d.ts lib.esnext.full.d.ts lib.es2017.string.d.ts lib.esnext.intl.d.ts lib.es2017.typedarrays.d.ts lib.esnext.symbol.d.ts lib.es2018.asyncgenerator.d.ts lib.scripthost.d.ts lib.es2018.asynciterable.d.ts lib.webworker.d.ts lib.es2018.d.ts lib.webworker.importscripts.d.ts
該列表并不是固定的,它會隨著TypeScript版本的升級而更新。
在“/// <reference lib=“” />”三斜線指令中,?“lib”屬性的值是內(nèi)置聲明文件的名稱。內(nèi)置聲明文件統(tǒng)一使用“lib.[description].d.ts”命名方式,而“/// ”指令中“lib”屬性的值就是文件名中的“description”這部分
例如,對于內(nèi)置的“lib.es2015.symbol.wellknown.d.ts”聲明文件,應(yīng)使用如下方式進行引用:
/// <reference lib="es2015.symbol.wellknown" />
3.1、–target編譯選項
“–target”編譯選項能夠設(shè)置程序的目標運行環(huán)境,可選擇的值為:
- ES3(默認值)
- ES5
- ES6 / ES2015
- ES2016
- ES2017
- ES2018
- ES2019
- ES2020
- ESNext
如果我們將“–target”編譯選項設(shè)置為“ES5”?,那么編譯器會自動將適用于“ES5”的內(nèi)置聲明文件添加到編譯文件列表。示例如下:
lib.d.ts lib.es5.d.ts lib.dom.d.ts lib.webworker.importscripts.d.ts lib.scripthost.d.ts
另外,?“–target”編譯選項還決定了對哪些語法進行降級處理。例如,在“ES5”環(huán)境中不支持箭頭函數(shù)語法,因此當(dāng)將“–target”設(shè)置為“ES5”時,編譯后代碼中的箭頭函數(shù)將被替換為“ES5”環(huán)境中支持的函數(shù)表達式。
假設(shè)“index.ts”文件的內(nèi)容如下:
const double = [0, 1, 2].map(val => val * 2);
將“–target”設(shè)置為“ES5”?,然后編譯“index.ts”文件的結(jié)果如下:
var double = [0, 1, 2].map(function (val) {
return val * 2;
});
此例中,箭頭函數(shù)被降級成了常規(guī)的函數(shù)表達式。
將“–target”設(shè)置為“ES6”?,編譯“index.ts”文件的結(jié)果如下:
const double = [0, 1, 2].map(val => val * 2);
此例中,箭頭函數(shù)沒有被降級,因為在“ES6”環(huán)境中支持箭頭函數(shù)這個功能。
3.2、–lib編譯選項
“–lib”編譯選項與“/// <reference lib=“” />”三斜線指令有著相同的作用,都是用來引用語言內(nèi)置的某個聲明文件。
如果將“–target”設(shè)置為“ES6”?,但是我們想使用ES2017環(huán)境中才開始支持的“pad-Start()”函數(shù)。那么,我們就需要引用內(nèi)置的“lib.es2017.string.d.ts”聲明文件,否則編譯器將產(chǎn)生編譯錯誤。
在“tsconfig.json”配置文件中使用“–lib”編譯選項,示例如下:
{
"compilerOptions": {
"target": "ES6",
"lib": ["ES6", "ES2017.String"]
}
}
注意,我們不但要傳入“ES2017.String”?,還要傳入“ES6”?,否則編譯器將僅包含“ES2017.String”這一個內(nèi)置聲明文件,這通常不是我們期望的結(jié)果。
使用“/// <reference lib=“” />”三斜線指令,示例如下:
/// <reference lib="ES2017.String" />
不論使用以上哪種方式,我們都可以在代碼中使用“padStart()”函數(shù),因為編譯器能夠獲取到該函數(shù)的類型信息。示例如下:
'foo'.padStart(10, '-');
需要注意的是,在將“lib.es2017.string.d.ts”內(nèi)置聲明文件添加到編譯文件列表后,雖然編譯器允許使用“padStart()”方法,但是實際的JavaScript運行環(huán)境可能不支持該方法。因為該方法是在ES2017標準中定義的,而JavaScript運行環(huán)境可能仍處于一個較舊的版本,因此不支持這個新方法。這樣就會導(dǎo)致程序可以成功地編譯,但是在運行時出錯,因為找不到“padStart()”方法的定義。
在實際項目中,我們通過引入“polyfill”腳本來解決這個常見問題。?“polyfill”已經(jīng)成為了Web開發(fā)領(lǐng)域中的一個術(shù)語,在很多地方它被叫作“膩子腳本”?,個人感覺叫作“填充腳本”可能容易理解。?“polyfill”腳本是一段JavaScript代碼,它使用普遍支持的Java-Script語法和API來實現(xiàn)新版本JavaScript中才支持的API(在新版本ECMAScript規(guī)范中定義的API)?。因此,它相當(dāng)于用自定義代碼來填充JavaScript運行環(huán)境中缺失的API,從而為JavaScript運行環(huán)境打上了“補丁”?。
到此這篇關(guān)于TypeScript中三斜線指令的實現(xiàn)的文章就介紹到這了,更多相關(guān)TypeScript 三斜線指令內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實現(xiàn)為事件句柄綁定監(jiān)聽函數(shù)的方法分析
這篇文章主要介紹了JavaScript實現(xiàn)為事件句柄綁定監(jiān)聽函數(shù)的方法,結(jié)合實例形式分析了javascript事件綁定的常用技巧與注意事項,需要的朋友可以參考下2017-11-11
JS實現(xiàn)滾動觸底的思路與代碼(附PC端滾動分頁加載數(shù)據(jù))
Javascript實現(xiàn)當(dāng)頁面滾動到底部時觸發(fā)加載事件,可以通過監(jiān)聽窗口的滾動事件,同時判斷當(dāng)前滾動條的位置和文檔總高度來實現(xiàn)該功能,這篇文章主要給大家介紹了關(guān)于JS實現(xiàn)滾動觸底的思路與代碼,文中還附PC端滾動分頁加載數(shù)據(jù),需要的朋友可以參考下2024-06-06

