原文在 https://areknawo.com/5-interesting-and-not-necessarily-useful-javascript-tricks/
做者是 Areknawojavascript
前一段時間,我建立了一個標題爲「7個可愛的Web開發技巧」的帖子。在這裏,我描述了一些有趣的技巧,您可使用3種主要的Web技術之一來實現這些技巧-HTML,CSS和JavaScript。並且,我必須認可-大家彷佛都喜歡它!所以,續集來了!java
此次,爲了更加一致,我決定只專一於JavaScript。它多是三者中最有趣,用途最普遍的,所以有不少事情要討論。咱們將介紹5種JavaScript技巧,這些技巧在上一篇文章中沒有提到。但願您會發現它們頗有趣!node
在進入列表以前,請快速注意一下。我看到了對上一篇文章的一些回覆,並想清除一些內容。我知道並非該列表或上一個列表中的全部條目可能都是真正有用的或推薦的作法,但這不是個人目標。用「技巧」一詞個人意思就是-有趣的或僅出於此目的而值得了解的「技巧」。有用只是一種獎勵。若是它打算100%有用,那麼我將其稱爲「提示」。我但願你明白。如今,讓咱們轉到列表!git
從不太「極端」的技巧開始,咱們獲得了switch聲明。它的大多數用例都歸結爲字符串或數字值匹配。可是,您知道您也能夠將其與一些更復雜的布爾值一塊兒使用嗎?看一看。web
const useSwitch = value => { let message = ""; switch (true) { case value < 0: message = "lesser than 0"; break; case value === 0: message = "0"; break; case value % 1 !== 0: message = "a float"; break; case value > 0 && value <= 9: message = "higher than 0 and is 1 digit long"; break; case value >= 10 && value <= 99: message = "2 digits long"; break; case value >= 100: message = "big"; break; } console.log(`The value is ${message}`); }; useSwitch(24); // The value is 2 digits long.
而不是爲switch語句提供實際變量,咱們只是傳遞true。這樣,咱們實質上使它成爲一個大if-else選擇。是否應使用它僅取決於您的我的喜愛或所遵循的代碼準則。若是您發現它比if-else鏈條更具可讀性,那就去買它。兩種解決方案的性能大體相同。瀏覽器
接下來,咱們有一些自己並非真正的技巧。對函數進行字符串化是您很長時間以來最瞭解的功能。相反,我想讓您知道這種功能的一些有趣用例。緩存
const func = () => { console.log("This is a function"); } const stringifiedFunc = `${func}`; /* `() => { console.log("This is a function"); }` */
首先快速看一下語法方面。您應該知道,當您將任何JS類型的值轉換爲字符串時,.toString()都會調用一個特殊方法。您可使用此事實來實現此方法的本身的版本,並以不一樣的方式處理將JS值轉換爲字符串的狀況。能夠單獨考慮這是一個技巧。;)不管如何,我想說的是,您能夠將值(包括函數)轉換爲帶有ES6模板文字的字符串(如示例中所示),方法是將它們與空字符串文字("")串聯,或者僅經過調用該.toString()方法直接。less
如今,讓咱們回到函數。我想指出,您不能依賴結果字符串來包含函數編寫時的全部代碼。例如,它僅來自ES2019(當前爲ECMAScript標準的最新版本),其.toString()目的是在結果字符串中包含函數體內的全部註釋和空格。您能夠我以前的一篇文章中閱讀有關ES2019功能的更多信息。不管如何,考慮到全部這些,對函數進行字符串化怎麼可能甚至有用?ecmascript
不要搜索太多,我想引用一個我最近的副項目中使用的巧妙技巧。想象一下,能夠經過調用一個函數來建立一種節點。該函數將另外一個函數用做參數,而後運行該參數以配置新節點。對於包含相同語句的函數,結果節點相同。函數
可悲的是,建立新節點是一個緩慢的過程(尤爲是考慮大量節點時),而且您至少要最小化要建立的節點數。爲此,您能夠例如建立一個「緩存」對象,在該對象中經過其字符串化的config函數存儲全部已建立的節點,以防止進行任何重複調用-有趣嗎?
固然,即便是很小的空格或註釋,基於字符串的基於函數的ID也會被認爲是不一樣的。您能夠經過一些附加的字符串處理來解決它,可是這會忽略咱們試圖實現的全部性能改進。
可是,只要配置功能容許,您就不能容忍對象鍵。您能夠經過簡單地對字符串化函數進行哈希處理來輕鬆解決此問題-它不會在性能上花費不少。
// ... const hash = value => { let hashed = 0; for (let i = 0; i < value.length; i += 1) { hashed = (hashed << 5) - hashed + value.charCodeAt(i); hashed |= 0; } return `${hashed}`; }; const hashedFunc = hash(stringifiedFunc); // "-1627423388"
我知道我剛剛描述的內容彷佛過於具體,沒法應用於更通常的用例。固然能夠,可是我只是想給您一個現實的例子,說明這種技巧給您帶來的可能性。
可調用對象,具備屬性的函數或任何您想調用的對象都是一個很是簡單的想法,能夠很好地演示JavaScript的多功能性。
const func = () => { // ... }; func.prop = "value"; console.log(func.prop); // "value"
上面的代碼段對您來講彷佛沒有什麼特別。您能夠在幾乎任何JS對象保存本身的屬性,除非它與使用說明,不然.freeze(),.seal()或.preventExtensions()方法。上面的函數如今既能夠用做常規函數,也能夠用做包含某種數據的對象。
上面的代碼片斷看起來並不完美。將屬性分配給給定的函數可能會隨着時間的推移而感到重複和混亂。讓咱們嘗試改變它!
const func = Object.assign(() => { // ... }, { prop: "value" }); console.log(func.prop); // "value"
如今,咱們正在使用該Object.assign()方法來使咱們的代碼看起來更好。固然,此方法僅在與ES6兼容的環境中(或與Transpiler一塊兒使用)可用,可是,因爲咱們還在此處使用箭頭功能,所以我認爲這是理所固然的。
假設咱們有一個包含許多字段和方法的類。您能夠想象本身在這種狀況下,不是嗎?若是在給定的時刻僅須要全部類屬性和方法的一小部分怎麼辦?也許您可使用ES6 解構分配來使代碼看起來更好?可悲的是,這並不容易-看一下。
class Example { method() { console.log(this); } } const instance = new Example(); const { method } = instance; method(); // undefined
如您所見,在提取方法以後,將value this更改成undefined。這是預期的行爲-的價值this是運行時綁定和方式和地點,你的函數被調用在肯定我在討論這個。我之前的帖子。
有一個辦法解決,可是- .bind()。
class Example { constructor() { this.method = this.method.bind(this); } method() { console.log(this); } } const instance = new Example(); const { method } = instance; method(); // Example {}
如今,咱們的代碼能夠按預期工做,儘管它須要添加類構造函數,並所以增長了幾行代碼。咱們能夠縮短期嗎?
class Example { method = () => { console.log(this); } } // ...
看來咱們已經作到了!在您的類中具備按詞法綁定的方法的簡便快捷方法。上面的語法可最新的常綠瀏覽器中使用,並在必要時能夠進行編譯,請盡情使用!
此列表上的最後一個條目也與類相關。您可能據說過從構造函數返回自定義值的可能性。這不是很受歡迎或推薦的作法,可是它可使您得到一些有趣的結果。還記得我以前提出的緩存節點的先前示例嗎?讓咱們以此爲基礎!
// ... const cache = {}; class Node { constructor(config) { const id = hash(`${config}`); if (cache[id]) { return cache[id]; } else { cache[id] = this; config(); } } } const node = new Node(() => {}); const nodeReference = new Node(() => {}); const secondNode = new Node(() => { console.log("Hello"); }); console.log(node === nodeReference, node === secondNode); // true, false
咱們的節點如今具備類的形式,而且像之前同樣,可使用字符串化和哈希配置函數對其進行緩存。看到全部片斷融合在一塊兒真是太好了!
因此,僅此而已。我知道這不是您見過的最長的一個,可是,嘿,至少我設法使您感興趣,對嗎?不管如何,請在評論部分讓我知道您不知道上述哪些技巧?另外,您還能夠在這種文章中分享您的意見,若是您想查看更多文章,請與咱們分享。;)
最後,我很快宣佈了一個消息-我正在創建本身的Reddit社區!它被稱爲r / Areknawo,我但願它成爲這個博客(像您這樣的博客)的讀者的地方,以討論各類帖子,博客相關的內容以及其餘與Web開發,設計或技術相關的內容。若是您想表達您的支持,只需去那裏,成爲會員,而後趕忙離開。;)
所以,若是您喜歡此博客,請考慮在Twitter,Facebook或Reddit上關注我,以獲取最新內容。若是您喜歡時事通信,則在帖子下方可使用一種表格來註冊。與往常同樣,感謝您閱讀本文,並祝您愉快!
機翻搬運沒有公衆號須要你關注