Conversation
Q1. 다음 코드를 바탕으로 이어지는 질문에 대답하시오.(a) 코드의 실행 결과와 그 이유를 간략히 서술하시오. 실행 결과는 다음과 같다. { name: 'JISUNG', printName: f }
callback's this.name: SOHYUN
{ name: 'NAEUN', printName: f }
callback's this.name: SOHYUN먼저 코드를 보면, 전역 변수 name은 'SOHYUN'이고, person 객체 안에는 name: 'JISUNG'과 printName 메서드가 정의되어 있다. 여기서 핵심!!!!!!은 콜백 함수 내부의 this가 무엇을 가리키는가이다. 요 과정을 순서대로 보자면
(b) 위 코드가 문맥에 맞게 동작할 수 있도록 (= 콜백 함수가 헬퍼 함수의 역할을 제대로 수행할 수 있도록) 수정하시오. 콜백 함수가 헬퍼 함수의 역할을 제대로 수행할 수 있도록 수정하려면, setTimeout 내부의 콜백 함수가 printName 메서드의 문맥(this)을 그대로 유지해서, person이든 anotherPerson이든 자신이 속한 객체의 name을 출력하게 만들어야 한다!! 이는 화살표 함수를 사용하면 해결 된다. printName() {
console.log(this);
setTimeout(() => {
console.log("callback's this.name:", this.name);
}, 100);
}화살표 함수는 자신만의 this를 가지지 않고, 바깥 스코프(printName의 this)를 그대로 사용하므로 올바르게 동작할 것이다. Q2. OX 문제(1) 자바스크립트의 모든 함수는 상위 스코프를 기억하므로 일반적으로 모든 함수를 클로저라고 칭한다. (X)
(2) 자바스크립트 객체의 모든 프로퍼티와 메서드는 기본적으로 public하다. (O) Q3. 다음 코드를 바탕으로 이어지는 질문에 대답하시오.(떡국 제가 만들어드릴게요;; 멍청한 렉시컬 환경!!) 하은이가 기대한 대로 나이의 증감이 서로 연동되지 않는 이유는, getOlder와 getYounger가 서로 다른 렉시컬 환경을 가지고 있기 때문이다. 함수 createAgeTracker는 호출될 때마다 새로운 실행 컨텍스트와 렉시컬 환경을 생성한다. 그런데 문제는, createAgeTracker가 두 번!! 호출되고 있다는 점이다!!!! const getOlder = createAgeTracker(eatTteokguk);
const getYounger = createAgeTracker(undoEatingTteokguk);이렇게 하면 getOlder는 첫 번째 createAgeTracker 호출에서 만들어진 렉시컬 환경을, getYounger는 두 번째 호출에서 만들어진 완전히 별개의 렉시컬 환경을 참조하게 된다. 즉, 두 함수는 각각 자신만의 독립된 age 변수를 가진 클로저가 되는 것이다. 결과적으로 getOlder를 여러 번 호출해 나이가 증가하더라도, getYounger가 참조하는 age는 그와는 전혀 다른, 초기값 23을 갖는 또 다른 변수를 바라보기 때문에 두 함수 간의 나이 변화가 연동되지 않는다. 이 문제를 해결하려면, 두 함수가 하나의 동일한 age 변수를 공유하도록 해야 한다. createAgeTracker가 두 번 호출될 때마다 새로운 렉시컬 환경을 만들지 않도록 하나의 공통된 클로저 환경을 가지게 만들어야 한다. 이를 위해 즉시 실행 함수를 이용할 수 있다. Q4. 코드를 바탕으로 이어지는 질문에 대답하시오.위 코드에서 clickHandler 함수가 props.id 값을 정상적으로 참조할 수 있는 이유를 컴포넌트 렌더링 시점과 이벤트 발생 시점으로 나누어 상세히 설명하시오.결론부터 말하자면 클로저 덕분에 렌더링 시점의 변수 값이 이벤트 발생 시점에도 유지되어 접근 가능한 것이다. 먼저, 렌더링 시점에 React는 Button 컴포넌트를 호출하여 JSX를 해석하고, 그 과정에서 함수 내부의 모든 변수와 함수 선언이 평가된다. 이때 props는 부모 컴포넌트로부터 전달된 인자 값으로, clickHandler 함수는 props 변수를 자신의 상위 스코프에서 참조하는 클로저로서 정의된다. 즉, clickHandler는 만들어질 때 이미 자신이 참조해야 할 props가 포함된 렉시컬 환경을 기억하게 된다!! 그다음, 이벤트 발생 시점에 사용자가 버튼을 클릭하면, React는 이전에 등록된 clickHandler를 호출한다. 이때 clickHandler 함수는 새로 정의되는 것이 아니라, 렌더링 시점에 생성되어 기억하고 있던 그 동일한 함수!!!!!다. 결국 clickHandler가 별도로 props를 전달받지 않았음에도 정상적으로 props.id 값을 출력할 수 있는 이유는, 이 함수가 컴포넌트 렌더링 시점의 스코프를 클로저로서 기억하고 있기 때문이다. 즉, 렌더링 시점에는 props가 함수의 상위 스코프에 존재하고, 이벤트 발생 시점에는 clickHandler가 그 렉시컬 환경을 통해 props.id를 안정적으로 참조하게 된다. |
(a)
추가적으로 setTimeout 의 콜백은 태스크 큐에 들어가고 이벤트 루프에 의해 실행되어 콜 스택이 비워진 후 마지막에 처리되어 5, 6 제일 마지막에 처리되어 log 출력 (b) 위 코드가 문맥에 맞게 동작할 수 있도록 (= 콜백 함수가 헬퍼 함수의 역할을 제대로 수행할 수 있도록) 수정하시오. ...
// bind를 활용한다.
const person = {
name: 'JISUNG',
printName() {
console.log(this);
setTimeout(function () {
console.log("callback's this.name: ", this.name);
}.bind(this), 100); // bind를 통한 this 바인딩
},
};
// 2. 화살표 함수를 활용한다.
const person = {
name: 'JISUNG',
printName() {
console.log(this);
setTimeout(() => {
console.log("callback's this.name: ", this.name);
}, 100);
},
};
...
// 불필요한 console.log 제거
person.printName();
anotherPerson.printName();
이유 해결방법
const counter = (function createAgeTracker(ageModifier) {
let age = 23;
return {
eatTteokguk: function () {
return ++age;
},
undoEatingTteokguk: function () {
return --age;
},
};
})();
console.log(counter.eatTteokguk());
console.log(counter.eatTteokguk());
console.log(counter.eatTteokguk());
console.log(counter.eatTteokguk());
console.log(counter.undoEatingTteokguk());
console.log(counter.undoEatingTteokguk());
console.log(counter.undoEatingTteokguk()); // 하은의 기대: 24클래스 static 활용도 가능
class Counter {
static #age = 23;
static eatTteokguk() {
return ++this.#age;
}
static undoEatingTteokguk() {
return --this.#age;
}
}
console.log(Counter.eatTteokguk());
console.log(Counter.eatTteokguk());
console.log(Counter.eatTteokguk());
console.log(Counter.eatTteokguk());
console.log(Counter.undoEatingTteokguk());
console.log(Counter.undoEatingTteokguk());
console.log(Counter.undoEatingTteokguk());
|
Q1. 다음 코드를 바탕으로 이어지는 질문에 대답하시오.(a) 코드의 실행 결과와 그 이유를 간략히 서술하시오. { name: 'JISUNG', printName: [Function: printName] }
callback's this.name: SOHYUN
{ name: 'NAEUN', printName: [Function: printName] }
callback's this.name: SOHYUN
하지만 setTimeout 내부의 콜백은 일반 함수로 호출되므로, this 전역 객체를 가리킴(sohyun)
그러나 setTimeout 콜백은 전역에서 실행되어 sohyun (b) 위 코드가 문맥에 맞게 동작할 수 있도록 (= 콜백 함수가 헬퍼 함수의 역할을 제대로 수행할 수 있도록) 수정하시오. setTimeout(() => {
console.log("callback's this.name:", this.name);
}, 100);Q2. OX 문제(1) 자바스크립트의 모든 함수는 상위 스코프를 기억하므로 일반적으로 모든 함수를 클로저라고 칭한다. (X) (2) 자바스크립트 객체의 모든 프로퍼티와 메서드는 기본적으로 public하다. (O) Q3. 다음 코드를 바탕으로 이어지는 질문에 대답하시오.function createAgeTracker(ageModifier) {
let age = 23;
return function () {
age = ageModifier(age);
return age;
};
}
function eatTteokguk(curAge) {
return ++curAge;
}
function undoEatingTteokguk(curAge) {
return --curAge;
}
const getOlder = createAgeTracker(eatTteokguk);
const getYounger = createAgeTracker(undoEatingTteokguk);
console.log(getOlder());
console.log(getOlder());
console.log(getOlder());
console.log(getOlder());
console.log(getYounger());
console.log(getYounger());
console.log(getYounger()); // 하은의 기대: 24하은이는 먹은 떡국 그릇 수만큼 나이를 먹는다는 말에 속아, 코드 상에서라도 자신의 나이를 되돌리기 위해 떡국을 먹기 전으로 돌아갈 수 있는 프로그램을 만들고 싶었다. 그러나 하은의 기대와 달리 나이의 증감이 연동되지 않는 문제점이 발생하였다. 우울해하는 하은을 위해 문제점이 발생한 이유와 해결 방법을 서술하시오. 실행결과 24
25
26
27
22
21
20getOlder와 getYounger은 각각 독립된 실행 컨텍스트에서 생성된 별개의 클로저 해결 방법 function createAgeTracker() {
let age = 23;
return {
getOlder() {
age++;
return age;
},
getYounger() {
age--;
return age;
}
};
}
const tracker = createAgeTracker();
console.log(tracker.getOlder()); // 24
console.log(tracker.getOlder()); // 25
console.log(tracker.getYounger()); // 24Q4. 코드를 바탕으로 이어지는 질문에 대답하시오.위 코드에서 렌더링 시점 이벤트 발생 시점 사용자가 버튼을 클릭하면 clickHandler가 실행. |
Q1. 다음 코드를 바탕으로 이어지는 질문에 대답하시오.(a)
(b) setTimeout(() => {
console.log("callback's this.name: ", this.name);
}, 100);
혹은
setTimeout(function() {
console.log("callback's this.name: ", this.name);
}.bind(this), 100);Q2. OX 문제(1) X (2) O Q3. 다음 코드를 바탕으로 이어지는 질문에 대답하시오.getOlder와 getYounger가 서로 다른 렉시컬 환경을 가지기 때문에, 같은 age를 공유하지 않아 기대하는 값인 24가 출력되지 않는다. 즉시 실행 함수를 사용해 age 변수를 한 번만 생성해 동일한 age를 공유하도록 하는 방식으로 해결할 수 있다. Q4.코드를 바탕으로 이어지는 질문에 대답하시오.
|
Q1. 다음 코드를 바탕으로 이어지는 질문에 대답하시오.
(a) 코드의 실행 결과와 그 이유를 간략히 서술하시오.
(b) 위 코드가 문맥에 맞게 동작할 수 있도록 (= 콜백 함수가 헬퍼 함수의 역할을 제대로 수행할 수 있도록) 수정하시오.
Q2. OX 문제
(1) 자바스크립트의 모든 함수는 상위 스코프를 기억하므로 일반적으로 모든 함수를 클로저라고 칭한다. (O/X)
(2) 자바스크립트 객체의 모든 프로퍼티와 메서드는 기본적으로 public하다. (O/X)
Q3. 다음 코드를 바탕으로 이어지는 질문에 대답하시오.
하은이는 먹은 떡국 그릇 수만큼 나이를 먹는다는 말에 속아, 코드 상에서라도 자신의 나이를 되돌리기 위해 떡국을 먹기 전으로 돌아갈 수 있는 프로그램을 만들고 싶었다.
그러나 하은의 기대와 달리 나이의 증감이 연동되지 않는 문제점이 발생하였다. 우울해하는 하은을 위해 문제점이 발생한 이유와 해결 방법을 서술하시오.
Q4. 코드를 바탕으로 이어지는 질문에 대답하시오.
위 코드에서
clickHandler함수가props.id값을 정상적으로 참조할 수 있는 이유를 컴포넌트 렌더링 시점과 이벤트 발생 시점으로 나누어 상세히 설명하시오.