簡體   English   中英

如何用 Ramda 模仿 lodash.set

[英]How to imitate lodash.set with Ramda

我正在學習 Ramda,但我很困惑。 我想創建一個類似於 lodash.set 函數的 set 函數。 但是,當我在對象中存在的路徑上嘗試以下操作時,它似乎按預期工作,但是當我使用它來創建新路徑時,它會添加這個奇怪的數組。

const R = require('ramda')

const set = (object, path, value) => R.set(R.lensPath(path), value, object);

const foo = {
  moo: {
    goo: 'goo'
  }
}


set(foo, ['moo', 'goo', 'boo'], 'roo'); // { moo: { goo: { '0': 'g', '1': 'o', '2': 'o', boo: 'roo' } } }

所以結果是: // { moo: { goo: { '0': 'g', '1': 'o', '2': 'o', boo: 'roo' } } }

當我期望它是: // { moo: { goo: { boo: 'roo' } } }

為什么按索引添加這些字符? 如何使用 Ramda 完成 lodash.set 功能?

這似乎是不需要的行為。 為什么有人希望 Ramda 強制字符串?

我認為這是一個不同的問題。 foo.moo.goo是一個字符串時,您正在編寫的代碼應該做一些模糊地等同於foo.moo.goo.boo = 'roo' foo.moo.goo 這當然會引發錯誤,例如Cannot create property 'boo' on string 'goo'

Lodash 的回答是這樣的:“哦,你一定是說foo.moo.goo = {boo: 'roo'} 這是一個完全合理的猜測。 但這是一個猜測。 圖書館應該拋出像上面那樣的錯誤嗎? 這可能是合乎邏輯的做法。

Ramda(免責聲明:我是它的作者之一)做出了不同的選擇。 它假定您的意思是您所說的。 您想要更新foo.moo goo屬性, foo.moo是將其boo屬性設置為'roo' 然后它這樣做。 但是,當它更新這樣的屬性時,與其他任何地方一樣,它不會改變您的原始數據,而是為您構建一個新的輸出,復制舊對象的屬性,除了這個新路徑,它適當地設置。 那么,你的舊對象( 'goo' )有三個屬性, {0: 'g'} {1: 'o'}{2: 'o'}這Ramda的assocPath (公共函數也被用於lensPath完成這項工作)然后與您的{boo: 'roo'}組合成一個對象。

但我在這里誇大其詞。 Ramda 從未真正做出過這個選擇。 這只是實施中失敗的原因。 assocPath只知道兩種類型:數組和對象。 它只知道如何重建這些類型。 實際上它可以作為數組和其他人使用。 由於您的foo.moo不是數組,因此它將其視為對象。

如果你希望看到這種行為發生改變,一個新的 issue或者更好的pull request會得到公平的聽證會。 我可以向你保證那個。

但我預計會有很多阻力。

Ramda 的哲學與 lodash 的哲學截然不同。 lodash 強調靈活性。 例如, set允許您將路徑寫為數組或字符串,其中有兩個示例

_.set(object, 'a[0].b.c', 4);

_.set(object, ['x', '0', 'y', 'z'], 5);

並且許多函數都有可選參數。 它可以自由地改變提供給它的數據。 它旨在“為盡可能多的開發人員提供高質量的實用方法,重點是一致性、兼容性、定制化和性能”。 正如它的創始人曾經說過的那樣

相比之下,Ramda 不太擔心靈活性。 Ramda 的一個更重要的目標是簡單性 它的 API 沒有可選參數。 當它允許一個參數有多種類型時,只是因為它們共享更高的抽象。 提供給assocPath的路徑是一個數組,並且只是一個數組; 它通過注意每個路徑元素是字符串還是整數來處理對象與數組。 當然,Ramda 永遠不會改變您的輸入數據。

Ramda 也對手持設備不感興趣。 哲學通常是垃圾進,垃圾出之一。 這個案子似乎進入了那個領域。 Ramda 會心甘情願地將{moo: {goo: 'goo'}}轉換為{moo: {goo: {boo: 'roo'}}} 但是你必須更明確地告訴它這樣做: assoc(['moo', 'goo'], {boo: 'roo'})

因此,改變這一點的請求可能很難推銷……但這是一群友好的人。 如果您認為這很重要,請隨時提出。

我覺得我只需要從 lodash 導入set函數來防止意外行為。

但請記住,行為是多么不同。 最大的區別是 lodash 正在改變它的輸入,而 Ramda 不會這樣做。 他們對要增強哪些值和替換哪些值有不同的想法(如當前示例中所示)。當然,他們的簽名是不同的。 它們在數組索引方面有不同的行為。 (例如,我想不出在 lodash 的set中添加一個字符串鍵為 '0' 的對象的方法。當你調用類似assocPath(['grid', 'width'], newVal, myObj) ,而 lodash 很樂意改變內部的 Rectangle 對象。)

換句話說,它們是不同的行為,為不同的目的而設計。 如果 lodash 的行為是您想要的,請務必包含它。 但是,如果您在大部分實用程序工作中都使用 Ramda,請注意它們的理念有何不同。

暫無
暫無

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

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