簡體   English   中英

我們應該關心 JS 非原始值的可變性嗎?

[英]Should we care about JS non-primitive values mutability?

想象你有一個方法,它的目的是修改一個對象數組,並返回它的新版本。

 const likePosts = (posts) => posts.map((post) => { post.isLiked = true return post; }); const originalPosts = [{ isLiked: false }, { isLiked: false }]; const newLikedPosts = likePosts(originalPosts); console.log(newLikedPosts);

但是,由於 JS 非原始值是可變的,如果在執行代碼后,我們記錄 originalPosts,我們將看到 isLiked 字段如何不是 false,它也被修改為 true!

 const likePosts = (posts) => posts.map((post) => { post.isLiked = true return post; }); const originalPosts = [{ isLiked: false }, { isLiked: false }]; const newLikedPosts = likePosts(originalPosts); console.log({ newLikedPosts }); console.log({ originalPosts });

我們應該關心這件事嗎? 我的意思是,例如,在這種情況下,“originalPosts”是否更新並不重要,因為它是執行“likePosts”后代碼的無用數據。

如果我們在沒有必要時關心數據突變,我們可能會進行額外的克隆,從而對性能產生負面影響,對嗎?

換句話說,當您編寫 JS 代碼時,您是否不斷克隆數據以避免在不必要的情況下發生突變?

是的,這是值得思考和關心的事情。 在腳本中,至少根據我的經驗以及我在 Stack Overflow 上看到的情況,相當多的錯誤是由腳本編寫者未預料到的可變值更改引起的。

使用您的代碼:

const likePosts = (posts) => posts.map((post) => {

如果維護這個腳本的其他人(或者你,幾個月后)看到這個函數,他們完全有理由假設它創建一個新數組,而不是修改現有數組中的對象 - 這就是.map是為了,這就是大多數人期望它做的事情。 但是,如果您在回調中改變對象,然后返回原始對象,則使用.map沒有多大意義 - 那些必須稍后維護代碼的人很容易被代碼的意圖誤導,這可能導致錯誤。

當然,對於這么小的函數,這樣的事情是不太可能的,但對於一般情況,事情很少如此簡單。 IMO,返回新對象而不是改變現有對象通常會產生更清晰、更易於理解的代碼 - 有一個基於此和類似想法的巨大編程范式- 但你是對的:

我們可能會進行額外的克隆,從而對性能產生負面影響,對嗎?

在不必要時創建全新的對象可能會影響性能,特別是如果您需要經常這樣做並且否則必須克隆的對象很大和/或很深。 但是,現在的計算機相當不錯——即使在低端機器上,這種差異(變異與創建新對象)在給定的代碼段中也不太可能產生任何可辨別的影響。 可能會,但可能不會。

與往常一樣,如果您擔心性能問題,請首先確保您擁有可工作、清晰且可維護的代碼 - 然后您可以運行性能測試來確定瓶頸並修復瓶頸。 過早的優化需要時間,會使代碼更難理解,並且可能不會對整個應用程序產生任何影響。

在大多數情況下,當您必須在變異和創建新對象之間做出選擇時,您可能可以選擇其中之一,並且您的應用程序無論如何都會一樣好,只要代碼的意圖是明確的 例如,您可能會更改

const likePosts = (posts) => posts.map((post) => {
  post.isLiked = true
  return post;
});

const likePosts = (posts) => {
  for (const post of posts) {
    post.isLiked = true;
  }
};

沒有返回值,也沒有多余的.map ,使得意圖更加清晰。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM