underscore.js:カスタム関数のチェーン方法
-
08-10-2019 - |
質問
使用 underscore.js, 、戻る以下を書くことができます 42
:
_([42, 43]).chain()
.first()
.value()
underscore.jsの一部ではなく、カスタム機能があります double()
:
function double(value) { return value * 2; };
アンダースコアの一部であるかのように、この関数をアンダースコアチェーンで呼び出すことができます。以下を書きたいです。返したい 84
:
_([42, 43]).chain()
.first()
.double()
.value()
Underscoreが定義していないため、これは機能しません double()
. 。使用できます tap()
のように:
_([42, 43]).chain()
.first()
.tap(double)
.value()
これは有効ですが、 tap
関数をその引数に適用し、関数の結果ではなく、引数を返します。だから私はある種のものが必要だと思う tap
それは、その引数に適用された関数の結果を返します。 underscore.jsにこのようなことはありますか?私はひどく明白なものを見逃していますか?
解決
見つけていない tap
それは関数によって返される値を返すことは実行されます、私は私ができるものを定義します take
そして追加します _
:
_.mixin({take: function(obj, interceptor) {
return interceptor(obj);
}});
それから私が持っていると仮定すると:
function double(value) { return value * 2; };
私は書くことができます:
_([42, 43]).chain()
.first() // 42
.take(double) // Applies double to 42
.value() // 84
あなたは見ることができます take
なので map
オブジェクト上、リストの代わりに。これを試したいですか?これを参照してください jsfiddleの例.
他のヒント
したがって、カスタム関数があります:
function double(value) { return value * 2; }
使用できます mixin
それを拡張するには:
_.mixin({ double:double });
これで、アンダースコアオブジェクトから関数を呼び出すことができます _
:
_.double(42); // 84
から返されたラップオブジェクトから chain
:
_([42, 43]).chain()
.first()
.double() // double made it onto the wrapped object too
.value(); // 84
さて、私は初めてアンダースコアの注釈付きソースコードを読んでから新鮮です。しかし、私はあなたがこのようなことができると思います:
function double(value) { return value * 2; };
var obj = _([42, 43]).addToWrapper({double:double});
obj.chain()
.first()
.double()
.value();
構文/詳細は正しくないかもしれませんが、コアポイントはこれです:電話するとき _([42,43])
, 、あなたは関数としてアンダースコアを呼んでいます。そうすると、新しいオブジェクトをインスタンス化してから、そのオブジェクトに混合して、ほとんどのアンダースコア関数が機能します。次に、そのオブジェクトをあなたに返します。その後、そのオブジェクトに独自の関数を追加することができますが、これは「_」ネームスペース自体を汚染しません。
それがUnderscore.jsコードが私に姿を見せたものです。私が間違っているなら、私は知りたいです、そして、うまくいけば誰かがその理由を説明するでしょう。
編集:私は実際にEnderscore.jsを約1か月間頻繁に使用していますが、私はそれにかなり慣れてきました。今私は 知る 私がここで言ったように振る舞います。コンストラクター関数として_を呼び出すと、独自の「名前空間」(オブジェクトのみ)を取り戻し、名前空間に表示されるが「グローバル」「_」には表示されないaddtowrapper()で物事を追加できます。名前空間。したがって、OPが指名手配した機能はすでに組み込まれています(そして、私はアンダースコアに本当に感銘を受けました、それは非常にうまくいっています)。
これを簡単に達成するための多くの方法、こうしたそのような解決策があります。
_.chain([42,43])
.first(1)
.map(double)
.first()
.value();
// 84
ただし、使用することをお勧めします ラムダ その後、自動カリーとパイプ /これらの種類のタスクを作成することは些細なことです。
R.pipe(R.head, R.multiply(2))([42, 43]); // 84
equivalent to:
R.compose(R.multiply(2), R.head)([42, 43]); // 84
OPで要求されているように、単一の値ではなく、最初の2つのアイテムを言うためにソリューションを拡張したい場合は、
R.pipe(R.take(2), R.map(R.multiply(2)))([42, 43]) // [84, 86]
ただし、Ramda R.composeでは推奨されます。いずれにせよ、このような些細なタスクの場合、より便利で使いやすい傾向があります。
Lodashがあなたが探しているものを正確に実装したように見えます:
_.thru(value, interceptor)
ドキュメントから:
この方法は_.tapのようなものですが、インターセプターの結果を返すことを除いて
します map
これのために働いていますか?
_([42, 43]).chain()
.first()
.map(double)
.value()
編集
ドキュメントからは、そのように見えます map
電話の前に配置する場合にのみ機能します first
:
_([42, 43]).chain()
.map(double)
.first()
.value()
使用 compose
状況に対処する別の方法ですが、 take
前に提案したように より良い解決策です。それでも、ここにコードがどのように見えるかがあります compose
:
function double(value) { return value * 2; };
_.compose(
double,
_.first,
_.bind(_.identity, _, [42, 43])
)();
初期値は、その値を返す関数を介して提供する必要があります(ここではカリーによって行われます identity
)、そして関数は、あなたが持っているものの逆である他のものにリストする必要があります。