본문 바로가기
Web/웹 개념

Chrome: Illegal invocation. / IE: 호출 개체가 잘못되었습니다. Error에 대해서 알아보자.

by 강깅꽁 2021. 2. 14.

Javascript의 경우 this가 자유로운 편이다.

 

객체가 method를 가지고 있더라도 해당 method를 다른 객체가 호출할 수도 변수에 저장했다가 호출할 수도 있다.

 

예를 들어보면 Person class가 printName method를 가지고 있다.

이를 객체화 했지만 어느 시점에 person 객체가 가지고 있는 printName이라는 메서드만 필요하다고 가정한다면

다음과 같이 사용할 수 있다. 

class Person {
	constructor(name) {
    	this.name = name;
    }
    
    printName() {
    	console.log(this.name);
    }
 }
 
 const person = new Person("choi");
 const printName = person.printName;
 
 printName.call({name: "Lee"});

 

그렇다면 어느 순간 window 객체 또는 document 객체가 가지고 있는 메서드를 저장했다가 사용하고 싶다면 어떻게 될까

// e.g 1
const getEl = document.getElementById;

getEl("test"); // Uncaught TypeError: Illegal invocation

// e.g 2
document.addEventListener('click', (e) => {
	const { id } = e.target
    const setDefault = e.preventDefault;
    
    if (id !== "root") {
    	setDefault(); // Uncaught TypeError: Illegal invocation
     }  
});
     

다음과 같이 Uncaught TypeError: Illegal invocation 에러가 발생한다.

왜 그럴까 JS는 객체 간의 메서드를 빌려서 사용하고 this를 bind, call, apply로 설정해주는게 자유로운 편인데..

 

JS Spec에 그 해답이 존재했다.

JS Engine이 생성하는 window, document, event 객체의 경우 메서드를 호출할 때 this는 해당 메서드를 가지고 있는 객체여야 한다.

 

// document.getElementById() 의 getElementById 함수 본문에서의 this는 document가 된다.

const getById = document.getElementById;
getById.call(document, "root"); // 에러가 나지 않는다.