首頁 > web前端 > js教程 > JavaScript中可變分配和突變的指南

JavaScript中可變分配和突變的指南

尊渡假赌尊渡假赌尊渡假赌
發布: 2025-02-10 10:35:09
原創
529 人瀏覽過

JavaScript中可變分配和突變的指南

在JavaScript的世界中,您經常聽到

突變,但是它們到底是什麼,它們是邪惡的嗎? 在本文中,我們將涵蓋可變分配和突變的概念,並查看為什麼 - 一起 - 它們對開發人員來說可能是一個真正的痛苦。我們將研究如何管理它們以避免問題,如何使用盡可能少的以及如何保持代碼可預測。 如果您想更詳細地探索此主題,或者與Modern JavaScript提高速度,請查看我的新書的第一章,學習免費使用JavaScript。 >

讓我們從回到價值類型的基礎知識開始吧……

>

鑰匙要點

JavaScript值分類為原語(不變)和對象(可變),從而影響了可變分配和突變的行為。 使用“ const”不會阻止對象突變;它僅防止將變量重新分配到其他值或對象。 >

'LET'關鍵字允許重新分配,使其適用於需要在整個代碼中更改值的變量。

傳播操作員(``…')對於創建對象的淺副本至關重要,從而避免了與復制劃分的對像中的突變有關的問題。

突變本質上不是不好的,而應仔細管理以維持代碼可預測性並最大程度地減少錯誤,尤其是在動態的Web應用程序中。

>

    >數據類型
  • JavaScript中的每個值都是原始值或對象。有七種不同的原始數據類型:
  • 數字,例如3、0,-4、0.625
  • >字符串,例如'Hello',“ world”,`hi`'''
  • booleans,true and false
  • null

未定義的

>符號 - 一個獨特的令牌,保證永遠不會與另一個符號衝突

    bigint-用於處理大整數值
  • 任何不是原始價值的東西都是一個對象,包括數組,日期,正則表達式,當然還有對象文字。功能是一種特殊的對像類型。它們絕對是對象,因為它們具有屬性和方法,但也可以稱為對象。
  • 變量分配
  • >變量分配是您在編碼時學習的第一件事之一。例如,這是我們將數字3分配給變量熊的方式:>
  • 變量的常見隱喻是其中一個標籤的框之一,其內部有值。上面的示例將被描繪成一個包含標籤“熊”的盒子,其中3個值。
  • >考慮發生的事情的另一種思考方式是作為參考,將標籤映射到3:
  • >的值

    JavaScript中可變分配和突變的指南

    如果我將數字3分配給另一個變量,則引用與熊相同的值:

    <span>const bears = 3;
    </span>
    登入後複製
    登入後複製
    登入後複製
    登入後複製
    登入後複製

    JavaScript中可變分配和突變的指南

    變量熊和火槍手都引用相同的原始值3。我們可以使用嚴格的等價運算符對此進行驗證,===:

    <span>let musketeers = 3;
    </span>
    登入後複製
    登入後複製
    登入後複製
    登入後複製
    如果兩個變量都引用相同的值,則相等性操作員返回true。

    在使用對象時

    時有些陷入困境

    >先前的示例顯示了要分配給變量的原始值。分配對象時使用相同的過程:

    此分配意味著變量Ghostbusters引用了一個對象:>
    bears <span>=== musketeers
    </span><span><< true
    </span>
    登入後複製
    登入後複製
    登入後複製

    但是,在將對象分配給變量時,一個很大的區別是,如果將另一個對象分配給另一個變量,它將引用一個完全不同的對象 - 即使兩個對象文字看起來完全相同!例如,下面的作業看起來像變量TMNT(青少年突變體忍者神龜)引用與變量捉鬼敢死的對象:

    JavaScript中可變分配和突變的指南

    >即使變量Ghostbusters和Tmnt看起來像是引用相同對象,它們實際上都引用了一個完全不同的對象,我們可以看到我們是否使用嚴格的平等操作員檢查

    <span>const ghostbusters = { number: 4 };
    </span>
    登入後複製
    登入後複製

    >變量重新分配
    <span>let tmnt = { number: 4 };
    </span>
    登入後複製
    登入後複製
    當在ES6中引入const關鍵字時,許多人錯誤地認為常數已被引入JavaScript,但事實並非如此。此關鍵字的名稱有點誤導。

    JavaScript中可變分配和突變的指南> const聲明的任何變量均不能重新分配到另一個值。這適用於原始值和對象。例如,變量熊在上一節中使用const聲明,因此它不能為其分配另一個值。如果我們嘗試將數字2分配給變量熊,我們會發現一個錯誤:

    >

    對數字3的引用是固定的,熊變量無法重新分配另一個值。 >

    >同樣適用於對象。如果我們嘗試將另一個對象分配給變量Ghostbusters,則會得到相同的錯誤:>

    使用LET

    >當關鍵字用於聲明變量時,可以將其重新分配以稍後在我們的代碼中引用不同的值。例如,我們使用LET聲明了可變的火槍手,因此我們可以更改火槍手所引用的價值。如果D'Artagnan加入了火槍手,他們的人數將增加到4:
    ghostbusters <span>=== tmnt
    </span><span><< false
    </span>
    登入後複製
    登入後複製

    這可以做到這一點,因為讓我們用來聲明變量。我們可以根據我們喜歡的次數改變火態引用的價值。

    >

    也使用Let聲明了變量TMNT,因此也可以重新分配以引用另一個對象(如果我們喜歡的話,或者完全是其他類型):>

    <span>const bears = 3;
    </span>
    登入後複製
    登入後複製
    登入後複製
    登入後複製
    登入後複製
    請注意,變量TMNT現在引用a

    完全不同的對象;我們不僅將數字屬性更改為5。 總而言之,如果您使用const聲明一個變量,則無法重新分配其值,並且始終將引用最初分配給的相同原始值或對象。如果您使用LET聲明一個變量,則可以根據程序後來要求將其值重新分配多次。

    >通常將盡可能多地視為良好實踐,因為這意味著變量的價值保持恆定,並且代碼更加一致和可預測,從而使其不容易出現錯誤和錯誤。 通過參考 在本機JavaScript中,您只能為變量分配值。即使看起來可以,您也無法分配變量來引用另一個變量。例如,stooges的數量與火槍手的數量相同,因此我們可以使用以下內容來分配變量stooges以引用與變量火槍手相同的值:

    這看起來像變量stooges正在引用變量步槍儀,如下圖所示:

    但是,在本機JavaScript中,這是不可能的:變量只能引用實際值;它無法引用另一個變量。當您進行這樣的作業時,實際發生的是,分配左側的變量將引用右引用的變量的值,因此變量stooges將引用與Musketeers變量相同的值,這是數字3一旦完成了這項任務, Stooges變量根本沒有連接到Stubketeers變量。

    <span>let musketeers = 3;
    </span>
    登入後複製
    登入後複製
    登入後複製
    登入後複製

    這意味著,如果D'Artagnan加入了火槍手,並且我們將火槍手的價值設置為4,則Stooges的價值將保持3.實際上,因為我們使用const聲明了Stooges變量,所以我們無法設置它具有任何新價值;它將永遠是3 總結:如果您使用const聲明變量並將其設置為原始值,即使是通過對另一個變量的引用,則其值無法更改。這對您的代碼有益,因為這意味著它將更加一致和可預測。

    JavaScript中可變分配和突變的指南突變

    如果可以更改值,則說一個值為

    >可變的

    。僅此而已:AJavaScript中可變分配和突變的指南突變

    是更改值的屬性的行為。JavaScript中的所有原始價值均為

    不變的:您永遠無法更改其屬性。例如,如果我們將字符串“蛋糕”分配給可變食品,我們可以看到我們無法更改其任何屬性:

    <span>const bears = 3;
    </span>
    登入後複製
    登入後複製
    登入後複製
    登入後複製
    登入後複製
    如果我們試圖將第一個字母更改為“ F”,看起來它已經改變了:>

    >但是,如果我們看一下變量的值,我們發現什麼都沒有改變:
    <span>let musketeers = 3;
    </span>
    登入後複製
    登入後複製
    登入後複製
    登入後複製
    >

    如果我們嘗試更改長度屬性,也會發生同樣的事情:
    bears <span>=== musketeers
    </span><span><< true
    </span>
    登入後複製
    登入後複製
    登入後複製
    >

    >儘管返回值表示已更改了長度的屬性,但快速檢查表明它沒有:
    <span>const ghostbusters = { number: 4 };
    </span>
    登入後複製
    登入後複製

    請注意,這與使用const而不是let聲明變量無關。如果我們曾經使用過,我們可以將食物設置為引用另一根字符串,但我們無法更改其任何屬性。不可能更改原始數據類型的任何屬性,因為它們是不變的
    <span>let tmnt = { number: 4 };
    </span>
    登入後複製
    登入後複製
    。 JavaScript中的

    可變性和對象 相反,JavaScript中的所有對像都是可變的,這意味著即使使用const聲明了它們的屬性,也可以更改其屬性(請記住,請記住並僅控制一個變量是否可以重新簽名,並且與可變性)。例如,我們可以使用以下代碼更改數組的第一項:>

    請注意,儘管我們使用const宣布了可變食品,但仍會發生這種變化。這表明使用const

    不會阻止對像被突變

    >我們也可以更改數組的長度屬性,即使已使用const聲明了數組:>
    ghostbusters <span>=== tmnt
    </span><span><< false
    </span>
    登入後複製
    登入後複製

    >通過參考複製 >請記住,當我們將變量分配給對象文字時,變量也將完全不同的對象引用,即使它們看起來相同:

    >

    bears <span>= 2;
    </span><span><< TypeError: Attempted to assign to readonly property.
    </span>
    登入後複製

    但是,如果我們將變量factant4分配給另一個變量,它們都會引用相同

    對象:>

    ghostbusters <span>= {number: 5};
    </span><span>TypeError: Attempted to assign to readonly property.
    </span>
    登入後複製
    這將變量factany4分配給引用

    與變量TMNT引用的對象相同,而不是完全不同的對象。 JavaScript中可變分配和突變的指南

    這通常稱為通過引用複制,因為兩個變量都分配給引用

    > same
    musketeers <span>= 4;
    </span>
    登入後複製
    對象。

    這很重要,因為對此對象進行的任何突變都將在兩個變量中都可以看到。 >因此,如果蜘蛛俠加入神奇四俠,我們可能會更新對像中的數字值:>

    這是一個突變,因為我們已經更改了數字屬性,而不是設置factand4來引用新對象。 JavaScript中可變分配和突變的指南

    這會導致我們一個問題,因為TMNT的數量屬性也會改變,甚至可能沒有我們意識到:>
    <span>const bears = 3;
    </span>
    登入後複製
    登入後複製
    登入後複製
    登入後複製
    登入後複製

    這是因為TMNT和FANTANDY4都在引用相同的對象,因此任何對TMNT或FANTANDEN的突變都會影響它們兩個。

    >這突出了JavaScript中的一個重要概念:當對象通過參考複製並隨後突變時,突變會影響任何引用該對象的任何其他變量。這可能會導致意外的副作用和難以追踪的錯誤。

    搶救的傳播操作員!

    >

    >那麼,如何在不創建對原始對象的引用的情況下製作對象的副本?答案是使用傳播操作員!

    >傳播操作員是在ES2015中的陣列和字符串以及ES2018中的對象引入的。它使您可以輕鬆地製作對象的淺副本,而無需創建對原始對象的引用。

    >下面的示例顯示了我們如何設置可變factany4來引用tmnt對象的副本。該副本將與TMNT對象完全相同,但是fancally4將引用一個全新的對象。這是通過將要復制的變量的名稱放置在對像中的文字中,並在其前面的傳播操作員來完成:>

    >我們在這裡實際完成的是將變量factally4分配給新對象文字,然後使用傳播操作員複製TMNT變量引用的對象的所有枚舉屬性。由於這些屬性是值,因此它們按值將其複製到奇妙的4個對像中,而不是通過參考。
    <span>let musketeers = 3;
    </span>
    登入後複製
    登入後複製
    登入後複製
    登入後複製
    >

    JavaScript中可變分配和突變的指南>現在,對任何一個對象進行的任何更改都不會影響另一個對象。例如,如果我們將fandand4變量的數字屬性更新為5,則不會影響tmnt變量:

    >

    bears <span>=== musketeers
    </span><span><< true
    </span>
    登入後複製
    登入後複製
    登入後複製

    JavaScript中可變分配和突變的指南>傳播運算符還具有有用的快捷方式表示法,可用於製作對象的副本,然後在單個代碼行中對新對象進行一些更改。 > 例如,說我們想創建一個對象來建模青少年忍者神龜。我們可以創建第一個烏龜對象,並為其分配可變的leonardo:>

    除武器和顏色特性外,其他烏龜都具有相同的特性,每隻烏龜都不同。使用ever operator,然後更改武器和顏色屬性,將列昂納多引用的對象複製進行副本,就像:

    一樣:

    >我們可以通過添加引用在vread對像後要更改的屬性來在一行中執行此操作。這是為變量Donatello和Raphael創建新對象的代碼:

    <span>const bears = 3;
    </span>
    登入後複製
    登入後複製
    登入後複製
    登入後複製
    登入後複製

    >請注意,以這種方式使用傳播操作員只能使對象的淺副本。要進行深層副本,您必須遞歸進行此操作或使用庫。就個人而言,我建議您嘗試使物體盡可能淺。

    突變不好?

    在本文中,我們介紹了可變分配和突變的概念,並看到了為什麼 - 它們對開發人員來說可能是一個真正的痛苦。

    突變的聲譽不好,但它們本身並不一定是不好的。實際上,如果您要構建動態的Web應用程序,則必須在某個時候改變。從字面上看,這就是“動態”一詞的含義!這意味著您的代碼中必須存在一些突變。話雖如此,突變越少,您的代碼就會越容易預測,使維護更容易,並且不太可能開發任何錯誤。

    一種特別有毒的組合正在通過參考和突變複製。這可能會導致您甚至沒有意識到發生的副作用和錯誤。如果您突變代碼中另一個變量引用的對象,則可能會導致許多可能難以追踪的問題。關鍵是嘗試最大程度地減少您對突變的使用,並跟踪哪些物體已被突變。 在功能編程中,純函數是不會引起任何副作用的功能,突變是副作用的最大原因之一。

    黃金法則是避免通過參考複製任何對象。如果要復制另一個對象,請使用傳播操作員,然後在製作副本後立即進行任何突變。

    接下來,我們將研究JavaScript中的數組突變。

    如果您想通過現代JavaScript加快速度,請不要忘記查看我的新書與JavaScript學習代碼。您可以免費閱讀第一章。如果您有任何疑問或評論,請在Twitter上與您聯繫!

    經常詢問有關JavaScript變量分配和突變的問題(常見問題解答)

    > JavaScript中的變量分配與突變之間有什麼區別?例如,令x = 5;在這裡,我們將值5分配給變量x。另一方面,突變是指更改現有變量價值的過程。例如,如果我們以後寫x = 10;我們通過將其值從5更改為10來突變x。

    > JavaScript在原始和非基本數據類型中如何處理可變分配和突變?

    > JavaScript處理原始數據類型(例如數字,字符串和布爾值)和非主要數據類型(例如對象(例如對象)在變量分配和突變方面,陣列的不同。對於原始數據類型,當您分配變量時,將創建並存儲在新的內存位置中。但是,對於非主要數據類型,當您分配變量時,兩個變量都指向同一內存位置。因此,如果您突變一個變量,則將變化反映在所有指向該內存位置的變量中。

    >

    >在JavaScript中,逐個傳遞和逐次參考的概念是什麼?

    >通過逐步傳遞和通過引用是JavaScript可以將變量傳遞到函數的兩種方式。當JavaScript通過值通過變量時,它會創建變量值的副本,並將復製到函數的副本。對函數內部變量的任何更改都不會影響原始變量。但是,當JavaScript通過引用傳遞變量時,它將引用對變量的內存位置。因此,對函數內部變量的任何更改也會影響原始變量。

    >如何防止JavaScript中的突變?

    >有幾種方法可以防止JavaScript突變。一種方法是使用object.freeze()方法,該方法可防止新屬性被添加到對象,現有屬性被刪除,並防止更改現有屬性的枚舉性,可配置性或書寫性。另一種方法是在聲明變量時使用const關鍵字。這樣可以防止重新分配變量,但是如果該值是對像或數組。 🎜>在JavaScript中,對象的淺副本是對象的副本,其中原始對象的值和副本指向非原始數據類型的同一內存位置。因此,如果將副本變異,則原始對像也會突變。另一方面,對象的深副本是對象的副本,其中原始對象和副本的值未指向相同的內存位置。因此,如果將副本變異,則原始對像不會被突變。

    >

    >如何在JavaScript中創建對象的深副本?在JavaScript中是使用JSON.PARSE()和JSON.STRINGIFY()方法。 JSON.STRINGIFY()方法將對象轉換為JSON字符串,而JSON.PARSE()方法將JSON字符串轉換回對象。這將創建一個新對象,它是原始對象的深副本。

    >

    > JavaScript中的突變處理器API是什麼?它旨在提供一般,高效且健壯的API,以對文檔中的更改做出反應。

    > JavaScript如何在封閉情況下如何處理變量分配和突變?閉合是一個函數,它具有訪問其自己的範圍,外部函數範圍和全局範圍的函數。當變量被分配或在閉合內部突變時,它可能會影響外部範圍中變量的值,具體取決於該變量是在閉合範圍中聲明還是外部範圍。在JavaScript?

    中的var,let和const之間,在JavaScript,var,let和const中用於聲明變量。 VAR是函數範圍的,如果在函數之外聲明它,則將其在全球範圍內進行範圍。讓我們的const是塊範圍的,這意味著它們僅存在於其聲明的塊中。 let and const之間的差異是讓允許重新分配,而const卻不。在JavaScript中異步編程的上下文中,異步編程允許同時進行多個事物。當變量在異步函數中分配或突變時,如果代碼的其他部分依賴於變量的值,則會導致意外結果。這是因為在代碼的其他部分運行之前,變量分配或突變可能尚未完成。為了解決此問題,JavaScript提供了多個功能,例如Promises和Async/等待,以幫助管理異步代碼。

    >

以上是JavaScript中可變分配和突變的指南的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板