ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JavaScript] "Illegal invocation" errors
    개발/Javascript 2022. 5. 31. 03:14

    "Illegal invocation" 오류는 함수 호출과 관련해서 발생합니다.

    JavaScript에서 this는 상황에 따라 달라지는데,

    호출되는 함수가 동작 과정에서 this를 참조하고 있을 때

    this가 참조하는 객체가 달라지면 문제가 됩니다.

     

    다음 예제를 살펴봅시다.

    const $ = document.querySelector;
    $("#root"); // TypeError

    언뜻 보면 문제가 없을 것 같지만, 살펴봅시다.

    document 객체의 메소드의 this는 document 객체를 가리킵니다.

    document 객체의 메소드에서 다른 메소드나 객체에 접근할 때 this가 필요합니다.

    만약 this가 가리키는 객체가 document가 아니게 된다면 동작을 제대로 수행할 수 없기 때문에

    오류를 발생시키는 게 맞습니다.

     

    document.querySelector("#root")로 사용할 때는 this가 document를 참조하지만

    메소드 객체를 $으로 가져와 $()로 호출하면

    $()의 this는 호출자인, 상위 객체인 window가 되는 것입니다.

    이 예제에서는 window지만 상황에 따라 this는 다른 객체가 될 수 있습니다.

    정상 작동을 하기 위해서는 querySelector가 실행될 때의 this가 document라고 지정하면 됩니다.

    const $ = document.querySelector.bind(document);
    $("#root"); // OK

     

    예제 하나만 더 살펴보겠습니다.

    bind 메소드를 이용해 this를 묶어놓은 채로

    새로운 객체로 받을 수 있고

    bind 없이 받은 뒤에

    apply, call 함수를 이용해 this를 지정하면서 호출할 수도 있습니다.

    const obj = {
        func: function() {
            console.log("Calling func() 'this' refers to ", this);
    
            if (this !== obj) {
                throw new TypeError("Illegal invocation❌");
            }
    
            console.log("Successfully called obj.func()✅");
        }
    }
    obj.func(); // OK. 'this' refers to obj
    
    const {func} = obj;
    // func.apply(obj);
    func(); // TypeError. 'this' refers to Window

     

    다음과 같은 경우도 생각해볼 수 있습니다.

    두 코드 모두 동일한 동작을 합니다.

    node.children.map(callback).forEach(element.doSomething.bind(element));
    node.children.map(callback).forEach((elem) => element.doSomething(elem));

    댓글

Designed by Tistory.