<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          7 個(gè)我最喜歡的 JavaScript 小技巧

          共 6704字,需瀏覽 14分鐘

           ·

          2021-12-19 01:15

          英文 |?https://medium.com/young-coder/7-of-my-favorite-little-javascript-tricks-4f2a1cfe68b4

          翻譯 | 楊小愛(ài)


          O'Reilly 發(fā)布了第三版 JavaScript Cookbook,徹底更新了現(xiàn)代特性和實(shí)踐。我知道這一點(diǎn)是因?yàn)槲液臀业慕艹龊现邅啴?dāng)斯科特一起寫了一些內(nèi)容。
          為了紀(jì)念這個(gè)版本,我決定收集一些我最喜歡的 JavaScript 片段。我不是在談?wù)摯罅康墓δ堋⒖蚣芑蜃詣?dòng)生成的代碼。我也不是在談?wù)撔碌恼Z(yǔ)言創(chuàng)新或生產(chǎn)力技巧。我說(shuō)的是讓生活更美好的智能小代碼。
          將 12 行縮減為 2 行,或者更容易編寫干凈、清晰的代碼。我相信你也有自己的技巧庫(kù)——也許你會(huì)在這個(gè)列表中找到一個(gè)新的想法來(lái)收集。
          1、使用Symbol進(jìn)行枚舉
          您可能熟悉 Symbol,這是一個(gè)不尋常的 JavaScript 對(duì)象,它在生活中只有一個(gè)目的:提供一個(gè)保證全局唯一的隨機(jī)標(biāo)識(shí)符。
          Symbol 在可擴(kuò)展性和元編程方面有一些有趣(且高度專業(yè)化)的應(yīng)用。但它也是創(chuàng)建枚舉的好方法——一組命名常量——JavaScript 語(yǔ)言本身并不支持它。
          這是一個(gè)名為 TrafficLight 的類似枚舉結(jié)構(gòu)的示例:
          // Create three constants to use as an enum const TrafficLight = { Green: Symbol('green'), Red: Symbol('red'), Yellow: Symbol('yellow')}
          // This function uses the enumfunction switchLight(newLight) { if (newLight === TrafficLight.Green) { console.log('Turning light green'); } else if (newLight === TrafficLight.Yellow) { console.log('Get ready to stop'); } else { console.log('Turning light red'); } return newLight;}
          // Let's try it out!let light = TrafficLight.Green;light = switchLight(TrafficLight.Yellow);light = switchLight(TrafficLight.Red);console.log(light); // shows "Symbol('red')"

          在此示例中,每個(gè)枚舉值(例如,TrafficLight.Green)都獲得一個(gè)唯一值。但是你永遠(yuǎn)不會(huì)真正看到那個(gè)值,因?yàn)?Symbol 讓它完全不透明。

          因此,如果您需要在應(yīng)用程序之外序列化此數(shù)據(jù)(例如,將其存儲(chǔ)在磁盤上或通過(guò)網(wǎng)絡(luò)發(fā)送),這可能不是您想要的方法。

          2、在控制臺(tái)中無(wú)痛地測(cè)試代碼

          引導(dǎo) JavaScript 測(cè)試頁(yè)面只需要幾秒鐘。但有時(shí)我想嘗試一個(gè)單獨(dú)的、離散的 JavaScript 函數(shù)。如果我可以在瀏覽器中處理我正在閱讀的文章旁邊的這個(gè)測(cè)試代碼片段,那就更有用了。

          現(xiàn)在,調(diào)用瀏覽器的 DevTools(Windows 上為 F12,macOS 上為 Cmd-Shift-J 或 Cmd-Option-J,具體取決于瀏覽器)并沒(méi)有什么神奇之處。

          在 JavaScript 控制臺(tái)中輸入一些代碼并沒(méi)有什么神奇之處——只需記住在每個(gè)換行符處按 Shift+Enter 并按 Enter 以運(yùn)行完成的代碼。

          但是,如果你想迭代一個(gè)例子(輸入一次,編輯它,重新運(yùn)行它,等等),你需要控制你的代碼執(zhí)行的范圍。

          最好的方法是用大括號(hào) { } 將整個(gè)代碼塊括起來(lái)。這樣你就可以運(yùn)行你的代碼(按 Enter),再次調(diào)用它(按向上箭頭),編輯它,然后重新運(yùn)行它,所有這些都不會(huì)出現(xiàn)惱人的“標(biāo)識(shí)符已經(jīng)聲明”錯(cuò)誤。

          所以不要輸入這個(gè):

          let testValue = 40+12;console.log(testValue);

          你要這樣寫:

          {let testValue = 40+12;console.log(testValue);}

          3、一行深度復(fù)制一個(gè)數(shù)組

          您可能知道現(xiàn)代 JavaScript 的一項(xiàng)重大改進(jìn)是一組函數(shù)式數(shù)組處理方法,它們使您無(wú)需迭代即可處理數(shù)據(jù)。

          這些方法中最強(qiáng)大的方法之一是 Array.map(),它對(duì)每個(gè)元素運(yùn)行一個(gè)函數(shù),并為您提供一個(gè)帶有結(jié)果的新數(shù)組。

          Array.map() 可以做很多技巧,但克隆數(shù)組是更有用的技巧之一。要了解它是如何工作的,請(qǐng)想象您創(chuàng)建了一個(gè)這樣的數(shù)組,其中包含兩個(gè)對(duì)象:

          const objectsOriginal = [{name: 'Sadie', age: 12},                         {name: 'Patrick', age: 18}];

          現(xiàn)在假設(shè)您要復(fù)制這些對(duì)象。這段代碼不是你想要的:

          // All this gets you is two variables pointing to the same arrayconst objectsCopy = objectsOriginal;

          這有點(diǎn)好,但仍然沒(méi)有做你想要的:

          // Creates two array objects, but they share the same people objectsconst objectsCopy = [...objectsOriginal];

          (您可以通過(guò)更改一個(gè)數(shù)組中的對(duì)象并驗(yàn)證它是同一個(gè)更改的對(duì)象來(lái)測(cè)試這一點(diǎn),即使您通過(guò)另一個(gè)數(shù)組訪問(wèn)它也是如此。)

          現(xiàn)在這是一個(gè)使用 Array.map() 的解決方案,它接受每個(gè)元素,擴(kuò)展對(duì)象,然后創(chuàng)建一個(gè)具有相同屬性的重復(fù)對(duì)象:

          const objectsCopy = objectsOriginal.map(element => ({...element}));

          這是該技術(shù)的完整演示如下:

          const objectsOriginal = [{name: 'Sadie', age: 12},                         {name: 'Patrick', age: 18}];
          // Create a new array with copied objectsconst objectsCopy = objectsOriginal.map( element => ({...element}) );
          // Change one of the people objects in objectsCopyobjectsCopy[0].age = 14;
          // Investigate the same object in objectsOriginalconsole.log(objectsOriginal[0].age); // 12

          當(dāng)然,也有一些注意事項(xiàng)。這是一個(gè)單層深拷貝,所以如果你的對(duì)象持有對(duì)其他對(duì)象的引用,它們就不會(huì)被復(fù)制。

          在這種情況下,最好通過(guò)創(chuàng)建自定義類并編寫自定義 clone() 方法來(lái)形式化克隆邏輯。

          然后你可以使用 Array.map() 來(lái)調(diào)用 clone() 方法:

          const objectsCopy = objectsOriginal.map(element => element.clone());

          4、一行清空一個(gè)數(shù)組

          如果我們討論數(shù)組,這里我分享一個(gè)有用的技巧。有時(shí)你想清空一個(gè)數(shù)組對(duì)象而不用一個(gè)新的空白數(shù)組替換它(可能是因?yàn)樗涣硪粋€(gè)對(duì)象引用)。

          在開(kāi)始迭代和調(diào)用 Array.remove() 之前,這里有一個(gè)通過(guò)設(shè)置 length 屬性起作用的快捷方式:

          const numbers = [2, 42, 5, 304, 1, 13];numbers.length = 0;// The array is now empty

          如果您學(xué)習(xí)的是傳統(tǒng)的 OOP 語(yǔ)言,這可能看起來(lái)很奇怪,因?yàn)?Array.length 似乎是一個(gè)應(yīng)該只讀的屬性,并且設(shè)置屬性通常不應(yīng)該觸發(fā)操作(如刪除元素)。但是在 JavaScript 中,有時(shí)您只是做感覺(jué)良好的事情。

          5、給你的對(duì)象一個(gè)合理的字符串表示

          是否厭倦了在使用 console.log() 時(shí),在瀏覽器控制臺(tái)中看到“[object Object]”?您可以通過(guò)為您的對(duì)象提供一個(gè)可觀的 toString() 方法來(lái)輕松覆蓋此行為。下面是一個(gè)例子:

          class Person {   constructor(firstName, lastName) {     this.firstName = firstName;     this.lastName = lastName;  }
          toString() { return `${this.lastName}, ${this.firstName}`; }}
          // Let's use our Person classconst newPerson = new Person('Luke', 'Takei'); const message = 'The name is ' + newPerson;
          // Now message = 'The name is Takei, Luke'// which is much better than 'The name is [object Object]'

          再一次,JavaScript 剝離了您在經(jīng)典 OOP 語(yǔ)言中看到的一些基礎(chǔ)設(shè)施。(例如,沒(méi)有覆蓋關(guān)鍵字。)但它有效。

          6、支持類中的方法鏈

          方法鏈并不是真正的技巧,但它是我們并不總是認(rèn)為支持的那些實(shí)踐之一,它可以為您節(jié)省一些時(shí)間。

          同樣重要的是,它與 JavaScript 的生活方式相契合,因?yàn)樵S多內(nèi)置對(duì)象使用它取得了良好的效果。

          考慮這個(gè)帶有 Array 對(duì)象的例子。在這里,方法鏈允許您將兩個(gè)操作合并為一行——數(shù)組連接和數(shù)組排序:

          const evens = [2, 4, 6, 8];const odds = [1, 3, 5, 7, 9];const evensAndOdds = evens.concat(odds).sort();console.log(evensAndOdds); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

          在您自己的自定義類中支持方法鏈的最簡(jiǎn)單方法就是使用 this 關(guān)鍵字返回對(duì)當(dāng)前對(duì)象的引用。這個(gè) Book 類在它的 raisePrice() 和 releaseNewEdition() 方法中使用了這種技術(shù):

          class Book {  constructor(title, author, price, publishedDate) {     this.title = title;    this.author = author;    this.price = price;    this.publishedDate = publishedDate;  }
          raisePrice(percent) { const increase = this.price*percent; this.price += Math.round(increase)/100; return this; }
          releaseNewEdition() { // Set the pulishedDate to today this.publishedDate = new Date(); return this; }}
          // Let's make a Book objectconst book = new Book('I Love Mathematics', 'Adam Up', 15.99, new Date(2010, 2, 2));
          // Raise the price 15% and then change the edition, using method chainingconsole.log(book.raisePrice(15).releaseNewEdition());

          函數(shù)式程序員會(huì)看到這個(gè),說(shuō)也許您根本不想要一個(gè)有狀態(tài)的對(duì)象,而是一個(gè)不斷返回副本的不可變對(duì)象,就像 Array.concat() 和 Array.sort() 做的那樣。

          如果這種方法對(duì)您的代碼庫(kù)有意義,只需在方法末尾返回一個(gè)帶有修改細(xì)節(jié)的新對(duì)象,而不是當(dāng)前實(shí)例,如下所示:

          raisePrice(percent) {  const increase = this.price*percent;  return new Book(this.title, this.author,   this.price + Math.round(increase)/100, this.date);}

          7、制作可重復(fù)的隨機(jī)數(shù)列表

          這個(gè)更專業(yè)一點(diǎn),但它在緊要關(guān)頭對(duì)我很有用。

          有幾種不同的方法可以在 JavaScript 中創(chuàng)建偽隨機(jī)數(shù)。

          標(biāo)準(zhǔn) Math.random() 獲取不加密安全的隨機(jī)值,這適用于大多數(shù)用途。如果沒(méi)有,那么鮮為人知的 Crypto.getRandomValues() 可以幫助您。

          但是,這兩種方法都為您提供了不可重復(fù)的隨機(jī)數(shù)。

          如果您想運(yùn)行可重復(fù)的測(cè)試或模擬,這不是您所需要的,這對(duì)于大量統(tǒng)計(jì)和科學(xué)操作很重要。

          這個(gè)領(lǐng)域變得非常深入和復(fù)雜,但我總是保持簡(jiǎn)單而快速的 Mulberry32 算法來(lái)給我完全確定性的偽隨機(jī)數(shù)(這意味著如果你從相同的種子開(kāi)始,你總是得到相同的列表值)。

          我將它封裝在一個(gè)生成器函數(shù)中,這是我最喜歡的 JavaScript 專用特性之一。

          這是代碼:

          function* mulberry32(seed) {   let t = seed += 0x6D2B79F5;
          // Generate numbers indefinitely while(true) { t = Math.imul(t ^ t >>> 15, t | 1); t ^= t + Math.imul(t ^ t >>> 7, t | 61); yield ((t ^ t >>> 14) >>> 0) / 4294967296; }}

          你不需要理解這個(gè)實(shí)現(xiàn)的位移部分,它是從經(jīng)典的 C 實(shí)現(xiàn)中借來(lái)的。JavaScript 的不同之處在于,這是一個(gè)生成器函數(shù),正如 function* 關(guān)鍵字中的星號(hào)所表示的那樣。

          生成器函數(shù)使用 yield 返回按需值 — 在本例中為隨機(jī)數(shù)。

          以下是您創(chuàng)建和調(diào)用生成器的方法:

          // Use the same seed to get the same sequenceconst seed = 98345;const generator = mulberry32(seed);
          console.log(generator.next().value); // 0.9057375795673579console.log(generator.next().value); // 0.7620641703251749console.log(generator.next().value); // 0.0211441791616380

          這個(gè)生成器函數(shù)包裝了一個(gè)無(wú)限循環(huán),只要你繼續(xù)調(diào)用 next() 就會(huì)運(yùn)行。如果您不需要隨機(jī)數(shù),則生成器的執(zhí)行將暫停,其所有狀態(tài)保持不變。

          當(dāng)然,您不需要生成器函數(shù)來(lái)創(chuàng)建隨機(jī)數(shù)列表,但它是一個(gè)優(yōu)雅的解決方案。

          總結(jié)

          如果您喜歡這些示例,請(qǐng)查看注意收藏學(xué)習(xí),在此,非常感謝您的閱讀,祝您編程愉快!

          如果您覺(jué)得這些內(nèi)容對(duì)您有幫助,請(qǐng)記得關(guān)注我,點(diǎn)贊我,并將今天的內(nèi)容分享給您的朋友,也許能夠幫助到他。



          學(xué)習(xí)更多技能

          請(qǐng)點(diǎn)擊下方公眾號(hào)

          瀏覽 56
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一區二區三區色 | 在线香蕉| 大香蕉伊人免费在线观看 | 一区二区三区三级18岁看的 | 成人无码不卡免费视频 |