あなたはJavaScriptを書いていて、突然あなたが巨大な関数を書いたことを恐怖と恐怖で認識しています。 それは私たちの最高に起こった。 今より小さい部分の機能を分けるほとんど止められない衝動は来る。
大きな関数は、一つの場所で多くの責任を意味し、おそらくコードの匂いもするので、それ自体は良い考えです。 しかし、あなたはその意味や文脈を失わないように関数を分割したいと思っています。 これを行うには、関数連鎖とも呼ばれるメソッド連鎖を考える必要があります。 この記事では、私がそれによって何を意味するのかを説明します。
前提条件
始める前に、すでに慣れ親しんでおく必要があるJavaScriptの概念をいくつか紹介します:
- Arrow関数
- 配列メソッド
- 非同期関数
ほとんどの経験豊富な開発者は、map、reduce、filterなどのArray
メソッドの経験があります。 あなたはおそらくすでにこのようなものに遭遇しました:
const food = ;// This type of usage is very commonfood .map(item => item.type) .reduce((result, fruit) => { result.push(fruit); return ; }, );// result:
メソッドの連鎖は、同じオブジェクトとその参照を使用して複数の関数を呼び出す場合に発生します。 上記の例では、配列メソッドmap
は、膨大な数のメソッドを持つArray
を返します。
Array
を指す参照を返すため、Array
のすべてのプロパティにアクセスできます。 それはあなたがあなた自身の方法連鎖のために使うのと同じ原則です。
これをよりよく理解する
私はthis
のすべてのニュアンスをカバーするわけではありませんが、なぜthis
が機能するのかを理解するのは良いことです。 どんなにあなたが経験しても、これは理解するのは難しいことができますキーワード。 それはしばしば物事があなたがそれらを期待するようにうまくいかない理由です。
ここにその要点があります:this
は常に現在のscope
またはそれが呼び出されたインスタンスを指します。 例を挙げてみましょう:
const dog = { is: null, log: () => console.log(this.is), bark() { this.is = "woofing"; this.log(); return this; }, walk() { this.is = "walking"; this.log(); return this; }, eat() { this.is = "eating"; this.log(); return this; }};dog .bark() .eat() .walk();
このような関数を書くとき(しゃれは意図していません)、オブジェクトに関連するメソッドを連鎖させたい場合があります。 オブジェクトdog
には、walk
、bark
、eat
の3つのメソッドがあります。 私がその関数のいずれかを呼び出すたびに、コンソールはその正確な瞬間に犬が何をしているかの表現を表示する必要があります。
しかし、それには問題があります。 ブラウザで実行すると、期待どおりに動作しないことがわかります。 これは、矢印関数が字句スコープを使用しているためです。this
はその周囲のスコープを参照します-この場合はwindow
であり、オブジェクト自体ではありません。
これを解決するには、log
プロパティを表す無名関数呼び出しを使用する必要があります:
// instead of this: log: () => console.log(this.is),// use this: log() { console.log(this.is); }
これで、犬のthis
スコープは関数内でアクセスできるようになります。
クラスを使用して
あなたはクラスを使用して同じ結果を達成することができます:
class Dog { is = null; log() { console.log(this.is); } bark() { this.is = "woofing"; this.log(); return this; } walk() { this.is = "walking"; this.log(); return this; } eat() { this.is = "eating"; this.log(); return this; }}const dog = new Dog();dog .bark() .eat() .walk();
Prototype
を使用するprototypeを使用する必要がある場合は、次のようにします:
function Dog() {}Dog.prototype.is = null;Dog.prototype.log = function() { console.log(this.is);};Dog.prototype.bark = function() { this.is = "woofing"; this.log(); return this;};Dog.prototype.walk = function() { this.is = "walking"; this.log(); return this;};Dog.prototype.eat = function() { this.is = "eating"; this.log(); return this;};const dog = new Dog();dog .bark() .eat() .walk();
非同期関数はどうですか?
async
あなたがasync
関数を宣言するとき、あなたはそれが約束を返すことを知っています。 そのため、promiseのすべてのメソッドにアクセスすることもできます。
const requests = { user: null, action: null, log(something) { console.log(this); }, async getUser() { this.user = await new Promise(resolve => { setTimeout(() => { resolve("Douglas Pires"); }, 1000); }); this.log("user"); return this; }, async registerAction() { this.action = await new Promise(resolve => { setTimeout(() => { resolve("programming stuff"); }, 1000); }); this.log("action"); return this; }};requests.getUser().then(() => requests.registerAction());
しかし、約束の束を一緒に連鎖させることは良い考えではありません。 私は代わりにawait
キーワードの束を使用することをお勧めします。 それはより簡単で、あなたのコードをはるかに読みやすくします。
await requests.getUser(); // Douglas Piresawait requests.registerAction(); // programming
そして、あなたはここで同じプロパティへのアクセス権を持っています:
console.log(requests.user); // Douglas Piresconsole.log(requests.action); // programming
結論として、
連鎖関数は、オブジェクトを操作する必要があるときに便利です。 また、コードの可読性を向上させる実用的な方法でもあります。 しかし、あなたが上で見てきたように、あなたは賢明に連鎖する必要があります。
この記事では、JavaScriptメソッドチェーンのコンテキストでthis
、クラス、プロトタイプ、およびasync
関数について説明しました。 私はあなたがいくつかの有用なヒントを拾ってきたし、今より良いトピックについて知らされている願っています。 JavaScriptメソッドのすべてのコードをここに連鎖させた私のリポジトリを見つけることができます。 次の投稿でお会いしましょう!
以下のボタンを使用してソーシャルメディア上で共有すること自由に感じます。 また、NuxtとVuetifyを使用してカラーパレットジェネレータを構築する方法についても書いています。 それをチェックアウトしてください!