코더
자바스크립트 심화문법 본문
1.이벤트 루프
호출스택 <==이벤트루프 <== 테스트 큐 <== 백그라운드
호출스택은 동기코드를 담당한다
이벤트루프는 비동기코드를 담당한다.
테스트 큐는 실행돼야 할 콜백 함수(나중에 호출되는 함수)들이 대기하는 곳이다.
백그라운드는 타이머,이벤트 리스너 저장하는 공간이다.
chrome브라우저는 소스코드가 실행되는 순간에 하나의 함수가 실행된다고 보고 anonymous라는 함수로 표기한다.( 호출스택은 역순으로 출력되기 때문에 실행을 하면 anonymoous가 가장 나중에 표시되는 것을 알 수있다.)

여기서 발생하는 문제는 2,5가 같은색이면 뒤집어 지고 8,9가 같은 색이면 뒤집어 진다고 생각 할 수 있는데 그렇지 않다.
( 그 이유는 2,5,8,9가 이미 클릭을 통해 테스트 큐로 넘어간 상태이기 때문에 순차적으로 일을처리 하는 호출스택의 입장에서는 2,5,8,9가 한번에 넘어오고 그제서야 clicked = [];가 발생한다고 입력이 들어오기 때문에 8,9는 안뒤집어지는 오류가 생겨날수있다 . 즉, 이현상을 고치기 위해서는 clickable = false;라는 코드를 if (firstBaclcolor === secondBackColor) 뒤에 넣어준다)
2.렉시컬스코프
스코프는 함수를 호출할 때가 아니라 선언할 때 생긴다( 함수를 처음 선언하는 순간, 함수 내부의 변수는 자기 스코프로부터 가장 가까운 곳(상위 범위에서)에 있는 변수를 계속 참조하게 된다.)
var name = 'zero';
function log() {
console.log(name);
}
function wrapper() {
name = 'nero';
log();
}
wrapper();
의 값은 nero이다. 하지만
var name = 'zero';
function log() {
console.log(name);
}
function wrapper() {
var name = 'nero';
log();
}
wrapper();
의 값은 zero이다.(첫번째 예시는 name='nero';에서 name의 값이 없으니 전역변수에서 값을 찾아 zero의 값을 nero로 바꿔준 것이고 두번째 예시의 var name = 'nero';는 지역변수로서 새로운 name의 변수를 생성한 것이닌 log(); 함수를 부를때 우선권을 가진 전역변수 값인 var name='zero'; 를 불러서 출력시키는 것임 )
3.스코프체인(특정 함수에서 어떠한 값에 접근 할 수 있는지) <=선언에 영향을 받는다.

예를 들어 function a()안에 있는 값의 console.log(x)의 값을 찾으려고 할 때 anonymous까지 갈필요없이 바로 a에 대해 접근이 가능함으로 값은 x2가 나오는것이다.
호이스팅: JavaScript에서 변수 및 함수 선언이 코드의 맨 위로 끌어올려지는 현상을 말한다.<=템페럴 데드 존은 함수내부에서 영향을 받지 않는다.(위의 예제에서 호이스팅이 되면 함수 선언이 변수 선언보다 우선권을 가지기 때문에 annoy => c,a,x 로 적히는게 맞다)
4.this는 함수가 호출될 때 결정된다.
1.앞에 객체가 붙어서 호출되는 경우
2.new를 붙혀서 호출하는 경우
3.bind(),apply,call을 통해 this를 직접적으로 바꿔주는경우
ex)
function Human(name){
this.name = name;
}
new Human('kim');
ex)
function add(a,b) { return a+b }
add.apply(null,[1, 2]);
add.call(null, 1, 2);
add.bind(null,1,2)();
화살표함수는 부모함수의 this를 그대로 가지고 온다.(아래 첫번째 예시만 부모함수의 this를 그대로 가지고 옴)
ex)
sayname: () => {
}
sayname() {
}
sayname: function() {
}
addEventListener의 this는 window를 가르키지 않고 앞에 변수를 this의 값으로 바꿔준다.
5. promise
promise는 내용은 이미 실행이 되었지만 결과가 반환이 되지 않는 객체
-then을 붙이면 결과를 반환한다.
-실행이 완료되지 않았으면 완료된 후에 then 내부 함수가 실행된다.
-resolve('성공리턴값'); => then으로 연결
-reject('실패리턴닶'); => catch로 연결
-Finally 부분은 무조건 실행됨
-Promise.resolve : 바로 resolve하는 프로미스
-Promise.reject : 바로 reject하는 프로미스
ex)
const condition = true;
const promise = new Promise((resolve, reject) => {
if (condition) {
resolve('성공');
} else {
reject('실패');
}
});
promise
.then((message) => {
console.log(message);
})
.catch((error) => {
console.error(error);
});
promise.all(배열)
여러 개의 프로미스들을 동시에 수행한다.
-하나라도 실패하면 catch로 간다
-allSettled로 실패한것만 추려 낼 수 있다.
ex)
const Promise11 = Promise.resolve('성공1');
const Promise22 = Promise.resolve('성공2');
promise.all([promise1, promise2])
.then((result) => {
console.log(result);
})
.catch((error) => {
console.log(error);
})
6.async/await
-async function : 변수 = await 프로미스;인 경우 프로미스가 resolve된 값에 저장이 된다. (아래의 예시);
: 변수 await 값;인 경우 그 값이 변수에 저장된다.
ex) 첫번째 예시
const condition = true;
const promise = new Promise((resolve, reject) => {
if (condition) {
resolve('성공');
} else {
reject('실패');
}
});
async function KimHyeonJun() {
try {
const message = await promise;
console.log(message);
} catch (error) {
console.error(error);
}
}
KimHyeonJun() ;
ex) 두번째 예시
function aaa(users) {
users.findeOne({})
.then((user) => {
user.name = 'zero';
return user.save();
})
.then((user) => {
return Users.findOne({ gender : 'm' });
})
를 asyan/awit을 사용해 바꾸어 주면
async fuction Jun(users) {
let user = await users.findOne({});
user.name = 'zero';
user = await user.save();
user = await Users.findOne({ gender : 'm' });
}
for await(변수 of 프로미스배열)
resolve된 프로미스가 변수에 담아 나옴
await을 사용하기 때문에 async가 함수 안에서 해야한다.
const promise1 = Promise.resolve('성공1');
const promise2 = Promise.resolve('성공2');
( async () => {
for await (promise of [ promise1,promise2] ) {
console.log(promise);
}
})();
promise 실전 사용예시
const promise = new Promise((resolve,reject) => {
setTimeout(() => {
resolve();
}, 1000);
});
promise.then((result)=>{
console.log('result', result);
})
7.closure
closure는 함수와 함수외부의 변수의 관계를 말한다.