摘要:歷史裝飾器這個(gè)概念三年多前被首次提出。在版本年中發(fā)布了對(duì)裝飾器的支持以及許多特性。有不同的安全級(jí)別需要考慮裝飾器不應(yīng)該意外泄漏私有名稱。你可以測(cè)試裝飾器的新語(yǔ)法,并向提案的作者們提出反饋意見。
原文地址:https://babeljs.io/blog/2018/...
原文作者:Nicolò Ribaudo
Babel 7.1.0最終支持新的裝飾器提案,可以通過@babel/plugin-proposal-decorators插件使用。
歷史
裝飾器這個(gè)概念三年多前被Yehuda Katz首次提出。TypeScript在版本1.5(2015年)中發(fā)布了對(duì)裝飾器的支持以及許多ES6特性。很多主流框架,像Angular和MobX,為了提高開發(fā)體驗(yàn)也開始使用裝飾器。這些使裝飾器變得很流行,并且給了社區(qū)一種很穩(wěn)定的錯(cuò)覺。
Babel在版本5里面首次實(shí)現(xiàn)了裝飾器,但在版本6的時(shí)候移除了,因?yàn)樘岚冈诓粩嗟淖兓ogan Smyth創(chuàng)建了一個(gè)非官方的插件(babel-plugin-transform-decorators-legacy)來代替Babel5里面的裝飾器,在第一個(gè)Babel7 alpha版本發(fā)布的時(shí)候的時(shí)候,它被移到了Babel官方的存儲(chǔ)庫(kù)。這個(gè)插件還是使用老版本的插件語(yǔ)法,因?yàn)檫€不清楚新的提案會(huì)變成什么樣。
從那個(gè)時(shí)候開始,Daniel Ehrenberg和Brain Terlson和Yehuda Katz一起成為了提案的作者,提案幾乎完全被重寫了。并非所有的事情都已經(jīng)確定,而且目前也沒有合規(guī)實(shí)施的方案。
Babel7.0.0為@babel/plugin-proposal-decorators插件介紹了一個(gè)新的標(biāo)志:配置項(xiàng)legacy的唯一有效值為true。為了從提案的第一階段平滑過渡到當(dāng)前版本,需要有這種重大的改變。
在Babel7.1.0,我們引入了對(duì)這個(gè)新提案的支持,并且在使用@babel/plugin-proposal-decorators插件的時(shí)候會(huì)默認(rèn)啟用。如果我們不在Babel7.0.0里引入配置項(xiàng)legacy為true的話,在默認(rèn)情況下就不可能使用正確的語(yǔ)義(也就意味著配置項(xiàng)legacy的值為false)
新的提案還支持私有字段和方法上的裝飾器。我們還沒有在Babel中實(shí)現(xiàn)這個(gè)功能(對(duì)于每個(gè)類而言,你可以使用裝飾器或者私有元素),但很快就會(huì)實(shí)現(xiàn)的。
新的提案的改變點(diǎn)
盡管新的提案看上去跟舊的很相似,但還是有一些重要的不同點(diǎn)。
語(yǔ)法
舊的提案允許任何有效的左側(cè)表達(dá)式(文字、函數(shù)和類表達(dá)式,new表達(dá)式和函數(shù)調(diào)用,簡(jiǎn)單和計(jì)算屬性訪問)作為裝飾器的主體:
class MyClass { @getDecorators().methods[name] foo() {} @decorator [bar]() {} }
這個(gè)語(yǔ)法有一個(gè)問題:[...]這個(gè)符號(hào)在裝飾器里進(jìn)行屬性訪問以及定義計(jì)算屬性名字的時(shí)候也會(huì)被用到。為了消除這個(gè)歧義,新的提案值允許用點(diǎn)符號(hào)來進(jìn)行屬性訪問(foo.bar),也可以在最后加上一個(gè)括號(hào)(foo.bar())。如果你需要更多復(fù)雜的表達(dá)式,你可以用括號(hào)括起來:
class MyClass{ @decorator @dec(arg1, arg2) @namespace.decorator @(complex ? dec1 : dec2) method() {} }
對(duì)象裝飾器
舊版本的提案允許出現(xiàn)除了類和類元素裝飾器之外的對(duì)象成員裝飾器:
const myObj = { @dec1 foo: 3, @dec2 bar() {}, };
由于跟當(dāng)前對(duì)象的一些表達(dá)語(yǔ)法的不兼容性,在提案中被移除了。如果你在你的代碼中使用了對(duì)象成員裝飾器,繼續(xù)關(guān)注因?yàn)樗鼈兛赡軙?huì)在后續(xù)提案中被引入。
函數(shù)裝飾器的參數(shù)
新提案引入的第三個(gè)重要變化是關(guān)于傳遞給裝飾器函數(shù)的參數(shù)。
在第一版提案中,類元素裝飾器接受一個(gè)目標(biāo)類(對(duì)象),一個(gè)變量,和一個(gè)屬性描述符-類似于傳遞給Object.defineProperty的參數(shù)。類裝飾器將目標(biāo)構(gòu)造函數(shù)作為唯一的參數(shù)。
新的提案的裝飾器更強(qiáng)大一些:元素裝飾器接受一個(gè)對(duì)象,該對(duì)象除了更改屬性操作符之外,還允許更改變量值,位置(static、prototype或者own)以及元素的種類(field或method)。他們還可以創(chuàng)建其他的屬性并定義運(yùn)行在類裝飾器里的函數(shù)。
類裝飾器接受一個(gè)包含每個(gè)類元素的描述符的對(duì)象,從而保證可以在創(chuàng)建類之前修改它們。
升級(jí)
由于這些不兼容性,不能在現(xiàn)有的裝飾器上使用新的提案:這會(huì)讓升級(jí)特別慢,因?yàn)楝F(xiàn)有的庫(kù)(MobX,Angular等)不能再?zèng)]有引入重大改變的情況下進(jìn)行升級(jí)。為了解決這個(gè)問題,我們已經(jīng)發(fā)布了一個(gè)實(shí)用程序包,它將裝飾器包裝在你的代碼里。運(yùn)行這個(gè)之后,你可以安全地修改你的Babel配置以使用新的提案。
你可以使用下面這行代碼去升級(jí)文件:
npx wrap-legacy-decorators src/file-with-decorators.js --decorators-before-export --write
如果你的代碼只在Node中運(yùn)行,或者你用Webpack或Rollup打包你的代碼,你可以使用外部依賴來避免在每個(gè)文件中都注入包裝函數(shù):
npm install --save decorators-compat npx wrap-legacy-decorators src/file-with-decorators.js --decorators-before-export --external-helpers --write
開放問題
并非所有的事情都已經(jīng)確定:裝飾器是一個(gè)非常大的功能,而且要以最好的方式定義它們是非常復(fù)雜的。
導(dǎo)出類的裝飾器應(yīng)該放在哪里
這個(gè)問題在裝飾器的提案里反復(fù)出現(xiàn):裝飾器應(yīng)該在export這個(gè)關(guān)鍵字的前面還是后面?
export @decorator class MyClass {} // or @decorator export class MyClass {}
根本問題是export關(guān)鍵字是否是類聲明的一部分,還是只是一個(gè)“包裝器”。如果是前一種情況,它應(yīng)該放在裝飾器的后面,因?yàn)檠b飾器出現(xiàn)在聲明的開頭;在第二種情況下,它應(yīng)該在裝飾器前面,因?yàn)檠b飾器是類裝飾器的一部分。
如何讓裝飾器和私有元素安全地互動(dòng)?
裝飾器引起了重要的安全問題:如果可以裝飾私有元素,那么私有名稱(也可以稱為私有屬性的變量名)可能會(huì)被泄漏。有不同的安全級(jí)別需要考慮:
1) 裝飾器不應(yīng)該意外泄漏私有名稱。惡意代碼不應(yīng)該以任何方式從其他裝飾器中“竊取”私有名稱。
2) 只有直接應(yīng)用于私有元素的裝飾器才能被視為可信任:類裝飾器應(yīng)該無法讀寫私有元素?
3) 硬私有(類字段提案的目標(biāo)之一)意味著私有元素應(yīng)該只能有類的內(nèi)部訪問:任何裝飾器是否可以訪問私有名稱?裝飾器只能裝飾公共元素么?
這些問題需要進(jìn)一步討論才能解決,這也是Babel的用武之地。
Babel的作用
隨著What"s Happening With the Pipeline(|>) Proposal?這篇文章里的趨勢(shì),隨著Babel7的發(fā)布,我們開始利用我們?cè)贘S生態(tài)系統(tǒng)中的位置,通過讓開發(fā)人員測(cè)試和反饋有關(guān)提案的不同版本的體驗(yàn)來幫助提案的提出者們。
由于這個(gè)原因,在@babel/plugin-proposal-decorators更新的同時(shí),我們也引入了一個(gè)新的屬性:decoratorsBeforeExport,允許用戶同時(shí)使用export @decorator class C {}和 @decorator export default class。
我們也將引入一個(gè)屬性來自定義私有屬性裝飾器的隱私約束。在TC39人員做出決定之前,這些屬性是必需的,這樣我們可以讓默認(rèn)行為成為最終提案知道的內(nèi)容。
如果你直接使用我們的解析器(@babel/parse,以前的babylon),你已經(jīng)可以在版本7.0.0里使用decoratorsBeforeExport屬性:
const ast = babylon.parse(code, { plugins: [ ["decorators", { decoratorsBeforeExport: true }] ] })
用法
Babel用法:
shell版本:
npm install @babel/plugin-proposal-decorators --save-dev
JSON版本:
{ "plugins": ["@babel/plugin-proposal-decorators", {"decoratorsBeforeExport": true }] }
查看@babel/plugin-proposal-decorators文檔了解更多屬性。
你的作用
作為JavaScript的開發(fā)人員,你可以幫助概述該語(yǔ)言的未來。你可以測(cè)試裝飾器的新語(yǔ)法,并向提案的作者們提出反饋意見。我們需要知道你在現(xiàn)實(shí)生活的項(xiàng)目中是怎么使用它們的。你也可以通過閱讀問題中的討論和proposal"s repository中的筆記中發(fā)現(xiàn)為什么要這樣設(shè)計(jì)。
如果你想要立即嘗試裝飾器,你可以在我們的repl里使用不同的預(yù)設(shè)屬性值。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/102159.html
摘要:最大的好處是對(duì)用戶而言透明,可惜原因如前所述,此方案已否定。鑒于已經(jīng)在正式提案中,倘若討論持續(xù)僵持不下,不出意外將會(huì)隨著時(shí)間推移而正式成為規(guī)范。月碰頭會(huì)的與會(huì)者紛紛表示這次會(huì)議進(jìn)展令人愉快,會(huì)議內(nèi)容匯總在此,以及一些補(bǔ)充。 說明:本文發(fā)布之后,此問題的推進(jìn)峰回路轉(zhuǎn),不停有新內(nèi)容。文末新增一節(jié) Updates,跟進(jìn)本文發(fā)布之后的 ES Module 標(biāo)準(zhǔn)化進(jìn)展情況。 瀏覽器大戰(zhàn)多年了熱度...
摘要:距離上一篇走馬觀花已經(jīng)快兩年時(shí)間了,上個(gè)月底正式發(fā)布,再寫一篇姊妹篇,介紹新特性。會(huì)議的每一項(xiàng)決議必須大部分人贊同,并且沒有人強(qiáng)烈反對(duì)才可以通過。已經(jīng)準(zhǔn)備就緒,該特性會(huì)出現(xiàn)在年度發(fā)布的規(guī)范之中。 距離上一篇《ES6 走馬觀花》已經(jīng)快兩年時(shí)間了,上個(gè)月底 ES8 正式發(fā)布,再寫一篇姊妹篇,介紹 ES8 新特性。 什么是 ES8 ES8 是 ECMA-262 標(biāo)準(zhǔn)第 8 版的簡(jiǎn)稱,從 ES...
摘要:他們的計(jì)劃是,使用微軟開發(fā)者們所習(xí)慣的其他語(yǔ)言的開發(fā)工具所支持的靜態(tài)類型,得到更好的代碼。在微軟內(nèi)部,被和以及團(tuán)隊(duì)所使用,而且它被系的等公司使用。標(biāo)準(zhǔn)的編輯,同時(shí)也是微軟項(xiàng)目高級(jí)經(jīng)理的也同意。 本文轉(zhuǎn)載自:眾成翻譯譯者:文藺鏈接:http://www.zcfy.cc/article/895原文:http://thenewstack.io/javascript-transpilers-n...
摘要:提交內(nèi)容可以是一個(gè)提議想法初步描述該階段是對(duì)所提交新特性的正式建議。在這個(gè)階段需具備以下條件指定一名成員作為審閱通過有實(shí)現(xiàn)的或者初步編寫標(biāo)準(zhǔn),包括問題描述解決方案示例語(yǔ)法語(yǔ)義關(guān)鍵的算法及抽象實(shí)現(xiàn)在的復(fù)雜度等該階段是會(huì)出現(xiàn)標(biāo)準(zhǔn)中的第一個(gè)版本。 ECMAScript 與 JavaScript ECMAScript 是一套腳本語(yǔ)言的規(guī)范,內(nèi)部編號(hào) ECMA-262 該規(guī)范由 Ecma(Eu...
閱讀 728·2021-08-17 10:11
閱讀 1594·2019-08-30 11:15
閱讀 1017·2019-08-26 13:54
閱讀 3502·2019-08-26 11:47
閱讀 1212·2019-08-26 10:20
閱讀 2816·2019-08-23 18:35
閱讀 1213·2019-08-23 17:52
閱讀 1297·2019-08-23 16:19