⚠️ 해당 게시글은 모던애자일 팀원이 준비한 테크톡 내용을 스크랩했습니다.

출처 : 모던애자일 3기 이한결 블로그

 

leephoter (leephoter) - velog

앱 vs 웹 테크톡 재희님 (2021.12.16) 2021년 12월 16일 · 0개의 댓글

velog.io

 

⭐ this 란? ⭐

JavaScript 의 함수는 호출될 때 매개변수로 전달되는 인자값 (parameter) 이외에 arguments 객체와 this 를 암묵적으로 전달 받는다.

함수의 arguments 는 함수 호출 시 전달된 인수들(arguments) 의 정보를 담고 있는 순회가 가능한 (iterable) 유사 배열 객체 (array-like object) 이며 함수 내부에서 지역변수처럼 사용된다.

$$
예시 1
$$

JavaScript 의 this 는 인스턴스 자신 (self) 을 가리키는 참조변수이다. this 가 객체 자신에 대한 참조 값을 가지고 있다는 뜻이다. 주로 매개변수와 (parameter) 객체 자신이 가지고 있는 멤버 변수명이 같을 경우 이를 구분하기 위해서 사용된다.

  • ❓ Iterator ❓자바스크립트에서 가장 일반적인 Iterator 는 배열로, 배열의 각 값 (요소) 을 순서대로 반환한다. 모든 반복자가 배열로만 표현될수 있다고 상상할 수 있지만 객체나 생성자 함수 또한 Iterator 객체이다. .
  • 배열은 완전히 할당되어야 하지만, 반복자는 필요한만큼만 소모되므로 무제한 시퀀스로 표현할 수 있습니다

  • 해당 객체가 Iterator 인지 확인해보는 방법은 for of 를 사용해보면 된다. for of 는 순회가능한 객체의 요소를 순차적으로 반환하기 때문에 예시 코드에서 객체와 같이 iterator 가 아닌 객체에 for of 를 사용하면 에러를 발생시킨다.
  • $$
    예시 1 - 1
    $$
  • Iterator (반복자) 란❓ 쉽게 말해서 순회가 가능한 객체를 뜻한다.

🔥 함수 호출 방식과 this 바인딩 🔥

JavaScript 는 함수를 선언할 때 this 에 바인딩할 객체가 정적으로 결정되는 것이 아닌, 함수를 호출할 때 함수가 어떻게 호출되었는지 (호출 방식 → 호출 순서) 에 따라 this 에 바인딩할 객체가 결정된다.

함수의 상위 스코프를 결정하는 방식인 렉시컬 스코프 (Lexical scope) 함수를 선언할 때 결정된다. this 바인딩과 혼동하지 않도록 주의해야 한다.

  • 렉시컬 스코프 (Lexical scope)

  •  
    먼저 함수를 호출한 위치에 따라 상위 스코프를 결정한다면 함수2 의 상위 스코프는 함수1 과 전역이고, 선언한 위치에 따라 결정한다면 함수2 의 상위 스코프는 전역이 될텐데...렉시컬 스코프는 “함수를 어디서 호출하는지”가 아닌, “함수를 어디에 선언했는지” 에 따라 결정된다. JavaScript 는 정적 스코프를 규칙을 따르기 때문에 함수를 선언한 시점에 상위 스코프가 결정되는데, 함수를 어디에서 호출했는지는 스코프 결정에 아무 의미를 부여하지 않는다. 위 예제의 함수 함수2 는 전역에서 선언되었기 때문에 전역변수 num (1) 이 두번 출력된다.
  • 일단 프로그래밍 언어는 이 두가지 방식 중 하나의 방식으로 함수의 상위 스코프를 결정한다. 첫 번째 방식을 동적 스코프 (Dynamic scope) 라 하고, 두 번째 방식을 정적 스코프 (Lexical scope) 라고 한다. JavaScript 를 포함한 대부분의 프로그래밍 언어는 정적 스코프를 따른다.
  • 예제 2 의 실행 결과는 함수 함수2 의 상위 스코프가 무엇인지에 따라 결정된다. 두가지 패턴을 예측할 수 있는데 첫번째는 함수를 어디서 호출했는지, 두번째는 함수를 어디서 선언했는지에 따라 상위 스코프가 결정된다.
  • $$
    예제 2
    $$

함수 호출의 방식은 여러가지가 있다.

  • 함수호출
    • 기본적으로 this 는 전역객체 (Global object) 에 바인딩된다 (Browswer - window, Server(node.js) - global). 내부함수의 경우도 this는 외부함수가 아닌 전역객체에 바인딩된다.

  •  
    •  
      • 2. 매소드의 내부 함수
      • $$
        예시 3
        $$
      • 메소드의 내부함수일 경우에도 this 는 전역객체에 바인딩된다.

  •  
    •  
      • 3. 콜백함수
      • $$
        예시 4
        $$
      • 콜백함수의 경우에도 this 는 전역객체에 바인딩된다.
      • $$
        예시5
        $$
  • 1. 함수 호출, 내부 함수 호출
 내부함수는 일반함수, 메소드, 콜백함수 어디에서 선언되었는지 상관없이 `this` 는 전역객체를 바인딩한다. 더글라스 크락포드 (Douglas Crockford - JavaScript 언어 개발에 참여) 는 “이 것은 설계 단계의 결함으로 메소드가 내부함수를 사용하여 자신의 작업을 돕게 할 수 없다는 것을 의미한다” 라고 한다.

### 내부 함수의 this 가 전역객체를 참조하는 것을 방지하는 방법 👆

상위 (부모) 함수를 참조하는 방법

$$
예시 5- 1
$$

![Screen Shot 2022-01-19 at 1.29.11 PM.png](%5BJS%5D%20this%20d46c1da58c824bcf8123e3afcc835ce0/Screen_Shot_2022-01-19_at_1.29.11_PM.png)

메소드의 내부함수에서 상위 함수, 즉 this 값을 참조해야 할 경우 this를 변수로 선언하여 참조가 가능하다.

\

  • 메소드 호출$$
    예시6
    $$→ Lee 와 Kim 이 순서대로 출력된다.

  • 함수가 객체의 프로퍼티 (property) 값이면 메소드로서 호출된다. 이 때 메소드 내부의 this 는 해당 메소드를 소유한 객체, 즉 해당 메소드를 호출한 객체에 바인딩된다.
  • 생성자 함수 호출
    이는 반대로 생각하면 생성자 함수가 아닌 일반 함수에 new 연산자를 붙여 호출하면 생성자 함수처럼 동작할 수 있다. 따라서 일반적인 생성자 함수명은 첫문자를 대문자로 작명하여 혼란을 방지하려 노력 (convention) 한다.
    생성자 함수 동작 방식생성자 함수의 코드가 실행되기 전 빈 객체가 생성된다. 이 빈 객체가 생성자 함수가 새로 생성하는 객체이다. 이후 생성자 함수 내에서 사용되는 this는 이 빈 객체를 가리킨다. 그리고 생성된 빈 객체는 생성자 함수의 prototype 프로퍼티가 가리키는 객체를 자신의 프로토타입 객체로 설정한다.생성된 빈 객체에 this를 사용하여 동적으로 프로퍼티나 메소드를 생성할 수 있다. this는 새로 생성된 객체를 가리키므로 this를 통해 생성한 프로퍼티와 메소드는 새로 생성된 객체에 추가된다.• 반환문이 없는 경우, this에 바인딩된 새로 생성한 객체가 반환된다. 명시적으로 this를 반환하여도 결과는 같다.
    • 반환문이 this가 아닌 다른 객체를 명시적으로 반환하는 경우, this가 아닌 해당 객체가 반환된다. 이때 this를 반환하지 않은 함수는 생성자 함수로서의 역할을 수행하지 못한다. 따라서 생성자 함수는 반환문을 명시적으로 사용하지 않는다.

    • 생성자 함수에 new 사용하지 않고 호출하는 경우

  •  
    •  
      일반 함수를 호출하면 this는 전역객체에 바인딩되지만 new 연산자와 함께 생성자 함수를 호출하면 this 는 생성자 함수가 암묵적으로 생성한 빈 객체에 바인딩된다.
    • 객체 생성 목적으로 작성한 생성자 함수를 new 없이 호출하거나 일반함수에 new를 붙여 호출하면 오류가 발생할 수 있다. 일반함수와 생성자 함수의 호출 시 this 바인딩 방식이 다르기 때문이다.
    • $$
      예시 7 - 1
      $$
  • funciton 사람(이름) { // 생성자 함수 코드 실행 전 -------- 동작 방식 - 1 this.이름 = 이름; // --------- 동작 방식 - 2 // 생성된 함수 반환 -------------- 동작 방식 - 3 }
  • $$
    예시 7
    $$
  • 3. 생성된 객체 반환
  • 2. this를 통한 프로퍼티 생성
  • 1. 빈 객체 생성 및 this 바인딩
  • JavaScript 의 생성사 함수는 객체를 생성하는 역할을 한다. 형식이 정해져있지 않고 기존 함수에 new 연산자를 붙여서 호출하면 해당 함수는 생성자 함수로 동작한다.
  • 객체 리터럴 방식 vs 생성자 함수 방식$$
    예시 8
    $$
    • 객체 리터럴 방식의 경우, 생성된 객체의 프로토타입 객체는 Object.prototype이다.
    • 생성자 함수 방식의 경우, 생성된 객체의 프로토타입 객체는 사람.prototype이다.
    • 프로토타입 체인$$
      예시 8 -1
      $$객체 ‘나’ 는 hasOwnProperty 메소드를 가지고 있지 않으므로 에러가 발생하여야 하나 정상적으로 결과가 출력되었다. 이는 ‘나’ 객체의 [[Prototype]]이 가리키는 링크를 따라가서 ‘나’ 객체의 부모 역할을 하는 프로토타입 객체(Object.prototype)의 메소드 hasOwnProperty를 호출하였기 때문에 가능한 것이다.

  •  
    • 자바스크립트는 특정 객체의 프로퍼티나 메소드에 접근하려고 할 때 해당 객체에 접근하려는 프로퍼티 또는 메소드가 없다면 [[Prototype]]이 가리키는 링크를 따라 자신의 부모 역할을 하는 프로토타입 객체의 프로퍼티나 메소드를 차례대로 검색한다. 이것을 프로토타입 체인이라 한다.

  • 객체 리터럴 방식과 생성자 함수 방식의 차이는 프로토타입 객체 (prototype) 에 있다.
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기