Today I Learned
- javascript 심화 강의 수강 - this, 콜백 함수
- DOM 기초 특강 수강
javascript 심화 강의 - THIS
NodeList에 배열 메서드를 적용
document.body.innerHTML = `<div>A</div><div>B</div><div>C</div>`;
var nodeList = document.querySelectorAll('div');
console.log(nodeList)
// 유사배열객체
// {
// 0: div,
// 1: div,
// 2: div,
// length: 3
// }
var nodeArr = Array.prototype.slice.call(nodeList);
nodeArr.forEach(function(node) {
console.log(node);
// <div>A</div>
// <div>B</div>
// <div>C</div>
});
여러 인수를 묶어 하나의 배열로 전달할 때 apply 사용
var numbers = [10, 20, 3, 16, 45];
var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);
console.log(max, min); // 45 3
bind 메서드
call과 비슷하지만 즉시 호출하지는 않고 넘겨받은 this 및 인수들을 바탕으로 새로운 함수를 반환하는 메서드
이미지 출처 https://medium.com/@yejinh/개념-이해-bind-메소드-e76b9ced897
var func = function (a, b, c, d) {
console.log(this, a, b, c, d);
};
var bindFunc = func.bind({ x:1 }, 4, 5);
console.log(func.name); // func
console.log(bindFunc.name); // bound func
bind 메서드를 적용해서 새로 만든 함수는 name 프로퍼티에 ‘bound’ 라는 접두어가 붙음 (추적하기가 쉬움)
상위 컨텍스트의 this를 내부 함수나 콜백 함수에 전달하기
1. 내부함수
a. 메서드의 내부 함수에서 메서드의 this를 그대로 사용하기 위한 방법
b. self 등의 변수를 활용한 우회법보다 call, apply, bind를 사용하면 깔끔하게 처리 가능
var obj = {
outer: function() {
console.log(this); // this는 obj
var innerFunc = function () {
console.log(this);
};
innerFunc.call(this); // this는 obj
}
};
obj.outer();
var obj = {
outer: function() {
console.log(this); //obj
var innerFunc = function () {
console.log(this); // obj
}.bind(this); // this에 obj를 바인딩
innerFunc();
}
};
obj.outer();
2. 콜백 함수
a. 콜백 함수도 함수이기 때문에, 함수가 인자로 전달될 때는 함수 자체로 전달 (this가 유실됨)
b. bind메서드를 이용해 this를 입맛에 맞게 변경 가능
var obj = {
logThis: function () {
console.log(this);
},
logThisLater1: function () {
setTimeout(this.logThis, 500);
},
logThisLater2: function () {
setTimeout(this.logThis.bind(this), 1000);
}
};
obj.logThisLater1(); // obj를 잃어버림 - 정상 동작X
obj.logThisLater2(); // bind 메서드 이용하여 this는 obj - 정상 동작O
화살표 함수의 예외사항
i. 화살표 함수는 실행 컨텍스트 생성 시, this를 바인딩하는 과정이 제외
ii. 이 함수 내부에는 this가 아예 없으며, 접근코자 하면 스코프 체인상 가장 가까운 this에 접근하게 됨
iii. this우회, call, apply, bind보다 편리한 방법
var obj = {
outer: function () {
console.log(this);
var innerFunc = () => {
console.log(this);
};
innerFunc();
};
};
obj.outer();
javascript 심화 강의 - 콜백 함수
콜백 함수란?
a. 다른 코드의 인자로 넘겨주는 함수
b. 콜백 함수를 넘겨받은 코드는 이 콜백 함수를 필요에 따라 적절한 시점에 실행 (제어권)
콜백 함수는 다른 코드(함수 또는 메서드)에게 인자로 넘겨줌으로써 그 제어권도 함께 위임한 함수. 콜백 함수를 위임받은 코드는 자체적으로 내부 로직에 의해 이 콜백 함수를 적절한 시점에 실행.
var count = 0;
var cbFunc = function () {
console.log(count);
if (++count > 4) clearInterval(timer);
};
// 0.3초 마다 반복하면서 callback함수(cbFunc) 안에 있는 것을 실행함
var timer = setInterval(cbFunc, 300);
// 실행 결과
// 0 (0.3sec)
// 1 (0.6sec)
// 2 (0.9sec)
// 3 (1.2sec)
// 4 (1.5sec)
호출 주체 | 제어권 | |
cbFunc( ) | 사용자 | 사용자 |
setInterval(cbFunc, 300) | setInterval | setInterval |
map 함수
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 ]
map : 배열의 모든 요소를 꺼내어 처음부터 끝까지 콜백 함수 반복 호출 + 새로운 배열 리턴
callback: function(currentValue, index, array)
this의 제어권
i. 콜백 함수도 함수이기 때문에 기본적으로는 this가 전역 객체를 참조
ii. 제어권을 넘겨받을 코드에서 콜백 함수에 별도로 this가 될 대상을 지정한 경우 에는 그 대상을 참조
콜백 함수 내부의 this에 다른 값 바인딩하기
가장 좋은 방법 → bind메서드의 활용
var obj1 = {
name: 'obj1',
func: function () {
console.log(this.name);
}
};
//함수 잡채를 obj1에 바인딩
setTimeout(obj1.func.bind(obj1), 1000);
var obj2 = { name: 'obj2' };
//함수 잡채를 obj2에 바인딩
setTimeout(obj1.func.bind(obj2), 1500);
동기와 비동기
동기 : synchronous
현재 실행 중인 코드가 끝나야 다음 코드를 실행하는 방식
비동기 : a + synchronous ⇒ async
1. 실행 중인 코드의 완료 여부와 무관하게 즉시 다음 코드로 넘어가는 방식
2. setTimeout, addEventListner 등
3. 별도의 요청, 실행 대기, 보류 등과 관련된 코드는 모두 비동기적 코드
콜백 지옥 해결 방법
콜백 지옥이란? 콜백 함수를 익명 함수로 전달하는 과정이 반복되어 코드의 들여 쓰기 수준이 헬 수준인 경우
비동기 작업의 동기적 표현 - Promise
var addCoffee = function (name) {
return function (prevName) {
return new Promise(function (resolve) {
setTimeout(function () {
var newName = prevName ? (prevName + ', ' + name) : name;
console.log(newName);
resolve(newName);
}, 500);
});
};
};
addCoffee('에스프레소')()
.then(addCoffee('아메리카노'))
.then(addCoffee('카페모카'))
.then(addCoffee('카페라떼'));
new 연산자로 호출한 Promise의 인자로 넘어가는 콜백은 바로 실행된다. 그 내부의 resolve (또는 reject) 함수를 호출하는 구문이 있을 경우 resolve (또는 reject) 둘 중 하나가 실행되기 전까지는 다음(then), 오류(catch)로 넘어가지 않는다. 따라서 비동기 작업이 완료될 때 비로소 resolve, reject를 호출하는 방법으로 비동기 작업의 동기적 표현이 가능하다.
비동기 작업의 동기적 표현 - Promise + Async/await
var addCoffee = function (name) {
return new Promise(function (resolve) {
setTimeout(function(){
resolve(name);
}, 500);
});
};
var coffeeMaker = async function () {
var coffeeList = '';
var _addCoffee = async function (name) {
coffeeList += (coffeeList ? ', ' : '') + await addCoffee(name);
};
await _addCoffee('에스프레소');
console.log(coffeeList);
await _addCoffee('아메리카노');
console.log(coffeeList);
await _addCoffee('카페모카');
console.log(coffeeList);
await _addCoffee('카페라떼');
console.log(coffeeList);
};
coffeeMaker();
비동기 작업을 수행코자 하는 함수 앞에 async, 함수 내부에서 실질적인 비동기 작업이 필요한 위치마다 await를 넣으면 Promise ~ then과 동일한 효과를 얻을 수 있다.
회고
드디어 DOM을 이해했다!!!!! 그동안 DOM은 HTML과 관련이 있는 것인데 JS를 통해 HTML의 내부의 어떤 요소를 수정하거나 추가, 삭제할 수 있다 정도로만 이해했었는데 오늘 원장님의 특강을 들으면서 명확하게 그 개념을 이해할 수 있었다. 거기다가 queryselector도 어떻게 사용하는지 실습을 통해서 많이 배웠다.
반면에 자바스크립트 심화 강의는 진도를 잘 못 나가고 있는데, 대부분의 내용을 이해하지 못하는데도 강의를 계속 듣는 게 시간 낭비는 아닐까 걱정이 되기도 한다. 짧은 시간에 apply, call, slice, bind, this, 콜백 함수 등등 너무 많은 내용이 쏟아져서 돌아서면 금방 까먹게 되고 내가 이걸 실전에서 사용할 수 있을지 잘 모르겠다. 일단은 한 챕터만 남겨두고 있기 때문에 내일 빨리 다 들을 예정인데 리액트 강의가 다음 주로 미뤄져서 남는 시간 동안 뭘 할지도 고민이다. 원래는 주말 동안 이번 주에 끝난 팀 프로젝트 웹 페이지를 수정해 볼 생각이었는데 자바스크립트 강의를 구매해서 듣는 선택지도 고려하고 있다.
원장님 강의 보다가 굉~장히 사소한 꿀팀 알아 냄. console.log 쉽게 입력하기.