我們擅長(cháng)商業(yè)策略與用戶(hù)體驗的完美結合。
歡迎瀏覽我們的案例。
從 1995 年開(kāi)始,本文作者 Dr.Axel Rauschmayer 就專(zhuān)門(mén)從事 JavaScript 和 Web 開(kāi)發(fā),已經(jīng)有 30 多年了。2010 年,他獲得慕尼黑大學(xué)信息學(xué)博士學(xué)位。自 2011 年以來(lái),他一直在 2ality.com 寫(xiě)博客,并寫(xiě)了幾本關(guān)于 JavaScript 的書(shū),比如《JavaScript for impatient programmers》、《Deep JavaScript: Theory and techniques》等。今天這篇文章就來(lái)自于他的博客,介紹了在 JavaScript 命名沖突時(shí),現有代碼如何強制對提議的功能進(jìn)行重命名。
不斷發(fā)展的 JavaScript:不要破壞 web!
JavaScript 的一個(gè)發(fā)展核心原則就是"不要破壞 Web":在將新特性添加到語(yǔ)言中后,所有現有代碼都必須能夠繼續運行。
這樣有一個(gè)壞處,就是不能從語(yǔ)言中刪除現有的 quirks。但這樣做益處多多,比如舊的代碼可以繼續運行,而且升級到新的 ECMAScript 版本很簡(jiǎn)便等等。
在為新特征(如方法名稱(chēng))選擇名稱(chēng)時(shí),需要進(jìn)行一個(gè)重要的測試,即在瀏覽器的 nightly 版本(早期預發(fā)布版本)中添加該特征,并檢查是否有任何網(wǎng)站出現錯誤。
接下來(lái)將介紹過(guò)去案例中的的四個(gè)沖突源,當產(chǎn)生這四種沖突時(shí),就必須重命名特征。
沖突源1:向內置原型添加方法
在 JavaScript 中,我們可以通過(guò)改變其原型來(lái)為內置值添加方法:
神奇的是,語(yǔ)言可以通過(guò)這種方式改變。這種運行時(shí)的修改被稱(chēng)為猴子補丁(monkey patch)。
什么是猴子補丁?
如果我們給內置原型添加方法,我們就是在運行時(shí)修改一個(gè)軟件系統。這樣的修改被稱(chēng)為猴子補丁。簡(jiǎn)單來(lái)說(shuō),對其含義有兩種可能的解釋。
這個(gè)叫法起源于 Zope 框架,人們在修正 Zope 的 Bug 的時(shí)候經(jīng)常在程序后面追加更新部分,這些被稱(chēng)作是“雜牌軍補丁(guerilla patch)”,后來(lái) guerilla 就漸漸的寫(xiě)成了 gorllia ((猩猩),再后來(lái)就寫(xiě)了 monkey (猴子),所以猴子補丁的叫法是這么莫名其妙的得來(lái)的。
另一種說(shuō)法是,它指的是搞亂(monkeying about)代碼。
反對改變內置原型的原因
對任何類(lèi)型的全局命名,都會(huì )存在名稱(chēng)沖突的風(fēng)險。如果有解決沖突的機制,就能規避風(fēng)險。例如:
全局模塊是通過(guò)裸模塊指定器或 URLs 來(lái)識別的。前者之間的名稱(chēng)沖突可以通過(guò) npm 注冊表來(lái)解決。后者之間的名稱(chēng)沖突可以通過(guò)域名注冊處來(lái)解決。
可以通過(guò)將符號添加到 JavaScript 中,以避免方法之間的名稱(chēng)沖突。例如,任何對象都可以通過(guò)添加一個(gè)鍵為 .NET 的方法而成為可迭代的。由于每個(gè)符號都是唯一的,所以這個(gè)鍵永遠不會(huì )與任何其他屬性鍵 .Symbol.iterator 發(fā)生沖突。
然而,帶有字符串鍵的方法會(huì )導致名稱(chēng)沖突:
不同的庫可能會(huì )對他們添加到 .Array.prototype 的方法使用相同的名字。
如果一個(gè)名字已經(jīng)被某個(gè)庫使用了,那么這個(gè)名稱(chēng)就不能用于命名 JavaScript 標準庫的一個(gè)新特性。
具有諷刺意味的是,謹慎地添加一個(gè)方法可能會(huì )適得其反:
我們會(huì )檢查一個(gè)方法是否已經(jīng)存在。如果沒(méi)有,我們就添加它。
如果我們要實(shí)現一個(gè) polyfill(模擬原生 Web 平臺功能),將新的 JavaScript 方法添加到不支持它的引擎中,那么這個(gè)技術(shù)就能發(fā)揮作用。(順便說(shuō)一下,這是修改內置原型的一個(gè)合法用例。也許是唯一的一個(gè))。
然而,如果我們對一個(gè)普通庫的方法使用這種技術(shù),然后 JavaScript 獲取具有相同名稱(chēng)的方法,那么這兩種實(shí)現的工作方式就不一樣了,并且使用庫方法的所有代碼在使用內置方法時(shí)都會(huì )中斷。
必須更改名稱(chēng)的原型方法示例
ES6 的方法最初是與 JavaScript 框架 MooTools.String.prototype.includes () .contains ()全局添加的方法相沖突。
ES2016 的方法最初是與 MooTools.Array.prototype.includes () .contains ()添加的方法相沖突。
ES2019 的方法最初是和 MooTools.Array.prototype.flat () .flatten ()相沖突。
修改內置原型并不總是糟糕的
你可能會(huì )對 MooTools 的創(chuàng )建者的粗心大意感到疑惑。但是,向內置原型添加方法并不總是糟糕的。在 ES3(1999 年 12 月)和 ES5(2009 年 12 月)之間,JavaScript 是一種停滯不前的語(yǔ)言。MooTools 和 Prototype 等框架改進(jìn)了它。這些方法的缺點(diǎn)只有在 JavaScript 的標準庫再次增加之后才會(huì )凸顯出來(lái)。
沖突源2:檢查一個(gè)屬性的存在
ES2022 的方法最初是 .NET 的。因為以下庫檢查屬性以確定對象是否是一個(gè) HTML 集合(而不是一個(gè)數組),所以它必須被重新命名:Magic360、YUI 2、YUI 3.Array.prototype.at () .item () .item
沖突源3:檢查全局變量是否存在
自 ES2020 以來(lái),我們可以通過(guò) globalThis 訪(fǎng)問(wèn)全局對象。Node.js 一直使用該名稱(chēng)來(lái)實(shí)現此目的。最初的計劃是為所有平臺標準化該名稱(chēng) .global
然而,以下模式經(jīng)常被用來(lái)確定當前平臺:
如果瀏覽器也有一個(gè)名為 .global 的全局變量,這種模式(以及類(lèi)似的模式)就會(huì )失效。因此,標準化的名稱(chēng)被改為 .globalglobalThis。
沖突源4:通過(guò)創(chuàng )建局部變量 with 語(yǔ)句
JavaScript 的聲明 with 語(yǔ)句
長(cháng)期以來(lái),人們一直不鼓勵使用 JavaScript 的 with 語(yǔ)句,甚至在 ES5 中引入的嚴格模式中也被定為非法。在其他地方,嚴格模式在 ECMAScript 模塊中是活躍的。
該語(yǔ)句將一個(gè)對象的屬性變成局部變量:with
由 with 語(yǔ)句引起的沖突
框架 Ext.js 使用的代碼與下面的片段有些相似點(diǎn):
當 ES6 方法被添加到 JavaScript 中時(shí),如果用 Array(B行)來(lái)調用它,它就會(huì )失效。該語(yǔ)句將 Array 的所有屬性變成了局部變量。其中一個(gè)是繼承的屬性。因此,A行中的語(yǔ)句已記錄,不再是參數
Array.prototype.values () myFunc () withvalues.valuesArray.prototype.valuesvalue
Unscopables:防止 with 導致的沖突
公共符號Symbol.unscopables 允許對象隱藏語(yǔ)句中的某些屬性。它只在標準庫中使用一次,對于 Array.prototype:with
結論
以上提出了 JavaScript 結構與現有代碼發(fā)生名稱(chēng)沖突的四種方式:
向內置原型添加方法
檢查屬性是否存在
檢查全局變量是否存在
創(chuàng )建局部變量 with
沖突的某些來(lái)源很難預測,但存在以下一些一般規則:
不要更改全局數據。
避免檢查是否存在全局數據。
請注意,內置值將來(lái)可能會(huì )獲得其他屬性(自己的或繼承的屬性)。
對于庫來(lái)說(shuō),為 JavaScript 值提供功能的最安全方法是通過(guò)函數。如果 JavaScript 得到一個(gè) pipe operator,我們也可以像方法一樣使用它們。
?。?a href="http://www.wxlp666.cn/wechat/">邯鄲微信平臺)
小米應用商店發(fā)布消息稱(chēng) 持續開(kāi)展“APP 侵害用戶(hù)權益治理”系列行動(dòng) 11:37:04
騰訊云與CSIG成立政企業(yè)務(wù)線(xiàn) 加速數字技術(shù)在實(shí)體經(jīng)濟中的落地和應用 11:34:49
樂(lè )視回應還有400多人 期待新的朋友加入 11:29:25
亞馬遜表示 公司正在將其智能購物車(chē)擴展到馬薩諸塞州的一家全食店 10:18:04
三星在元宇宙平臺推出游戲 玩家可收集原材料制作三星產(chǎn)品 09:57:29
特斯拉加州San Mateo裁減229名員工 永久關(guān)閉該地區分公司 09:53:13