천진난만 코딩 스토리

2023.02.22) 항해 17일차 본문

TIL(Today I Learned)

2023.02.22) 항해 17일차

Wisdom_1104 2023. 2. 22. 22:06

오늘 공부 내용은 this, 콜백 함수, 클로저이다.

사실 이 세 가지 개념이 모두 어렵다고 생각되었던 내용이기에 쉽지 않았다.

다만 this와 콜백 함수는 강의를 보고 책을 읽다 보니 할만했지만 클로저는......

클로저 공부하는 데에 나머지 두 개념보다 시간을 3~4배는 쓴 듯하다....

사실 아직도 완벽하게 이해했다고 자신 있게 말하기는 어렵다.

어떤 느낌인지 감은 잡았지만 명확하지 않고 두루뭉술한 느낌이다...

이를 위해 모던 자바스크립트 딥다이브 책도 주문하였다.....ㅎ

 

 

 

1) this

  • 자바스크립트에서의 this는 어디서든 사용할 수 있지만,
  • 상황에 따라 this가 바라보는 대상이 달라지는데 엉뚱한 대상을 바라보는 경우도 있다.
  • 함수와 메서드의 구분이 느슨한 자바스크립트에서 this는 실질적으로 이 둘을 구분하는 거의 유일한 기능이다.
  • this는 함수를 호출할 때 결정된다. (this는 실행 컨텍스트가 생성될 때 결정되는데, 실행 컨텍스트는 함수를 호출할 때 생성된다)
  • 함수 호출 방식에 따라 값이 달라진다.

(1) 기본적인 this의 규칙

전역 공간에서 this는 전역 컨텍스트를 생성하는 주체인 전역 객체를 가리킨다.

그렇기에 대부분의 경우에서 전역공간의 '전역변수 a = window a= this.a'가 된다.

예외의 경우는 delete 연산자를 썼을 경우이다. (delete 연산자 = window.delete)

  • 처음부터 전역객체의 프로퍼티로 할당한 경우에는 삭제가 되지만, 전역변수로 선언한 경우에는 삭제가 되지 않는다.
  • 전역변수를 선언하면 자바스크립트 엔진이 이를 자동으로 전역객체의 프로퍼티로 할당하는데,
  • 이때 해당 프로퍼티의 변경 및 삭제 가능성을 false로 정의하기 때문이다.

① 함수와 메서드에서의 this

함수는 그 자체로 독립적인 기능을 수행하고, 메서드는 자신을 호출한 대상 객체에 관한 동작을 수행한다는 차이가 있다.

메서드로 호출 : 점 표기법이나 대괄호 표기법으로 함수를 호출할 때 함수 이름 앞에 객체가 명시되어 있는 경우이다.

함수로 호출 : 메서드로 호출한 경우를 제외한 경우이다.

메서드로 호출하는 경우 this는 함수명 앞의 객체의 정보를 담는데, 점 표기법의 경우에 마지막 점 앞에 명시된 객체가 this이다.

함수로 호출하는 경우 this는 지정되어 있지 않고, 전역 객체를 가리킨다.

화살표 함수는 실행 컨텍스트를 생성할 때 this의 바인딩 과정 자체가 빠지게 되어 상위 스코프의 this를 그대로 사용한다.

콜백함수에서 제어권을 받은 함수에서 콜백함수에 별도로 this가 될 대상을 지정하면 그 대상을 참조하고,

그렇지 않으면 전역 객체를 참조한다.

생성자 함수로 호출된 경우 내부에서의 this는 곧 새로 만들 구체적인 인스턴스 자신이다.

( 생성자는 구체적인 인스턴스를 만들기 위한 일종의 틀이다)

 

(2) 명시적 this 바인딩의 경우 (위의 규칙에 부합하지 않는 경우)

call, apply 메서드는 this를 명시적으로 지정하며 함수나 메서드를 호출하고,

bind 메서드는 this 및 함수에 넘길 인수를 이루 지정하여 새로운 함수를 만들고,

요소를 순회하며 콜백함수를 반복호출하는 일부 메서드는 별도의 인자로 this를 받는다.

 

 

2) 콜백함수

콜백함수는 다른 코드에게 인자로 넘겨줌으로써 그 제어권도 함께 위임한 함수이다.

위임받은 코드는 자체적인 내부 로직에 의해 이 콜백 함수를 적당한 시점에 실행한다.

(callback은 되돌아 호출해 달라는 명령이다)

콜백 함수는 어떤 객체의 메서드를 전달하더라도 그 메서드는 메서드가 아닌 함수로서 호출된다.

어떤 함수의 인자에 객체의 메서드를 전달하더라도 결국 메서드가 아닌 함수다.

객체의 메서드를 콜백 함수로 전달하면 해당 객체를 this로 바라볼 수 없게 된다.

콜백 함수 내부에서 this가 객체를 바라보게 하고 싶다면 bind 메서드를 사용할 수 있다.

 

(1) 콜백 지옥과 동기/비동기

콜백 지옥은 콜백 함수를 익명 함수로 전달하는 과정이 반복되어 코드의 들여 쓰기 수준이 감당하기 힘들 정도로 깊어지는 현상이다.

동기적인 코드는 현재 실행 중인 코드가 완료된 후에나 다음 코드를 실행하는 방식이고,

즉시 처리가 가능한 대부분의 코드이다.

비동기적인 코드는 현재 실행 중인 코드의 완료 여부와 무관하게 즉시 다음 코드로 넘어가고,

별도의 요청, 실행대기, 보류 등과 관련된 코드이다.

① 비동기적인 일련의 작업을 동기적으로 처리해 주는 장치

promise는 new 연산자와 함께 호출한 promise의 인자로 넘겨주는 콜백 함수는 호출할 때 바로 실행되지만,

그 내부에 resolve나 reject 함수를 호출하는 구문이 있을 경우,

둘 중 하나가 실행되기 전까지는 다음(then)이나 오류구문(catch)으로 넘어가지 않는다.

비동기 작업이 완료될 때 비로소 resolve나 reject를 호출하는 방법으로 비동기 작업의 동기적 표현이 가능하다.

asyanc/await비동기 작업을 수행하고자 하는 함수 앞에 async를 표기하고,

함수 내부에서 실질적인 비동기 작업이 필요한 위치마다 await를 표기하는 것 만으로

뒤의 내용을 promise로 자동전환하고 , 해당 내용이 resolve 된 후에야 다음으로 진행한다.

 

 

3) 클로저

(1) 클로저와 LexicalEnvironment

클로저는 함수와 그 함수가 선언될 당시의 LexicalEnvironment의 상호관계에 따른 현상이다.

주로 상태를 안전하게 변경하고 유지하기 위해 사용한다. (의도치 않은 상태의 변경을 막기 위해서)

자바스크립트 엔진은 함수를 어디서 호출했는지가 아니라, 함수를 어디에 정의했는지에 따라 상위 스코프를 결정한다.

LexicalEnvironment의 outerEnvironmentReference에 호출되는 환경과 상관없이 정의된 환경에 대한 정보를 저장한다.

외부 함수보다 중첩 함수가 더 오래 유지되는 경우,

가비지 컬렉터의 동작 방식에 의해 실행 종료된 외부 함수의 변수를 여전히 참조할 수 있도록 한다.

//예제 코드

const x = 1;

function outer() {
    const x = 10;
    const inner = function () { console.log(x) };
    return inner;
}

const innerFunc = outer();
innerFunc();

위의 코드를 보며 설명하자면,

outer 함수를 호출하면 중첩 함수 inner를 반환하게 된다.
그리고 outer 함수의 실행 컨텍스트는 실행 컨텍스트 스탭에서 역할을 다 했기 때문에 제거된다.
inner함수가 innerFunc에 전달되었는데, 이는 outer 함수의 렉시컬환경을 참조하고 있다.
즉, outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 제거되지만,

inner함수에서 outer 함수의 변수를 사용하기에 outer 함수의 렉시컬 환경까지 소멸하는 것은 아니다.

 

(2) 클로저가 아닌 경우

  • 중첩 함수이지만 상위 스코프를 참조하지 않으면 클로저라고 하지 않는다.
  • 중첩 함수이고 상위 스코프를 참조하지만 선언 후 바로 실행하고 소멸하는 경우에는 클로저라고 하지 않는다.

종합해 보자면 클로저가 되려면,

중첩함수이고 상위 스코프의 식별자를 참조하며 outer 함수보다 inner 함수가 더 오래 유지되어야 한다.

 

 

 

 

 

 

 

'TIL(Today I Learned)' 카테고리의 다른 글

2023.02.24) 항해 19일차  (0) 2023.02.24
2023.02.23) 항해 18일차  (0) 2023.02.23
2023.02.21) 항해 16일차  (0) 2023.02.21
2023.02.20) 항해 15일차  (0) 2023.02.20
2023.02.18) 항해 13일차  (0) 2023.02.20