자바스크립트의 에러 종류(NativeError)

쏘쏘임·2021년 10월 3일
6
post-thumbnail

1. 자바스크립트가 에러를 던지는 방법

자바스크립트 에러가 감지하면 Error 생성자 함수를 통해 인스턴스를 생성하고 이를 throw, 즉 던진다. 또한 프로토타입 체인을 통해 NativeError, AggregateError 등 더 세부적인 에러 인스턴스들을 생성하여 던질 수 있다. (참고 : 20.5 Error Objects)

1-1. 에러 인스턴스 생성 -> throw

throw new Error('There is error') 와 같이 Error 빌트인 객체를 이용해 직접 에러를 만들어줄 수도 있으며, AggregateError(다수의 에러를 래핑한 것)로 처리할 수 도 있다. 런타임 진행 중 특정 상황에 맞춰 자동으로 NativeError를 생성해주기도 한다.

다음 기회에 에러와 오류 처리에 대해 더 심도깊게 다뤄보고, 이번 포스팅에서는 특정 상황에 따라 자바스크립트 엔진이 자동으로 생성해주는 NativeError에 대해 알아보고자 한다.

2. NativeError 각각의 예시

2-1. EvalError

MDN : This exception is not currently used within this specification. This object remains for compatibility with previous editions of this specification.

사양서에서 더 이상 사용하지 않지만 이전 버전과의 호환을 위해 남겨두고 있는 예외다. 넘어가자.

2-2. RangeError

어떤 값이 집합에 없거나 허용되는 범위가 아닌 경우 발생

MDN : Indicates a value that is not in the set or range of allowable values.

const arr = [1,2,3]
arr.length=90**99
// Uncaught RangeError: Invalid array length

const arr = new Array(4294967295); // ok
const arr = new Array(4294967296);
// Uncaught RangeError: Invalid array length

const arr = new Array(1000000);
const arr2 = [];
arr2.push(...arr);
// Uncaught RangeError: Maximum call stack size exceeded

자바스크립트의 최대 배열의 길이(2^32승 -1)보다 큰 길이의 배열을 만들려고 하거나 실행 가능한 콜 스택 사이즈를 넘어선 동작을 진행하는 등 자바스크립트 엔진이 컨트롤 가능한 범위를 넘어선 경우 발생한다.

const arr = [1,2,3];
arr[6]; //undefined

(괜한 부연 설명)왠지 범위 에러라고하면 배열에 없는 인덱스값이 접근할 때 나는게 아닌가.. 라고 착각할 수 있다. 하지만 자바스크립트에서 배열은 인덱스로 접근하는 것 처럼 보여도 실은 해쉬맵 기반 + 동적 접근을 하는 자료구조다. 없는 인덱스값에 접근했을 땐 마치 객체에 없는 프로퍼티에 접근한 것과 같이 undefined가 뜬다.

2-3. ReferenceError

스코프체인(렉시컬 환경의 환경리코드)에서 식별자를 찾을 수 없을 때 발생

MDN : Indicate that an invalid reference has been detected.


const apple = "testing"
apple;
banana;
// Uncaught ReferenceError: banana is not defined

식별자를 호출하면 환경 리코드에 등록된 식별자들을 렉시컬 환경(스코프 체인)을 따라 검색한다. 스코프의 최상단인 전역 환경 리코드에서도 식별자를 찾을 수 없는 경우 리퍼런스 에러를 발생시킨다.

2-4. SyntaxError

토크나이징, 파싱 과정에서 문맥상 요소의 역할을 파악할 수 없을 때 발생

MDN : Indicates that a parsing error has occurred.

let apple h = "apple"
// Uncaught SyntaxError: Unexpected identifier

let 1 = 1;
// Uncaught SyntaxError: Unexpected number

77.toExponential(); // Uncaught SyntaxError: Invalid or unexpected token

class A {
	constructor(){}
	constructor(){}
}
// Uncaught SyntaxError: A class may only have one constructor

자바스크립트 엔진이 토크나이징하고 파싱하는 과정에서 문맥상 이해할 수 없는 요소를 만났을 때, 혹은 AST 트리구조로 만들 수 없는 불가능한 구조를 형성하고 있을 때 신택스 에러를 발생시킨다.

2-5. TypeError

다른 NativeError 생성 조건에 부합하지 않는 경우. 실행 중 데이터타입이 올바르게 사용되지 않았을 때 발생

MDN : TypeError is used to indicate an unsuccessful operation when none of the other NativeError objects are an appropriate indication of the failure cause.

  • 함수에 전달된 피연산자 또는 인수가 해당 연산자나 함수가 예상하는 타입과 호환되지 않음
  • 변경할 수 없는 값을 수정
  • 부적절한 방법으로 값을 사용
const num = 123
num.toUpperCase()
// Uncaught TypeError: num.toUpperCase is not a function

//String.prototype.toUpperCase()

Symbol() + '';
// Uncaught TypeError: Cannot convert a Symbol value to a string

위의 예제에서 num은 숫자 데이터타입으로, 객체처럼 접근했을 때 숫자 레퍼객체를 생성한다. Number.prototype에서는 toUpperCase 메서드가 존재하지 않기 때문에 undefined 값을 가지는데, 이를 함수에 접근하듯 호출하였으니 'num.toUpperCase는 함수가 아니다' 라며 잘못된 데이터 접근으로 에러를 발생시켰다.

또한 심볼 데이터타입은 불리언 외에 다른 형으로 변환할 수 없는 값이다. 이 또한 잘못된 데이터타입 사용으로 타입에러를 발생시킨다.

2-6. URIError

전역 URI 핸들링 함수가 잘못된 방법으로 사용되었을 때 발생

MDN : Indicates that one of the global URI handling functions was used in a way that is incompatible with its definition.

try {
  decodeURIComponent('%')
} catch (e) {
  console.log(e instanceof URIError)  // true
  console.log(e.message)              // "malformed URI sequence"
  console.log(e.name)                 // "URIError"
  console.log(e.fileName)             // "Scratchpad/1"
  console.log(e.lineNumber)           // 2
  console.log(e.columnNumber)         // 2
  console.log(e.stack)                // "@Scratchpad/2:2:3\n"
}

3. Conclusion

Error 빌트인 객체(생성자 함수)를 통해, 혹은 그를 상속받은 객체를 통해 인스턴스를 생성하고 이를 던짐으로서 에러를 발생시키고 해당 기능을 종료한다.

에러 메시지와 종류를 통해 어떤 문제가 있는지 파악하면 에러 해결에 도움이 된다.

참고 링크

ECMAScript2021 NativeError
MDN Error
MDN URIError
MDN SyntaxError
MDN ReferenceError
MDN TypeError
MDN RangeError

profile
무럭무럭 자라는 주니어 프론트엔드 개발자입니다.

0개의 댓글