文章插圖

文章插圖
JavaScript 已經存在了相當長的一段時間(大約 26 年) , 在這段時間里 , 該語言已經有了很大的發展 。
這種演變大多是有目的 , 特別是在最新的迭代中 , 開發者社區已經設法影響了其中的一些變化 , 使 JavaScript 成為一種非常靈活和好用的語言 。
然而 , 在這些年的演變過程中 , 可以說仍有一些殘余的過時功能 , 這些功能還沒有被拿掉 , 但確實沒有任何用途(或者更確切地說 , 在原本的用途方面效率不高) 。
以下三個 JavaScript 特性 , 即使它們在運行時仍然可用 , 但你應避免去使用它們 。
void 操作符
你可能在某一時刻看到過 void 操作符的存在 。在過去 , 每當你點擊一個鏈接 , 而這個鏈接將觸發一個 JavaScript 函數時 , 你會添加 href=”javascript:void(0)” 以確保默認行為(即頁面跳轉)不會觸發 。
但這究竟是什么意思呢?
void 操作符是一種在 JavaScript 中生成 undefined 值的方法 。沒錯 , 它能接受任何表達式 , 并且每次都返回 undefined 。
我知道你在想什么:為什么不直接使用已經存在的 undefined 關鍵字呢?嗯 , 正如你看到的 , 在 ECMAScript 5 之前 , undefined 關鍵字并不是一個常量值 。是的 , 你可以定義 undefined , 如果你再想一想 , 這不就是我們曾經想做的事情嗎?
當然 , 這樣做是沒有意義的 , 這就是為什么最終它被重新定義為一個常量值 , 且不可更改 。然而 , 因為早前你是可以改變它的 , 所以 void 會允許你訪問 undefined , 即使這個常量不再起作用 。
事實上 , 一個很好的方法是通過創建你自己的 IIFEs 來重新定義只屬于你的命名空間的常量 , 避免與第三方庫的任何問題 , 其中一個參數確實是 undefined , 像這樣:
(function (window, undefined) {// 你這里的邏輯 , 可以把 undefined 當作預期})(window, void(0))當然 , 今天的 void 操作符仍然有它的用途 , 但它是非必要的 。例如 , 在現在的 JavaScript 中 , 最好的用例是幫助避免單行箭頭函數的非預期返回 。你可能知道 , 一個單行箭頭函數將返回該行的結果 , 即使你沒有顯式使用 return 語句 。
const double = x => x * 2; // 返回 X 乘以 2 的結果const callAfunction = () => myFunction(); // 返回 myFunction 所返回的結果 , 即使我不想這樣做這兩個函數都會返回一些東西 。顯然 , 對于 double 函數來說 , 你希望它返回一個值 , 但另一個可能不是 , 你可能只是想用它調用另一個函數(即 myFunction()) , 但你對其結果值不感興趣 。因此你可以這樣做:const callAfunction = () => void myFunction(); // 返回 myFunction 所返回的結果 , 即使我不想這樣做而這將立即覆蓋返回值 , 并確保你的調用值返回 undefined 。對我來說 , 這種行為提供了一個最小的好處 , 使 void 在這個時代的 JavaScript 中毫無用處 。
我建議你避免使用它 , 讓它保持一個廢棄的狀態 。
With 語句
這個是 JavaScript 自帶的結構之一 , 但你可能從未聽說過它 , 因為它并沒有被真正推廣 。事實上 , 即使是 MDN 官方文檔也不鼓勵你使用它 , 因為它可能導致非常混亂的代碼 。
with 語句允許擴展給定語句的作用域鏈 。換句話說 , 它允許你將一個表達式注入到給定語句的作用域 , 理想情況下 , 可以簡化所述語句 。
下面是一個示例 , 這樣你就會明白我想說什么:
function greet(user) {with(user) {console.log(`Hello there ${name}, how are you and your ${kids.length} kids today?`)}}greet({name: "Fernando",kids: ["Brian", "Andrew"]})注意 greet 函數中 with 語句的魔力 。這是一個基本的示例 , 表明了表達式的 happy path 。但是 , 讓我們看另一個情況 , 事情變得有點復雜:function greet(user, message) {with(user) {console.log(`Hey ${name}, here is a message for you: ${message}`)}}// happy pathgreet({name: "Fernando"}, "You got 2 emails")// kinda sad pathgreet({name: "Fernando",message: "Unrelated message"}, "you got email")你認為這種執行方式的輸出結果會是什么?Hey Fernando, here is a message for you: You got 2 emailsHey Fernando, here is a message for you: Unrelated message由于你在傳入的對象中添加了一個同名屬性 , 你無意間覆蓋了函數的第二個參數 。我想補充的是 , 這完全是正常的 , 因為人們永遠不會期望兩者處于同一個作用域級別 。然而 , 多虧了 with , 我們把這兩個作用域都混在了一起 , 但結果并不理想 。這都是為了說明要避免使用 with , 雖然它可能看起來是節省代碼量的好方法 , 但你的代碼很快會變得非常復雜 , 這會對別人(或兩周后的你)去理解你的代碼造成心智負擔 。
Labels 標簽
如果你學習編程足夠早(像我一樣) , 你就經歷過其他語言(如 C 語言)中對 go-to 語句的憎恨 。那太糟糕了 , 那是一個在當年很有意義的功能 , 但最終隨著同一問題的更新的解決方案 , 這種功能變得如此過時和糟糕 , 以至于變成了一種反模式 。
因此 JavaScript 不得不去實現它 。
Go-to 語句是一種方式 , 讓你在代碼的任何地方放置一個標記 , 然后從其他地方跳到那里 。你可以跳到一個函數的中間 , 或者跳到一個 IF 語句里面 , 它就像一個神奇的入口 , 可以跳到你代碼中的任何地方 。我相信你可以看到這可能是一個問題 , 它的力量太大 , 靈活性太強 , 我們當然會錯過使用它的機會 。
然而 , JavaScript 實現了一個類似的 , 但不完全相同的結構:labels 標簽 。
JavaScript 中的標簽語句是一個你放在語句前的標記 , 然后你可以 break 或 continue 。請注意 , 沒有更多的 go-to , 這是一個很好的優勢 。
你可以這樣寫:
label1: {console.log(1)let condition = trueif(condition) {break label1}console.log(2)}console.log("end")而輸出結果將是:1end當然 , 這個例子看起來非常像一個 if..else 語句 。而且你完全可以說 , 它看起來并不那么糟糕 。然而 , 你打破了代碼的正常流程 , 跳過了語句 。如果你就是希望如此 , 那么使用 if..else 帶來的心智負擔會小很多 。當我們把標簽與循環和 continue 語句的相互作用包括在內時 , labels 標簽的問題就變得更明顯了 。
let i, j;loop1:for(i = 0; i < 10; i++) {loop2:for(j = 0; j < 10; j++) {if(j == 3 && i == 2) {continue loop2;}console.log({i, j})if(j % 2 == 0) {continue loop1;}}}你能在頭腦中運行上述代碼并告訴我具體的輸出結果嗎?這并非不可能 , 但要花點時間 。上面的腳本會打印:{ i: 0, j: 0 }{ i: 1, j: 0 }{ i: 2, j: 0 }{ i: 3, j: 0 }{ i: 4, j: 0 }{ i: 5, j: 0 }{ i: 6, j: 0 }{ i: 7, j: 0 }{ i: 8, j: 0 }{ i: 9, j: 0 }從本質上講 , 第二個 if 在 0 的時候評估為 true , 所以 continue 語句影響了外循環 , 導致它移動到下一個索引值 , 這反過來又重置了內循環 , 導致它回到 0 , 同樣的事情不斷發生 , 重復了 10 次 。第一個 if , 如果你想知道的話 , 從來沒有評估為 true , 因為 j 從來沒有達到 0 以外的任何值 。labels 標簽可能是棘手的小家伙 , 即使你能正確地使用它們 , 并且從解釋器的角度來看 , 它們也很有意義 , 但你應該為人類而不是為機器寫代碼 。別人會來讀它(甚至是三周后的你) , 當他們看到標簽的那一刻 , 他們會永遠恨你 。當然 , 他們會花更多的時間來理解你代碼的基本流程 , 但這在目前是次要問題 。
本文總結
請不要誤會 , 我喜歡 JavaScript 這門語言 , 自從 18 年前我開始從事網絡開發工作以來 , 我一直在以不同的方式與它互動 。我見證了這門語言的發展 , 就像一壇好酒 , 隨著時間的推移而變得更好 。然而 , 如果我說這門語言中沒有一些我不喜歡的黑暗角落 , 那是假的 。而這三個功能恰好表明了這一點 。
好消息是 , 在我多年的經驗中 , 我還沒有看到 with 或標簽(Label)被實施并部署到生產中 。這并不是說沒有這樣的情況 , 只是我從未見過 , 這讓我覺得沒有多少代碼審查會讓它們通過 。
【瀏覽器出現javascriptvoid 谷歌提示javascriptvoid怎么辦】你有沒有看到這些功能在現代 JavaScript 中被使用?
- chrome瀏覽器去廣告 谷歌瀏覽器去廣告插件
- 火狐瀏覽器為什么卸載不了 火狐瀏覽器卸載沒反應
- 手機有兼容性的ie瀏覽器 可以兼容ie的手機瀏覽器
- 急救常識 出現意外應該如何急救
- Chrome應用商店打不開 谷歌瀏覽器插件商店打不開
- 遠程時出現內部錯誤是什么意思原因 遠程控制提示出現內部錯誤
- cookie清除了有什么影響 瀏覽器cookie要不要清除
- 遠程控制出現了內部錯誤 遠程訪問出現內部錯誤
- 瀏覽器上無法下載的文件怎么下載 瀏覽器下載文件下載不了
- IE瀏覽器打不開閃退 ie瀏覽器無法打開閃退
