반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- donwstream #upstream #origin
- 코드스테이츠 #알고리즘 #그리디
- 백준 #직각삼각형
- React #Hook rules #Hook 규칙
- raect typescript #react #typescript #styled-component
- React #effect hook #useEffect
- interceptors
- 버블링 #갭쳐링 #이벤트 #JS
- RateLimit
- 이친수
- react #useCallback #react Hook
- React-Query
- useState #Hooks
- React #리액트 이벤트 주기 #리액트 이벤트
- 빡킹독
- 다익스트라 #파티 #백준
- #useRef #언제 쓰는데?
- 플로이드 #c++
- 얕은 복사 #깊은 복사 #shallow copy #deep copy
- React #controlled component #비제어 컴포넌트 #제어 컴포넌트
- rate limit
- html entities
- 노마드 코더 #타입스크립트 #typescript #class
- JWT #토큰 #refreshToken #accessToken #Token #token #localStorage #sessionStorage
- react fragment
- 백준 #적록색약
- DP #c++
- react
- axios
- npm #not being able to find a file #npm install Error
Archives
- Today
- Total
꿈꾸는 개발자
제로초 인간 js 엔진 되기 본문
추가로 학습해야 할 내용들:
- anonnymous 함수에 대한 내용!
- call/bind/apply()에 따른 this의 변환을 조사해라!
- promise의 정적 메소드들 추가 분석하기 (ex Promise.allSettled());
- this에 관한 내용! (화살표 함수의 this는 무조건 부모 값을 받아오는 것이다!)
const obj = {
name: "hoin",
sayName() {
console.log(this.name);
const inner = () => {
console.log(this.name);
};
inner();
},
};
- 위와 같은 경우에는 inner함수 즉 화살표 함수의 경우 내부 this 부모에 binding되어 sayName()과 마찬가지로 부모의 this를 지칭하게 된다!
- 하지만 화살표 외에 다른 방식으로 선언하게 될 경우 inner() 함수의 this는 window를 지칭하게 된다!
- 기억할 점: 항상 this는 호출 할 때 판단해야 한다! => obj.sayName() 이러한 호출과 일반 sayName()의 차이점을 분명히 알아야 한다!
- 위처럼 메소드 호출이라고 하더라도 무조건 객체 그 자체를 지칭하는 것은 아니니 주의하라!
- 분석하기 힘든 this!
- 밑과 같은 상황은 일반적으로 this가 window를 지칭한다고 생각할 수 있지만 실상은 html 태그를 보여준다!!!
- 핵심: this는 함수가 호출 될 때 결정된다=> 밑과 같은 상황에서 addeventlistenr가 호출된 것이지 매개변수로 주어진 함수가 호출된 것이 아니다=> 그래서 this는 addeventlistener함수를 기준으로 판단을 해야 한다!
- 저렇게 칠해진 function만을 보고 파악을 할 수 없다=>이유: 저 function은 호출된 적이 없으니까!
- 밑과 같은 상황은 일반적으로 this가 window를 지칭한다고 생각할 수 있지만 실상은 html 태그를 보여준다!!!
- 저 내부에 있는 function은 우리가 addeventlistner내부에서 호출되는 형태이다!=> 이런 것은 그냥 경험적으로 데이터를 축적해서 아는 방법 말고는 없다! =>
- addeventlistener 매개변수(callback함수로 => 화살표 함수를 사용하게 될 경우
- bind/apply/call=>this를 조작하는 method들이다!
function a() {}
a.bind(window); //여기에서 bind는 a라는 함수의 this를 변경해서 새로운 함수를 반환하는 것이다!
const b = a.bind(window); //여기에서 this가 변경된 함수 a의 reference가 b에 넘어가는 것이다!
console.log(b);
block scope와 매개변수:
- for(let i=0;i<a;i++) 이처럼 소괄호 내에도 scope 안쪽이라고 생각하게 맞다!
- const의 경우 호이스팅이 일어나지만 =>TDZ(temperal dead zone을 만든다!)
const x = true;
const y = false;
function a() {
let a = 4;
y = true;
if (x) {
let a = 3;
for (let i = 0; i < a; i++) {
console.log(i);
}
if (!y) {
kkk();
}
}
z(); //화살표 함수는 호이스팅되지 않기 때문에 에러가 발생한다!
}
a();
//z = () => {}; 이러한 경우에는 호이스팅되지 않기 때문에 위에서 호출했을 때 에러 발생
const z=(a,b)=>a+b;
z(3,5); //8을 return한다!
promise/비동기에 대한 내용을 다루고 있음!
- promise: 실행됐는데 결과값을 나중에 쓸 수 있는 것들을 지칭한다! ==>ex) setTimeout() 등 (callback 함수 아닌가!?!?)
setTimeout(() => {
console.log("a");
}, 1000);
- 위와 같은 경우 console.log('a')가 비동기 callback에 해당한다!!
- callback은 비동기일 수도 아닐 수도 있다=> 비동기 callback이 확실한 비동기이다!
function calculator(callback, a, b) {
return callback(a, b);
}
console.log(calculator(function(a,b){return a+b},3,5));
- 위 코드에서 callback은 비동기가 사용된 게 하나도 없다!
비동기 callback함수의 작동 원리 및 엔진 분석 방법:
//비동기 콜백에 해당한다! event loop를 항상 고려해라!
setTimeout(() => {
console.log("a");
}, 1000);
setTimeout(() => {
console.log("b");
}, 2000); //ms으로 넘어간다! 1000ms===1s이다
setTimeout(() => {
console.log("c");
}, 3000);
//Macro와 micro에 각각 누가 들어가는지 파악을 해야한다!
//promise, process.nextTick =>micro 나머지는 Macro에 들어간다고 보면 된다!
- 위의 방식으로 비동기를 해석하면 된다 항상 Macro와 micro의 차이를 구분할 수 있어야 한다!
Promise의 개념과 주의점:
- 프로미스의 핵심 정리:
- 1. Promise의 핵심: 실행은 바로하되, 결과값을 원할 때 받을 수 있는 클래스이다!
- 2. 비동기는 항상 Call Stack이 비워지는 순간 =>task queue에서 순차적으로 실행되는 것이다
- 3. 한 번 비동기는 영원한 비동기!!!!!!!
- 4. 프로미스는 동시의 문제가 아닌 순서의 문제이다!
- 5. 마이크로에 들어가는 것은 promise, process.nextTick, 나머지는 매크로에 들어감!?(참고 정도!)
- 6. 실행은 바로 --> 결과값이 나올 때는 나중 --> 결과값을 사용할 때는 더 나중
- 7. 실행은 바로 ---> 결과값도 거의 바로 쓰고 싶은데 ---> 그 다음에 결과값이 나오면-->then, await 등은 결과값을 기다린 후 실행된다! (delay가 발생함을 의미한다!)
let a = 2;
const p = new Promise((resolve, reject) => {
//const p가 생성되고, new Promise 생성자의 reference가 p에 저장이 된다
//**new Promise의 call back함수는 바로 호출됨을 기억해라!
//Promise 내부는 동기적 호출이다!
console.log("제일 먼저 실행 된다!");
setTimeout(() => {
a = 5;
console.log("promise 내부", a);
resolve(a); // promise에서 값을 호출하는 것이다!
}, 0);
});
console.log("딴짓");
//eventlistener처럼 생각하는 것이 좋다!(비동기!)
//p then 함수를 호출한 것과 같다!
p.then((result) => {
console.log("promise", result);
});
- call stack포함 모든 것들이 다 empty 되어야 JS 엔진의 마무리 됐다고 정의할 수 있을 것이다!
async await에 대한 이해
p.then((result) => {
console.log("promise", result);
})
.then((result) => {})
.catch(() => {})
.then((rueslt) => {
return Promise.resolve(1); //이런식의 작성도 가능하구나!! java의 static 메소드와 같은 느낌인가!?!
//일반 return 일 경우 return된 값이 그 다음 then의 result로 들어가지만,
//return Promise.resolve(1)의 경우 resolve된 값이 그 다음 then에 들어가게 된다!
})
.then((result) => {
console.log(result); //undefined가 출력된다!
return 1;
})
.then((result) => {
console.log(result); //앞에 return 1이 출력된다!=>.then()도 promise를 return 한다!
})
.catch((error) => {
console.log(error);
})
.finally(() => {
console.log();
});
- promise의 then(), catch()는 try-catch처럼 특정 try를 분할해서 작성해도 무방하다.
- 함수의 return 을 지정하지 않으면 => 기본적으로 함수는 return undefined를 실행하게 된다
- 위 코드와 같은 방식대로 await에서도 동일하게 작동을 한다!
async function a() {
//Promise로의 전환을 잘 할 수 있어야 한다!
const a = await 1; //await -> then 형식으로 전환을 해야 한다!
console.log("a", a);
console.log("hmm");
await null; //await null은 다른 역할을 담당하나?
const b = await Promise.resolve(2);
console.log("b", b);
return b;
//if return a+b일 경우=>then에서는 a를 계속 내려주면서 받아줘야 한다!
}
a();
console.log("\n");
//
Promise.resolve(1) //Promise()은 Promise 생성자를 호출하는 것이고
//Promise.resolve는 정적 메소드를 호출하는 것이다!(둘의 차이점을 구별!)
.then((a) => {
console.log("a", a);
console.log("hmm");
return null;
})
.then(() => {
return Promise.resolve(2);
})
.then((b) => {
console.log("b", b);
return b;
});
- 처음 시작이 await 프로미스가 아닌, 일반 값일 경우 => then에서는 promise만 받을 수 있기 때문에 promise의 정적 메소드를 호출해야 한다!
- 제로초만의 공식: 일반적인 코드는 좌에서 우로 해석을 하지만, await의 변경은 우에서 좌로 해석을 해야함! => await과 await 사이에 있는 것을 하나의 then으로 묶어주면 된다! =>awiat의 방식과 무조건적으로 1대1 대응되는 것은 아니니, 참고사항으로 생각할 것!
- async 함수의 핵심: 함수의 끝은 첫 번째 await이다!(동기 부분의 끝!) => 동기 부분만이 CS에 들어가니까 분석을 빠르게 하기 위해서는 동기 부분을 우선적으로 파악해라!
async function a() {
console.log("2");
const a = await 1;
console.log("4");
console.log("a", a);
console.log("hmm");
await null;
const b = await Promise.resolve(2);
console.log("b", b);
return b;
}
console.log("1");
a();
console.log("3");
- 해당 코드의 실행 순서를 파악할 수 있어야 한다!
//Promise.all(): 비동기를 묶어서 처리를 한다!
async function b() {
await delayp(3000); //3초
await delayp(6000); //6초
await delayp(9000); //9초
//total:18초 소요
}
async function b() {
const p1 = delayp(3000); //3초
const p2 = delayp(6000); //6초
await Promise.all([p1, p2]); //2개를 한 번에 Promise처를 한 것이다!
await delayp(9000); //9초
//total:15초 소요!
}
- 위처럼, await을 난발하기 보다는, 묶어서 처리할 수 있는 부분들은 묶어서 처리하는 것이 좋다! =>그리고 promise는 나중에 원할 때 언제든지 사용할 수 있는 장점이 존재하니 적극 활용을 해라!
- 핵심: 동시에 처리할 수 있는 것은 무조건 동시에 처리를 해라!
async function b() {
const p1 = delayp(3000); //3초
const p2 = delayp(6000); //6초
await Promise.all([p1, p2]); //2개를 한 번에 Promise처를 한 것이다!
await delayp(9000); //9초
//total:15초 소요!
}
new Promise((resolve, reject) => {
const p1 = delayp(3000);
const p2 = delayp(6000);
return Promise.all([p1, p2]);
}).then(() => {
return delayp(9000);
});
- await과 promise의 변환이 자유로워야 한다!
closure에 대한 이해
//클로저에 대한 이해
//밑에 식은 0~4를 출력하는 것이 아닌, 5를 5번 출력하게 된다!
function a() {
for (var i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i);
}, i * 1000);
}
}
a();
//해결법1: var -> let으로(블록 scope으로 전환!)
//해결법2: 즉시실행함수로 감싼다!
function b() {
for (var i = 0; i < 5; i++) {
(function (j) {
setTimeout(() => {
console.log(j);
}, i * 1000);
})(i);
}
}
b();
function c() {
for (let i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i);
}, i * 1000);
}
}
c();
- 총 2가지 해결방식이 있고, 각각의 scope 전환에 대해 면밀하게 파악을 해야 한다!
출처: https://www.youtube.com/playlist?list=PLcqDmjxt30Rt9wmSlw1u6sBYr-aZmpNB3