728x90
📍 14일 차 11.12. 금.(온라인 강의)
오늘은 closure
, arrow-function
, spread operator
, this
등 자바스크립트 동작 원리에 대해서 배웠는데, 아침부터 지금까지 계속 매달리는 중이다. 특히 closure
부분이 조금 어려운데 아무래도 내가 지금까지 잘 사용하지 않았던 문법이어서 그런가 보다. 자주자주 보고 익숙해져야겠다. 그리고 일반 함수와 화살표 함수의 차이는 FE면접에서 몇 번 받았던 질문이다. 그때는 코드의 가독성 부분만 강조했는데 `this`를 예로 들어 설명하면 면접관이 흡족해 하실 것 같다. `arrowFunction`은 선언된 당시의 `this` 값을 유지하기 때문에 `bind`, `call`, `apply`로 바꿀 수 없는 반면 `function`은 누가 호출했는지에 따라서 `this`가 달라진다.
❏ 자바스크립트 함수가 실행되는 과정
- JS의 코드가 없는 경우
// 동작 순서
1. 실행환경(실행 컨텍스트)을 초기화한다.
2. scope는 코드가 현재 실행되는 환경, 맥락(context)을 의미한다.
3. this 포인터, 스코프에 저장된 변수들, 스코프 체인 등이 환경에 포함된다.
4. this 포인터의 경우, 글로벌 스코프에서는 window를 가리킨다.
// GEC에서 실행되는 context
5. this
6. 변수들(Variable Object)
7. Scope
- JS의 코드가 있는 경우
// 1. 함수가 실행되면, 함수 스코프에 따라 환경이 만들어진다.
// 2. this, 함수 스코프의 변수들, 그리고 스코프 체인이 형성된다.
// 3. 스코프 체인을 따라 글로벌 환경에 도달한다.
function myFunc(){
let a = 10;
let b = 20;
function add(first, second){
return first + second
}
return add(a, b);
}
myFunc()
// 4. 객체의 메서드의 경우, 메서드 환경의 this는 해당 객체를 가리키게 된다.
// 5. 하지만 this가 가리키는 것은 환경에 따라 변할 수 있다.
❏ 실행 컨텍스트
JS
동작원리를 파악하기 위해 중요한 개념이다.- 자바스크립트 코드가 실행되는 환경
- 코드에서 참조하는 변수, 객체(함수 포함), this 등에 대한 레퍼런스가 있다.
- 실행 콘텍스트는 전역에서 시작해, 함수가 호출될 때 스택에 쌓이게 된다.
JS
가 실행될 때 전역 실행 콘텍스트(GEC)가 만들어진다.- 함수가 실행될 때 함수 실행 콘텍스트(FEC)가 만들어진다.
let a = 10;
function f1(){
let b = 20;
function print(v){console.log(v)};
function f2(){
let c = 30;
print(a+b+c);
}
f2();
}
f1(); // 60
const o = {
name: "Kim",
changeMyName: function (name) { this.name = name },
};
const o2 = {
name: "Song",
};
function callFuncWithArg(f, arg) {
f(arg);
}
o.changeMyName.bind(o2)("Sam");
console.log("1번 - ", o2.name); // "Sam"
callFuncWithArg(o.changeMyName, "Daniel"); // "Kim"
console.log("2번 - ", o.name);
o.changeMyName("Sam");
console.log("3번 - ", o.name); // "Sam"
728x90
❏ 함수가 호출되는 상황 4가지(dynamic binding
)
- 직접 호출: 함수를 직접 호출한다 (myfunc())
- 메서드 호출: 객체의 메서드를 호출한다.(o.method())
- 생성자 호출: 생성자 함수를 호출한다. (
const p = new Person()
) - 간접 호출:
call
,apply
등으로 함수를 간접 호출한다.(f.call(null, obj)
) - 콜백 함수(특정 동작 이후에 불려지는 함수), 다른 함수의 인자로 보내지는 함수 등
// 직접 호출
function myFunc(){
console.log("my func called");
}
// 메소드 호출
const o = {
name: "AYW",
printName: function(){
console.log(this.name);
}
}
o.printName()
// 생성자 호출
function Person(name){
this.name = name;
this.consoleName = function(){
console.log(this.name);
}
}
const p = new Person("AYW")
console.log(p)
p.consoleName()
setTimeout(p.consoleName.bind(p), 1000); // AYW
❏ this가 가리키는 것
- 함수는 다양한 상황에서 호출될 수 있다.
- 함수의 호출 환경에 따라
this
는 동적으로 세팅된다. this
가 환경에 따라 바뀌는 것을dynamic binding
이라고 한다.bind
,apply
,call
등으로this
를 가리키는 것을 조작할 수 있다.- 일반 함수와 화살표 함수의
this
차이
5-1. 화살표 함수로this
호출 시global
을 가리킨다.
5-2. 일반 함수로this
호출 시 누가 호출했는지에 따라 값이 동적으로 바뀐다.
const o = {
name: "TED",
arrowFunc: () => { console.log(this) },
generalFunc: function(){console.log(this)}
}
o.arrowFunc(); // global
o.generalFunc(); // { name: 'TED', arrowFunc: [Function: arrowFunc], generalFunc: [Function: generalFunc] }
setTimeout(o.arrowFunc, 1000); // global
setTimeout(o.generalFunc, 1000); // global
setTimeout
의this
는global
을 가리킨다.bind
,apply
,call
등의 함수로this
를 조작한다.setTimeout
은 함수 호출과는 다른 콜백 호출이다.printName
메서드는bind
함수를 이용해this
변수가o
를 가리키도록 컨텍스트를 동적 바인딩한다.
const o = {
name: "TED",
printName: function(){console.log("내 이름은" + this.name)},
}
o.printName(); // 내 이름은 TED
setTimeout(o.printName, 1000); // 내 이름은 undefined
setTimeout(o.printName.bind(o), 1000); // 내 이름은 TED
❏ 화살표 함수와 일반 함수의 this
- 화살표 함수의
this
는 호출된 함수를 둘러싼 실행 컨텍스트를 가리킨다. (선언 당시의this
값을 유지한다.this
값을bind
,apply
,call
로 바꿀 수 없다.)this
가 정해지면 바꿀 수 없다.setTimeout
등this
가 바뀌는 상황에서 유용하다. - 일반 함수의
this
는 새롭게 생성된 실행 컨텍스트를 가리킨다. (this
값을bind
,apply
,call
로 바꿀 수 있다.),this
가 바뀌어야 하는 경우는 일반 함수를 사용한다.
const o = {
method(){
console.log(this)
let f1 = function(){console.log(`f1`, this)};
let f2 = () => console.log(`f2`, this)
f1(); // global
f2(); // o
}
};
o.method() // o
window.name = "TED";
const o = {name: "AYW"};
const arrow = (prefix) => console.log(prefix + this.name);
arrow("Dr. "); // Dr. TED
arrow.bind(o)(("Dr. ")); // Dr. TED
arrow.call(o, "Dr. "); // Dr. TED
arrow.apply(o, ["Dr. "]); // Dr. TED
❏ closure
- 일급 객체란? 다른 변수처럼 대상을 다룰 수 있는 것. JS에서 함수는 일급 객체이다. JS에서 함수는 변수처럼 다룰 수 있다.
- 클로저는 함수의 일급 객체 성질을 이용한다.
- 함수가 생성될 때, 함수 내부에서 사용되는 변수들이 외부에 존재하는 경우 그 변수들은 함수의 스코프에 저장한다.
- 함수와 함수가 사용하는 변수들을 저장한 공간을 클로저라 한다.
function add(a, b){
return a+b;
}
[1, 2, 3].reduce(add, 0);
(() => {
console.log("익명 함수를 생성한다.")
})()
function outer(a){
function inner(b){
return a + b
}
return inner(10)
}
// 함수를 변수로 생성한다.
const Person = (name) => {
const printName = () => console.log(name);
return { printName } // 함수를 리턴하며 closure를 생성한다.
}
const person = Person("ted");
person.printName()
function printName(name){
console.log(name)
}
// 함수끼리 비교한다.
// ===의 경우, 변수가 같은 객체(함수)를 가리키는지 체크한다.
console.log(printName === person.printName)
// 클로저 함수 예시
// card1과 card2와 별도의 메모리 공간에 저장된다.
function createCard(){
let title = "";
let content = "";
function changeTitle(text) {title = text};
function changeContent(text) {content = text};
function print(){console.log(title), console.log(content)};
return { changeTitle, changeContent, print };
}
const card1 = createCard();
card1.changeTitle("생일 카드")
card1.changeContent("생일 축하해");
card1.print()
const card2 = createCard();
card2.changeTitle("감사 카드")
card2.changeContent("감사합니다.");
card2.print()
❏ Rest, spread operator
- 함수의 인자, 배열, 객체 중 나머지 값을 묶어 사용하도록 한다.
- 함수의 인자 중 나머지를 가리킨다.
- 배열의 나머지 인자를 가리킨다.
- 객체의 나머지 필드를 가리킨다.
- 함수인자
...arr
은, 인자들을 배열로 묶는다.
// 인자로 들어왔을 때
function findMin(...arr){
return rest.reduce((a, b) => a < b ? a : b)}
}
findMin(7, 3, 5, 2, 4, 1) // 1
// 객체로 사용할 때
const o = {
name: "TED",
age: 23,
job: "zzz"
}
const { name, ...rest } = o;
console.log(rest) // { age: 23, job: 'zzz' }
반응형
'Frontend > 엘리스 SW 엔지니어 트랙' 카테고리의 다른 글
[ 엘리스 SW 엔지니어 트랙 ] 16일차(4주차: 자바스크립트 III - Promise, async / await, API 통신) (0) | 2021.11.16 |
---|---|
[ 엘리스 SW 엔지니어 트랙 ] 15일차 (0) | 2021.11.15 |
[ 엘리스 SW 엔지니어 트랙 ] 13일차 (0) | 2021.11.11 |
[ 엘리스 SW 엔지니어 트랙 ] 12일차 (0) | 2021.11.10 |
[ 엘리스 SW 엔지니어 트랙 ] 11일차(3주차: 자바스크립트 II - DOM, event, this, closure) (0) | 2021.11.09 |
댓글