티스토리 뷰

this ?

  • this란 함수 내에서 함수 호출 맥락(context)를 의미한다.
  • 함수를 어떻게 호출하느냐에 따라서 this가 가리키는 대상이 달라진다는 의미이다.
  • 함수와 객체의 관계가 느슨한 자바스크립트에서 this는 이 둘을 연결시켜주는 실질적인 연결점 역할을 한다.
  • this는 상위 객체를 가르킨다. apply ,call을 활용해 제어가 가능하다. 

함수호출

  • 어떠한 객체에 소속되어 있지 않은 함수를 호출했을 때 this는 무엇을 가리키는가? -> this === window 
  • 사실상 window가 생략됐을 뿐이지(암시적으로 사용되고 있는 window) window가 해당 함수를 포함하는 전역객체인 것이다.

메소드의 호출

  • 객체의 소속인 메소드의 this는 그 객체를 가르킨다. 
  • e.g) o.func(); // 에서 this 란 o객체를 말한다.

생성자의 호출

let funcThis = null;
	//Func()함수가 실행되면 변수 앞에 뭐가 안붙어있다 -> 전역변수 가리킴 
    //funcThis의 값이 null에서 this로 할당됨 전역변수의 this는 window를 가리키기 때문에 this === window
      function Func() {
        funcThis = this;
      }
      //new 없이 일반함수로 호출
      const o1 = Func();
      if (funcThis === window) {
        document.write("window <br/>");
      }
      // 생성자 함수로 호출
      //내부로 비어있는 객체를 만들어냄-> 새로만들어내는 객체가 생성자 안에서 this가 되는 것 
      const o2 = new Func();
      if (funcThis === o2) {
        document.write("o2 <br/>");
      }
  • 생성자는 빈 객체를 만든다. 그리고 이 객체 내에서 this는 만들어진 객체를 가르킨다.
  • 생성자가 실행되기 전까지는 객체는 변수에도 할당될 수 없기 때문에 this가 아니면 객체에 대한 어떠한 작업을 할 수 없기 때문이다.
//오류가 나는 경우 :레퍼런스 에러발생
      function Func2() {
        document.write(o);
      }
      const o = new Func2();
  • Uncaught ReferenceError: Cannot access 'o' before initialization (번역: 레퍼런스 에러 : 초기화가 되기 전에 o변수(객체)에 접근할 수 없습니다. )
  • 생성자함수가 객체를 만들고 변수 o에 담으려면 Func2()함수의 작업을 진행(초기화작업)하고 그 다음 변수o에 담기는 것인데 변수에 담기기 전에 변수 o에 접근하려고 하기 때문에 오류가 나는 것이다. 
  • 이슈) 코드 예제의 결과가 undefined 라고 나와있는데 콘솔에서는 ReferenceError 가 발생했다. -> 이 경우는 변수 선언시 var가 아닌 const 와 let을 사용할 때 발생한다고 함.(아래에 정리)

😱Error를 만났다 발생한 에러를 이해해보자!😱

Cannot access before initialization Error in JS

  • cannot access before initialzation error은 변수가 'let' 혹은 'const'와 같이 선언되었고 해당 스코프에서 초기화되기 전에 변수가 사용되면 뜨는 에러이다.
  • var를 사용하여 선언된 변수와 함께 호이스트가 작동하는 방법은 변수 선언을 파일의 맨 위로 올리는 것입니다. 그렇기 때문에 var로 선언된 변수에서는 아래와 같은 상황에서 레퍼런스 에러가 아닌 undefined의 결과를 냅니다.
  • let, const 와 var를 사용해서 변수를 선언했을 때의 결과가 다르기 때문에 유의하시길 바랍니다. ref: https://bobbyhadz.com/blog/javascript-referenceerror-cannot-access-before-initialization
  • //변수에 const, let을 사용할 경우 arr = [3, 2, 1]; // ⛔️ Cannot access 'arr' before initialization let arr = [1, 2, 3]; //fix 상황 let arr = [1, 2, 3];//초기화 arr = [3, 2, 1]; //변수에 var을 사용할 경우 var arr; console.log(arr); // 👉️ undefined arr = [1, 2, 3];

Undefined 와 ReferenceError 의 차이점

Undefined

  • undefined 속성은 Undefined 원시값을 나타내며, JS의 원시 자료형 중 하나이다. 
  • 기본적으로 값이 할당되지 않은 변수는 Undefined 타입이며, Undefined 타입은 변수 자체 값 또한 undefined 입니다. 
  • 변수는 선언했지만 초기화를 하지 않아서 그 값을 원시값인 undefined 로 주는 것 엄밀히 말하면 오류가 아니라 초기화가 되지 않은 것이다.

ReferenceError

  • ReferenceError란 참조 에러입니다. 
  • 객체는 존재하지 않는 변수를 참조했을 때 발생하는 에러를 나타냅니다. 객체를 생성하지 않았기 때문에 참조할 값을 찾지 못했다고 이해하면 쉽다.

apply, call

//우리가 여태 함수를 정의한다고 알고있었지만 사실은 함수 객체를 만든 것입니다. 이것을 함수리터럴이라 합니다. 
      function sum(x, y) {
        return x + y;
      }
      let sumResult = sum(2, 3);
      document.write(sumResult + "<br/>");

      //Function 이라는 이름의 생성자 함수를 통해 메소드를 정의했다. 
      //마지막에 오는 인자가 바로 메소드의 본문에 해당한다.앞의 요소들은 매개변수이다.
      const sum2 = new Function("x", "y", "return x+y;");
      sum2(2, 3);
      let sumResult2 = sum2(3, 4);
      document.write(sumResult2);

      //객체 리터럴
      // 위 아래 코드 모두 빈 객체를 만드는 같은 동작을 한다. 
      const o = {};
      const o1 = new Object(); //차이점: JS 내장된 생성자 함수를 이용하여 객체를 만든 것

      //배열 리터럴 
      //객체 리터럴의 설명과 같음
      const a = [1,2,3];
      const a1 = new Array(1,2,3);
  • 자바스크립트에서 모든 함수는 객체란 사실을 명심하자. 그러므로 생성자 함수 또한 객체이다. 
  • 자바스크립트에서 객체란 속성(key)과 값(value)를 가지는 존재이다. 

🙄잠시 본문에서 벗어나 생성자 함수에 대해서 간단하게 알아보자🙄

생성자 함수(The Constructor Function)

new 키워드와 함께 쓰이는 함수이다.

  • 직접 정의하여 new 키워드로 생성자 함수를 만들어 사용할 수도 있고, 내장된 생성자 함수를 사용할 수도 있다. 

 

JS 내장된 생성자 함수 3가지 

  • new Array();
  • new Object();
  • new Function();

※함수 이름이 모두 대문자로 시작-> 관례적으로 직접 정의한 생성자 함수의 이름이 대문자로 시작하는 것과 동일

 

생성자 함수의 인스턴스(instance) 

e.g.) const obj = new Object(); 

  • 모든 생성자 함수는 this라는 빈 객체를 리턴한다. 
  • 그러므로 obj 변수에는 빈 객체가 할당된다.
  • 이 때 생성자 함수에서 리턴하는 결과물을 인스턴스(instance)라고 한다.

🙄다시 본문으로 와서 apply, call 에 대해서 공부합시다.🙄

 

/* 대체제 관계
if문 - switch문
for문 - while문
          */	
const o = {};
const p = {};
      function func() {
        switch (this) {
          case o:
            document.write("o<br/>");
            break;
          case p:
            document.write("p<br/>");
            break;
          case window:
            document.write("window<br/>");
            break;
        }
      }
      func(); //output: window
      func.apply(o); // 내장메소드 apply()의 첫번째인자는 함수호출 맥락(context)이다. output: o
      func.apply(p); //output: p
  • 전통적인 객체 지향에서 메소드란 객체에 강하게 소속되어 있음 -> 이 메소드는 다른 곳에 가지 못한다. 종속된 노예와 같은 상태
  • JS의 경우, 호출되는 방식에 따라 window,  o , p(위의 예시 속 객체s) 객체에 소속된 메소드가 된다. ->즉 어떤 함수가 종속된 것이 아니라 유연하게 맥락에 따라 원하는 객체에 포함될 수 있다. 

 

 

 

댓글