JS|コールバック関数が返されます🪃

20958 ワード

JavaScriptの開発者であれば、呼吸のようにコールバック関数を使用できます.しかし、本当にコールバック関数が何なのかと聞くと、簡単には答えられない.コールバック関数はAPI通信などの非同期論理を記述する際に必要であるため,これらの概念を理解してこそコードを正確に記述することができる.

コールバック関数


コールバック(callback)は「コールバック」を表します.
すなわち、関数Aが呼び出されると、ある条件が満たされると、関数Bが実行され、自身に通知する要求が発行される.
要求を受けた関数Aは、これらの条件が満たされているか否かを自ら判断し、関数Bを直接呼び出す.
コールバック関数は、別のコードのパラメータとして渡され、「制御権」が同時に委任された関数を指します.
コールバック関数を受信したコードは、内部論理に基づいて適切な時間にコールバック関数を実行します.
💡 パラメータを介して関数の外部からコールバック関数を渡す関数を「高次関数」と呼びます.高次関数にコールバック関数を渡す場合は、関数自体を渡す必要があります.
コールバック関数は,関数式プログラミングモードだけでなく,イベント処理,Ajax通信などの非同期処理の一般的なモードである.

コールバック関数の制御


コールポイント


コールバック関数を渡すコードには、コールバック関数呼び出しポイントの制御権があります.
var count = 0;
var timer = setInterval(function() { // setInterval 함수가 콜백 함수의 제어권을 넘겨받음.
	console.log(count);
	if(++count > 4) clearInterval(timer);
}, 1000);

// 1초 후
// 0
// 1초 후
// 1
// 1초 후
// 2
// 1초 후
// 3
// 1초 후
// 4

けいすう


コールバック関数の制御権を受け入れるコードは、コールバック関数を呼び出すときに、パラメータにどの値をどの順序で渡すかを制御します.
コールバック関数を呼び出すと、パラメータに渡される値とその順序が決定されるので、パラメータを順番に渡す必要があります.
var newArr = [10, 20, 30].map(function(currentValue, index) {
	console.log(currentValue, index);
	return currentValue + 5;
});

console.log(newArr);

// 출력값
// 10 0
// 20 1
// 30 2
// [15, 25, 35]

// ----------------------------------------------------------
// 인자의 순서를 지키지 않은 경우
var newArr2 = [10, 20, 30].map(function(index, currentValue) {
	console.log(index, currentValue);
	return currentValue + 5;
});

console.log(newArr2);

// 출력값
// 10 0
// 20 1
// 30 2
// [5, 6, 7]

this


コールバック関数も関数なので、デフォルトではグローバルオブジェクトを指しますが、コールバック関数に別のターゲットを指定すると、そのターゲットが参照されます.
コールバック関数の内部で別の値を参照する場合は、bindメソッドを使用してこの値にバインドします.
setTimeout(function() {
	console.log(this);
}, 1000);

// Window { ... } 출력

document.body.innerHTML += '<button id="btn">Click</button>';
document.body.querySelector('#btn').addEventListener('click', function() {
	console.log(this);
})

// <button id="btn">Click</button> 출력

// bind 메서드로 this 바인딩
var obj1 = {
	name: 'obj1',
	func: function() {
		console.log(this.name);
	}
}
setTimeout(obj1.func.bind(obj1), 1000);

var obj2 = { name: 'obj2' };
setTimeout(obj1.func.bind(obj2), 2000);

// 1초 후
// obj1 출력
// 1초 후
// obj2 출력

コールバック関数は関数です


コールバック関数を使用してオブジェクトを渡す方法を使用すると、メソッドではなく関数として呼び出されます.
var obj = {
	vals: [1, 2, 3],
	logValues: function(value, index) {
		console.log(this, value, index)
	}
}

obj.logValues(1, 2); // { vals: [1, 2, 3], logValues: f} 1 2 출력
[4, 5, 6].forEach(obj.logValues); // Window { ... } 4 0  Window { ... } 5 1  Window { ... } 6 2 출력

アレイ高次関数


コールバック関数は、非同期処理だけでなく、高次関数を並べ替えるためにも使用されます.
var map = [1, 2, 3].map(function(item) {
	return item * 2;
});

console.log(map); // [2, 4, 6] 출력

var filter = [1, 2, 3].filter(function(item) {
	return item % 2;
});

console.log(filter); // [1, 3] 출력

var reduce = [1, 2, 3].reduce(function(acc, cur) {
	return acc + cur;
}, 0);

console.log(reduce); // 6 출력

コールバック地獄


コールバック関数を匿名関数に渡すプロセスを繰り返し、コードのインデントが深すぎます.
通常、非同期操作を実行するときに発生します.
⑥¥毒性が低いだけでなく、メンテナンスにも不利!
loadScript('1.js', function(error, script) {
  if (error) {
    handleError(error);
  } else {
    // ...
    loadScript('2.js', function(error, script) {
      if (error) {
        handleError(error);
      } else {
        // ...
        loadScript('3.js', function(error, script) {
          if (error) {
            handleError(error);
          } else {
            // ...
          }
        });
      }
    })
  }
});

callback地獄を解決する方法は?

  • 匿名コールバック関数をすべて「記名関数」に変更する方法
  • .
  • Promise(ES6)
  • Generator(ES6)
  • async/await(ES2017)