Core JavaScript-04.コールバック関数
4879 ワード
1πコールバック関数は何ですか.
別のコードのパラメータに制御権を渡し、そのパラメータの関数に制御権を渡します.
コールバック関数を許可するコードは、自身の内部ロジックに基づいて適切な時点でコールバック関数を実行します.
📚 map関数によるコールバック関数の解析
mapメソッドは、コールバック関数を最初のパラメータとして受信します.
2番目の省略可能なパラメータは、コールバック関数の内部でthisと識別されるターゲットを指定することができる.(thisArgを省略すると、グローバルオブジェクトがバインドされます.)
配列内のすべての要素を最初から最後まで1つずつ取り出し、コールバック関数を繰り返し呼び出し、コールバック関数の実行結果を収集して新しい配列を作成します.
コールバック関数の最初のパラメータには現在の値が含まれ、2番目のパラメータには現在の値インデックスが含まれ、3番目のパラメータには配列全体が含まれます.
💻 map関数を直接実現しましょう
このメソッドをforEach関数のコールバック関数として渡します.
objを使う方法を直接伝えるのではなく、objです.valuesが指す関数のみが渡されます.
したがって、objと直接関連付けられていないため、グローバルオブジェクトの表示につながります.
オブジェクトのメソッドを関数のパラメータに渡しても、最終的にはメソッドではなく関数にすぎません.
📝 コールバック関数で特定のthisをバインドする場合はbindメソッドを使用します.
地獄
コールバック関数を匿名関数に渡すプロセスを繰り返し、コードのインデント深さに耐えられない
通常、イベント処理やサーバ通信などの非同期タスクを実行する場合に発生します.
🚀 例題を通じてcallback地獄から釈放する方法を理解しましょう.
💣 地獄
デップはますます深くなって、あなたの毒性は最も悪い!!⚠️⚠️⚠️
💡 コールバック地獄解決1-変換記名関数
💡 callback地獄解決2-Promise
new演算子とともに呼び出されたPromiseパラメータに渡されるコールバック関数は、呼び出されるとすぐに実行されますが、resolve、execute関数の内部に構文がある場合、そのうちの1つが実行されるまでthenまたはエラー構文(catch)には移動しません.
💡 callback地獄解決3-Generator
*付きの関数はジェネレータです.generator関数を実行してiteratorを返します.iteratorにはnextというメソッドがあります.
nextメソッドを呼び出すと、generator関数の内部に最初に現れた完成品で関数の実行が停止します.
nextメソッドが再び呼び出されると、前に停止した部分から開始し、表示された完成品で関数の実行を停止します.
すなわち、非同期操作が完了したときにnextが呼び出されると、ジェネレータ関数の内部ソースは上から下へ順に実行されます.
💡 コール地獄解決4-Promise+Async/Await
非同期操作を実行する関数の前にasyncをマークし、関数の内部に実際の非同期操作が必要な各位置にawaitをマークするだけで、後の内容を自動的にpromiseに変換できます.
この内容が解決してから、次のステップに進むことができます.
すなわち,承諾したthenのような効果を得ることができる.
📚 整理する
📌 コールバック関数は、パラメータを他のコードに渡し、同時に制御権を委任する関数です.
📌 制御権を受け取ったコードは、コールバック関数が呼び出された時点を自動的に判断します.
📌 制御権を渡すコードは、コールバック関数を呼び出すと、パラメータに渡される値の順序が決定されます.
📌 制御権を受け入れるコードは、コールバック関数のthisが何を望んでいるかを決定することができる.(bindメソッド)
📌 メソッドをパラメータとしてどの関数に渡しても、最終的には関数として実行されます.
📌 非同期制御のためにコールバック関数を使用すると、コールバック地獄に陥る.ソリューションにはPromise、Generator、async/awaitなどがあります.
別のコードのパラメータに制御権を渡し、そのパラメータの関数に制御権を渡します.
コールバック関数を許可するコードは、自身の内部ロジックに基づいて適切な時点でコールバック関数を実行します.
📚 map関数によるコールバック関数の解析
[1,2,3].map(function(currentValue, index) {
console.log(currentValue, index);
});
Array.prototype.map(callback[, thisArg])
callback: function(currentValue, index, array)
Arrayプロトタイプにおけるmap法は上記構造からなる.mapメソッドは、コールバック関数を最初のパラメータとして受信します.
2番目の省略可能なパラメータは、コールバック関数の内部でthisと識別されるターゲットを指定することができる.(thisArgを省略すると、グローバルオブジェクトがバインドされます.)
配列内のすべての要素を最初から最後まで1つずつ取り出し、コールバック関数を繰り返し呼び出し、コールバック関数の実行結果を収集して新しい配列を作成します.
コールバック関数の最初のパラメータには現在の値が含まれ、2番目のパラメータには現在の値インデックスが含まれ、3番目のパラメータには配列全体が含まれます.
💻 map関数を直接実現しましょう
Array.prototype.map = function (callback, thisArg) {
let mapArr = [];
for (let i = 0; i < this.length; i ++) {
let mapValue = callback.call(thisArg || window, this[i], i, this);
mapArr[i] = mapValue;
}
return mapArr;
}
2πコールバック可能な関数は関数である. let obj = {
vals: [1,2,3],
logValues: function(v,i) {
console.log(this,v,i);
}
}
[4,5,6].forEach(obj.logValues);
obj.logValueはobjオブジェクトのメソッドとして定義される.このメソッドをforEach関数のコールバック関数として渡します.
objを使う方法を直接伝えるのではなく、objです.valuesが指す関数のみが渡されます.
したがって、objと直接関連付けられていないため、グローバルオブジェクトの表示につながります.
オブジェクトのメソッドを関数のパラメータに渡しても、最終的にはメソッドではなく関数にすぎません.
📝 コールバック関数で特定のthisをバインドする場合はbindメソッドを使用します.
[4,5,6].forEach(obj.logValues.bind(obj)); //obj 객체를 this로 바인딩한 경우
3πコール地獄と非同期制御地獄
コールバック関数を匿名関数に渡すプロセスを繰り返し、コードのインデント深さに耐えられない
通常、イベント処理やサーバ通信などの非同期タスクを実行する場合に発生します.
🚀 例題を通じてcallback地獄から釈放する方法を理解しましょう.
💣 地獄
setTimeout(function (val) {
let text = val;
setTimeout(function(val) {
let text += val;
setTimeout(function(val) {
let text += val;
console.log(text); // aabbcc
}, 10, 'cc' )
}, 10, 'bb' )
}, 10, 'aa')
settimeoutコールバックでsettimeoutを使用してコールバックを複数回ネストします.デップはますます深くなって、あなたの毒性は最も悪い!!⚠️⚠️⚠️
💡 コールバック地獄解決1-変換記名関数
let text = '';
const test1 = function(val) {
text += val;
setTimeout(test2, 10, 'bb')
}
const test2 = function(val) {
text += val;
setTimeout(test3, 10, 'cc')
}
const test3 = function(val) {
text += val;
console.log(text); //aabbcc
}
test1('aa');
記名関数の使用は可読性の問題をある程度解決したようだが,同様に使い捨て関数を複数回使用するため面白くない.💡 callback地獄解決2-Promise
const test = function (name) {
return function(prev = '') {
return new Promise(function(resolve) {
setTimeout(function() {
let text = prev + name;
resolve(text);
}, 10)
})
}
}
test('aa')()
.then(test('bb'))
.then(test('cc')); // aabbcc
ES 6のPromiseを利用する方法です.new演算子とともに呼び出されたPromiseパラメータに渡されるコールバック関数は、呼び出されるとすぐに実行されますが、resolve、execute関数の内部に構文がある場合、そのうちの1つが実行されるまでthenまたはエラー構文(catch)には移動しません.
💡 callback地獄解決3-Generator
const test = function (prev, name) {
setTimeout(function() {
testGenerator.next(prev+name);
}, 10);
}
const generator = function* () {
let test1 = yield test('', 'aa');
let test 2 = yield test(test1, 'bb');
let test3 = yield test(test2, 'cc');
}
const testGenerator = generator();
testGenerator.next();
ES 6のジェネレータを使用しました.*付きの関数はジェネレータです.generator関数を実行してiteratorを返します.iteratorにはnextというメソッドがあります.
nextメソッドを呼び出すと、generator関数の内部に最初に現れた完成品で関数の実行が停止します.
nextメソッドが再び呼び出されると、前に停止した部分から開始し、表示された完成品で関数の実行を停止します.
すなわち、非同期操作が完了したときにnextが呼び出されると、ジェネレータ関数の内部ソースは上から下へ順に実行されます.
💡 コール地獄解決4-Promise+Async/Await
const test = function(name) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(name);
}, 10);
})
}
const maker = async function() {
let text = '';
let addText = async function (name) {
text += test(name);
}
await addText('aa')
await addText('bb')
await addText('cc')
console.log(text); // aabbcc
}
ES 8のasync/awaitを使用しました.非同期操作を実行する関数の前にasyncをマークし、関数の内部に実際の非同期操作が必要な各位置にawaitをマークするだけで、後の内容を自動的にpromiseに変換できます.
この内容が解決してから、次のステップに進むことができます.
すなわち,承諾したthenのような効果を得ることができる.
📚 整理する
📌 コールバック関数は、パラメータを他のコードに渡し、同時に制御権を委任する関数です.
📌 制御権を受け取ったコードは、コールバック関数が呼び出された時点を自動的に判断します.
📌 制御権を渡すコードは、コールバック関数を呼び出すと、パラメータに渡される値の順序が決定されます.
📌 制御権を受け入れるコードは、コールバック関数のthisが何を望んでいるかを決定することができる.(bindメソッド)
📌 メソッドをパラメータとしてどの関数に渡しても、最終的には関数として実行されます.
📌 非同期制御のためにコールバック関数を使用すると、コールバック地獄に陥る.ソリューションにはPromise、Generator、async/awaitなどがあります.
Reference
この問題について(Core JavaScript-04.コールバック関数), 我々は、より多くの情報をここで見つけました https://velog.io/@iamjoo/코어-자바스크립트-04.-콜백함수テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol