2024/05/09 자바스크립트 문법 7

YIS·2024년 5월 9일
post-thumbnail

콜백함수와 동기/비동기 처리

콜백함수

다른코드의 인자로 넘겨주는 함수.
콜백함수는 콜백함수를 받는 주체가 있음(forEach,setTimeout등)
콜백함수를 넘겨받은 주체들은 필요에 따라 적절한시점에 콜백함수를 실행
=> 콜백함수에 대한 제어권이 주체들에게 있다.

제어권

1. 호출시점

setInterval : 반복적으로 매개변수로 받은 콜백함수를 수행하는 메서드

var count = 0;
var timer = setInterval(function() { //반복적으로 console.log를 출력함
	console.log(count);				
	if(++count > 4) clearInterval(timer);//count를 증가시키고 그값이
//4보다 크면 clearInterval로 timer를 빠져나옴
}, 300); //0.3초마다 반복실행하라는 호출시점이 setInterval에게 있음
//위와 동일한 코드 
var count = 0; 
var cbFunc = function () {
	console.log(count);
	if (++count > 4) clearInterval(timer);
};
var timer = setInterval(cbFunc, 300);
cbFunc() 

cbFunc()를 직접호출하는 경우 호출주체와 제어권이 사용자
setInterval를 사용하는경우 호출주체와 제어권이 setInterval

2. 인자


var newArr = [10, 20, 30].map(function (currentValue, index) {
	console.log(currentValue, index); //커런트벨류값과 인덱스값이 찍힘.
	return currentValue + 5; //커런트벨류값에 +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; //위치 바꾼 커런트벨류값에 +5하면?
});
console.log(newArr2);
// 10 0
// 20 1
// 30 2
// [ 5, 6, 7 ] 

콜백함수를 넘겨준 코드에게 인자의 순서까지도 제어권이 있음.
제어권이 넘어간 순간 나는 그 제어권을 가친 함수의규칙(여기선map함수)에 맞게 작성해야됨.

3. this(이해못함)

콜백 함수도 기본적으로는 this가 전역객체를 참조.
단 제어권을 넘겨받을 코드에서 콜백 함수에 별도로 this가 될 대상을 지정한 경우에는
그 대상을 참조

map함수를 직접 수동으로 구현한 예시)

Array.prototype.map1 = function(callback, thisArg){ 
  //새로운 map1이라는 메소드를 정의 callback함수와 thisArg를 인자로 받음.
  
  var mappedArr = [];
  //map함수에서 return할, 결과를 저장할 배열
  
  for (var i = 0; i < this.length; i++){
    //this.length는 현재 배열(즉, map1 메소드를 호출한 배열)의 길이를 참조
    var mappedValue = callback.call(thisArg || window || global, this[i]);
    //call 메소드의 첫 번째 인자는 callback 함수 내에서의 this 값을 설정
    //thisArg가 존재하는 경우는 그 객체, 없으면 전역객체
    // thisArg가 제공되면, callback 함수 내에서 this는 thisArg
    // 없으면 window, glocal이 기본값으로 설정, 
    // call의 두 번째 인자는 this가 배열일 것(호출의 주체가 배열이므로)
    //i번째 요소를 넣어서 인자로 전달
    
    mappedArr[i] = mappedValue;
  }
  return mappedArr;
};
var newArr =[1,2,3].map1(function(number){
  return number * 2;
});

console.log(newArr);

중요. 제어권을 넘겨받을 코드에서 콜백 함수에 별도로 this가 될 대상을 시정한경우
그 대상을 참조.

// setTimeout은 내부에서 콜백 함수를 호출할 때, call 메서드의 첫 번째 인자에
// 전역객체를 넘김
// 따라서 콜백 함수 내부에서의 this가 전역객체를 가리킴
setTimeout(function() { console.log(this); }, 300); // Window { ... }

var obj = {name: 'Luton'};
setTimeout(() => { console.log(this.name); }, 300); // 아무 것도 출력되지 않음
//화살표함수 경우 자신을 포함하고 있는 외부 스코프의 this를 상속받는데
//이경우는 obj객체 내부에 있지않으므로 this는 전역객체를 가리킴.
//전역객체에 name이 없으므로 아무것도 출력하지 않음.

var obj = {name: 'Luton'};
setTimeout(function() { console.log(this.name); }.bind(obj), 300); // 'Luton'
//bind 메서드를 사용하여 콜백 함수에서의 this가 obj 객체를 가리키도록 설정



// forEach도 마찬가지로, 콜백 뒷 부분에 this를 명시해주지 않으면 전역객체
[1, 2, 3, 4, 5].forEach(function (x) {
	console.log(this); // Window { ... }
},obj);

var obj = {name: 'John'};
[1, 2, 3, 4, 5].forEach(function (x) {
	console.log(this.name); // 'John'이 5번 출력.
}, obj);


//addEventListener는 내부에서 콜백 함수를 호출할 때, call 메서드의 첫 번째
//인자에 addEventListener메서드의 this를 그대로 넘겨주도록 정의(상속)
//DOM 이벤트 모델에서 this가 항상 이벤트 핸들러가 연결된 요소를 가리킴
//즉 여기서는 id가 'a'인 버튼 요소
document.body.innerHTML += '<button id="a">클릭</button';
document.body.querySelector('#a').addEventListener('click', function(e) {
	console.log(this, e);
});

콜백함수는 함수다

콜백 함수로 어떤 객체의 메서드를 전달하더라도, 그 메서드는 메서드가 아닌 함수로 호출

var obj = {
	vals: [1, 2, 3],
	logValues: function(v, i) {
		console.log(this, v, i);
	}
};

//method로써 호출
obj.logValues(1, 2); //1,2
//이 경우, this는 메서드를 호출한 객체인 obj를 가리킴.

//callback으로서 호출
[4, 5, 6].forEach(obj.logValues);
//obj를 this로 하는 메서드를 그대로 전달한게 아님
//단지, obj.logValues가 가리키는 함수만 전달(obj 객체와 연관없음)
//이경우 this는 전역객체를 가리키고(엄격모드에서는 undefined)v와 i는 각각 배열의 원소와 그 인덱스를 가리킴.

[4, 5, 6].forEach(obj.logValues.bind(obj));
//bind(obj)를 사용하면 logValues 함수는 obj 객체의 컨텍스트에서 실행되어, this가 obj를 가리키게 됨.
profile
엉덩이가 무거운 사람

0개의 댓글