220608 TIL

Parker.Park·2022년 6월 8일
0

TIL

목록 보기
17/39

220608 TIL

오늘은 어제의 작은 궁금증이 나비효과처럼 커졌던 날이다.
220607 TIL 에서 마지막 쯤에 find 메소드에 대해서 MDN을 찾아 보았다. 거기서 thisArg 매개변수가 있었고, 해당 내용에 대해서 몰랐기에, 오늘 찾아 보기로 했다.

매개변수 thisArg

MDN 에서는 '선택 항목. 콜백이 호출될 때 this로 사용할 객체' 로 나와 있었다. 현재까지 알고있는 this는 클래스를 생성하고 constructor를 이용하여 가져오는 this였다. 이 또한 정확히 아는 개념이 아니기도 하다.

이전에 Execution Context를 알아야 했다.

한 블로그에 가보니 먼저 Execution Context에 대해서 설명하였다. 갑작스럽게 많은 정보의 양의 다소 괴로웠다. 실행 컨텍스트라고 하고, 자바스크립트의 코드가 실행하기 위해 음.. 메모리 할당?의 과정이라고 이해했다. 실행 컨텍스트가 let, const, var과 같은 변수 선언 방식이나, scope, hoisting같은 개념을 다 거치기 때문에 미리 숙지해야 할 것들도 많았다.
Scope?
Hoisting?
let, const, var?
다행히도 이전 포스팅으로 어느정도 개념을 알고 들어갔다고 생각했다. 무엇 먼저 이해해야 하는지 헷갈린다 ㅠ. Execution Context의 종류는 3가지라고 한다.

  • Global Execution Context
    전연 Context라고 하고, global object를 생성하며 this값에 global object를 참조한다고 한다. 앱이 종료 될 때 삭제 된다고 한다.
  • Functional Execution Context
    함수가 실행 될 때 정의 된다고 한다. 함수 컨텍스트는 함수가 실행 될 때마다 정의 되며 함수 실행이 종료 되면 Call Stack에서 제거 된다고 한다.
  • Eval Context
    eval함수로 실행한 코드의 context라고 하는데, 앞에 두 context에 대해 중점적으로 다뤄보자.

Call Stack?

javascript 엔진에는 context를 관리하는 목적으로 Call Stack(호출스택)을 갖고 있다고 한다. js는 단일 스레드 형식이기 때문에 런타임에 단 하나의 Call stack을 갖고 있는다고 한다. 코드가 실행 되면 Call Stack 으로 Global Execution Context 를 생성하고 그위에 함수 순서대로 Functional Execution Context를 쌓는 식이라고 한다. 그리고 해당 Functional Execution Context가 끝나면 삭제하는 식으로 이루어진다고 한다. 해당 Stack에는 사이즈가 있어서 최대치를 넘을 경우 'RangeError' 가 뜬다고 한다. 이걸 Stack Overflow라고 한다.

Execution Context의 구성

Execution Context에는 두 가지 구성으로 이루어져 있다고 한다.

  • Lexical Environment
  • Variable Environment
    그리고 Environment들은 공동된 속성을 가지고 있다고 한다.
  • Environment Records
  • Reference to the outer environment

Global Execution Context's Lexical Environment에서 Reference to the outer environment 의 초기값은 null 이라고 한다.
여기서 임의의 function이 실행 된다면 먼저 Functional Execution Context's Lexical Environment를 확인한다고 한다. 다음 변수가 없다면 Functional Execution Context's Lexical Environment에 있는 Reference to the outer environment 를 참조 한다고 하는데 다음 가르키는 곳은 Global Lexical Environment라고 한다.

여기서 조금 이해가 안가는데 Lexical Environment안에 두 개의 속성이 있다고 생각했는데 우선 Lexical Environment를 먼저 확인한다고 하니 헷갈린다.

Environment Record

Environment Record는 Lexical Environment내에 식별자 바인딩을 기록하는 객체라고 한다.
Environment Record에는 세 가지 서브 클래스가 있다고 한다고 한다.

  • Declarative Environment Record
    이곳에 함수와 변수 this, super등의 식별자 바인딩이 저장된다고 한다.
  • Object Environment Record
  • Global Environment Record

다시 Lexical Environment, Variable Environment 그리고 Scope

  • Variable Environment
    var로 선언된 변수가 메모리에 매핑되고, 초기값으로 undefined가 할당된다고 한다. 이건 Hoisting 개념에서 익혔던 것이다.

  • Lexical Environment
    let, const로 선언된 변수가 매핑 된다고 하지만, 초기값은 할당 되지 않는다고 한다.

    여기서 Variable Environment는 Lexical Environment를 상속하는 관계라고 한다. 그래서 둘 다 Lexical Environment라고 말할 수 있다고 한다. 그렇지만 Lexical Environment는 let과 const로 선언된 변수들로 local lexical Scope를 갖으며, Variable environment는 var로 선언된 변수들이 functional scope를 갖는다고 한다. 앞에서 얘기 했던 Environmet들의 속성을 조금 더 추가하여 설명하자면, Lexical Environment에서 Environment Record에서 참조값이 없으면 Reference to the Outer Environmet를 Variable Environment로 참조 한다는 것이다. Variable Environmet에 없으면? 다음은 Global로 outer Environmet로 이어진다고 한다.

Execution Context의 생성과정

  1. Creation Phase
    Creation 단계에서는 Lexical Environment와 Variable Environment의 정의가 이루어 진다고 한다. This binding과 Outer Reference를 결정하고 Environment Record에 변수 식별자에 대한 메모리가 매핑된다고 한다. 값의 할당은 선언방식에 따라 다르게 이루어진다고 하는데 이것이 hoisting 개념이라고 생각한다. 여기서 variable Environment 에서는 var가 undefined로 그리고 선언형 함수가 메모리에 매핑된다고한다. Lexical Environment에서는 let, const로 선언된 변수가 메모리에 매핑 되지만 초기값은 할당 되지 않은 상태라고 한다.
  2. Execution Phase
    코드를 위에서 부터 읽으며 실행하는 단계라고 한다.

그렇다면 this는 어디에 있는가

맨 앞에서 thisArg에서 출발한 의문점이 여기까지 왔다. 메소드에서 thisArg에 사용목적을 설명하라면 아직도 답하지 못 할 것이다. 하지만 적어도 this에 대해서는 여기서 정리해 보자.

this는 Lexical scope가 아닌 Global Scope를 참조 하고 있다고 한다. 그리고 아래와 같은 과정을 통해서 this값을 결정한다고 한다.

  1. strict mode에서 정의된 함수일 경우, thisthisArg가 된다.
  2. thisArg가 null | undefined일 경우, this는 global Object가 된다.
  3. Type(thisArg) 값이 객체가 아닌경우, this는 toObject(thisArg)가 된다.
  • Type() 함수는 ECMAScript 내부 함수로, 변수의 Type을 리턴한다고 한다.
  • toObject() 함수는 변수를 Boolean, Number, String, Object 형으로 변환한다고 한다.
  1. 위 과정을 거치고도 this값이 정해지지 않는다면, thisthisArg가 된다고 한다.

    call, apply, bind 모두 thisArg수정 함으로써 this값을 바인딩 하는 것이라고 한다. 그리고 함수 호출 과정의 6번 단계와 관계가 있다고 하는데... 이해가 와닿지 않는 부분이다.

this 예

  1. new키워드와 함께 함수를 호출하면, this는 아예 새로운 객체가 된다고 한다.
    추가 설명하자면 객체로 인스턴스화 될 때 this값은 인스턴스화 된 객체를 참조한다.
function Aaa(x) {
  console.log(this);
  this.x = x;
  console.log(this);
}

const aaa = new Aaa(20);
// Aaa {}
// Aaa {x: 20}
  1. apply, call, bind 가 함수의 호출/생성에 사용되면, this는 인수로 전달된 객체가 된다.

  2. obj.method()와 같이 함수를 호출 하면 this는 obj가 된다.

  3. 자유 함수로 호출 되면, this는 전역 객체(브라우저에서는 window)가 된다.
    단, strict mode에서는 undefined가 된다.

  4. 위의 4가지 규칙 중, 다수가 적용되면 상위 규칙이 승리한다고 한다.

  5. ES6에 새로 정의된 화살표 함수인 경우, 위의 규칙을 무시하고 Lexical Scope를 따라 상위 소코프의 this 값을 받는다고 한다.

    여기서 2, 3, 5, 6이 이해가 안갔다 ㅠ. 6번 경우 new를 사용하지 않으면 1번 값과 거진 동일하게 출력하는 것을 알 수 있었다.. 차이점은 ...

const Aaa = (x) => {
  console.log(this);
  this.x = x;
  console.log(this);
};

const aaa = new Aaa(20);
// TypeError: Aaa is not a constructor

const Aaa = (x) => {
  console.log(this);
  this.x = x;
  console.log(this);
};

const aaa = Aaa(20);
// {}
// { x: 20 }

마치면서

두서 없이 적어 내려갔다. 두서 없이 적어 내려간거 치고는 너무 오래 걸렸다 ㅠ. 그래도 조금은 조금은 이해를 했다. 이렇게 글쓰는게 어려울 뿐이지 ㅠ. 다음에 이어서 쓰기를 목표로 하면서 TIL를 마무리 한다.

참조

[[JavaScript] 자바스크립트 this 키워드의 모든것, 코드 보관함, 2022년06월08일 접속]
https://muckycode.blogspot.com/2015/04/javascript-this.html
[[JavaScript] 자바스크립트 this란?,velog , 2022년06월09일 접속]
https://velog.io/@arski/JavaScript-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-this%EB%9E%80
[[JavaScript] 실행 영역(Execution Context)과 스코프(Scope), 코드 보관함, 2022년06월08일 접속]
https://muckycode.blogspot.com/2015/03/javascript-execution-context-scope.html
[JavaScript - Execute context,생활코딩 YouTube, 2022년06월08일 접속]
https://www.youtube.com/watch?v=QtOF0uMBy7k
[[JavaScript] Execution Context(실행 컨텍스트) 정의와 종류,가장 쉬운 웹개발 with Boaz YouTube, 2022년06월08일 접속]
https://www.youtube.com/watch?v=AbNc8_poxu4
[[10분 테코톡] 💙 하루의 실행 컨텍스트,우아한Tech YouTube, 2022년06월09일 접속]
https://www.youtube.com/watch?v=EWfujNzSUmw
[Execution Context(실행 컨텍스트)란?,velog , 2022년06월08일 접속]
https://velog.io/@stampid/Execution-Context%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8%EB%9E%80
[Context (실행 컨텍스트) 와 Hoisting (호이스팅), velog , 2022년06월08일 접속]
https://velog.io/@imacoolgirlyo/JS-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%9D%98-Hoisting-The-Execution-Context-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85-%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-6bjsmmlmgy
[[JS]Execution Context와 Call Stack, Github, 2022년06월08일 접속]
https://dkje.github.io/2020/08/30/ExecutionContext/

profile
개발자준비중

0개의 댓글