javaScript/error

js // type error (타입 오류)

부엉이사장 2023. 5. 2. 04:44

# mdn정의

  • 함수에 전달된 피연산자 또는 인수가 해당 연산자나 함수가 예상하는 타입과 호환되지 않을 경우
  • 변경할 수 없는 값을 수정하려고 할 경우
  • 부적절한 방법으로 값을 사용하려고 할 경우

 

# 일반적인 오류

- 바꿀수 없는 값(상수)

const value = 1;
value = 2;

상수 value를 바꾸려고할때 에러뜬다

 

- 이상한거 연산하려고할때

console.log(Symbol("hello") + 1);

심볼이랑 숫자는 더할수 없는데..

- 이상한거 참조하려고할때

console.log(null.hello);
console.log(undefined.hello);

null과 undefined에서 프로퍼티 참조하려면 에러뜸니다..

+ 참고로 선언하지 않은 변수에서 프로퍼티 참조하려하면

console.log(babo.hello);

타입에러가 아니라 참조에러뜸.

 

 

 

 

 

 

# 이중 객체 프로퍼티 참조

const obj = { key1: 1, key2: 2, key3: 3 };
console.log(obj.key1); //1

이런 객체 프로퍼티에 참조하려고 할때

key1프로퍼티 키에 접근하려고하면 당연히 1을 잘 가져온다.

 

그렇다면 없는 키값에 접근할때는 어떻게 될까? 

const obj = { key1: 1, key2: 2, key3: 3 };
console.log(obj.key4); //undefined

없는 키값 key4에 접근하려 하면 undefined가 뜬다.

참조에러가 뜨는게 아니라 에러없이 undefined가 뜬다는거다.

 

즉 객체안에서 없는 프로퍼티에 접근하려하면 undefined로 뜬다.

참조코드와 동시에 객체내부에서 선언이되는건지 아닌건지 모르겠지만 이렇게 되는게

실제 코드를 써보면 더 편리하다.

 

+이중 객체에서의 참조

const obj = { key1: 1, key2: 2, key3: 3 };
console.log(obj.key4.secondKey);

위 obj에서 key4값은 undefined일것이다.

근데 이 key4가 객체라고 생각해서 그 안의 secondKey프로퍼티에 접근하려고하면

참조에러가 아닌 타입에러가 뜬다. 이땐 옵셔널체이닝써라.

const obj = { key1: 1, key2: 2, key3: 3 };
console.log(obj.key4?.secondKey);

이게 옵셔널 체이닝..

얕은 객체참조에선 그냥 undefined가 떠야 수월하고 깊은 객체참조에선 옵셔널체이닝을 사용하여 참조하는게

좋다는 말임.. 실제로 이거 웹사이트 개발할때 엄청 많이쓴다.

 

 

 

# 즉시실행 함수 개행문제 (세미클론) 

const value = 1
(function () {
  console.log("즉시실행함수");
})();

얘는 위에 어떤 코드가 있는지에따라 다른에러가 뜰수 있다.

 

내가 의도한 코드 : 

const value = 1;
(function () {
  console.log("즉시실행함수");
})();

멍청한 컴퓨터가 이해한 코드 :

const value = 1(function () {
  console.log("즉시실행함수");
})();

 

이건 보통 vs코드 emet기능인가로 알아서 문제생기게 처리된다.

보통 자바스크립트에 ASI기능(automatic semicolon insertion)으로 세미클론 알아서 붙여주고 

실행되는데 ASI가 위 즉시실행코드에는 안먹히므로 세미클론을 붙여주자.

 

 

# for 반복문의 조건에 const 를 쓴경우

for (const i = 0; i < arr.length; i++) {
  console.log(arr[i]);
} // error

for in에서는 에러안뜸

for (const i in arr) {
  console.log(i);
  console.log(arr[i]);
} // const 써도 됨.

 

 

 

# for of 문을 객체로 돌려버렸을때

for (let i of obj) {
  console.log(i); 
}// 객체는 이터러블 아니라고 오류뜸

이터러블 아니라면서 안된다.

 

 

 

# forEach 반복을 객체로 돌려버렸을때

obj.forEach((i) => {
  console.log(i);
}); //객체안에 forEach메서드 참조하는걸로 판단되서 타입에러뜸

 

 

 

# Array 프로토타입  메서드를 객체에 돌려버렸을때

every, some, find, findIndx, IndexOf 메서드도 다 동일함.

객체에 없는 메서드를 호출할때랑 걍 똑같다.

 

 

 

# 프로퍼티 어트리뷰트의 configurable을 false로 하고 다시 프로퍼티어트리뷰트를 재정의할때

const myHouse = {
  dog1: "무찌",
  dog2: "도리",
};

Object.defineProperty(myHouse, "dog1", {
  configurable: false,
});

Object.defineProperty(myHouse, "dog1", {
  configurable: true,
}); // 타입 에러뜸!!

단 writable이 true일때 value의 변경과, writable을 false로 바꾸는건 허용됨.

 

 

 

 

# 클래스를 new연산자 없이 호출할때

console.log(Dog_cls("무찌", 2)); // 타입에러 뜸

 

 

# 화살표함수에 없는 arguments, caller프로퍼티를 참조하려고할때

const arrow = () => {
  return;
};

console.log(arrow.caller); //타입에러
console.log(arrow.arguments); //타입에러

프로퍼티 참조하려고할때 없으면 undefined가 떠야하는데 얘는 특별히 타입에러 뜨게해줌.

 

 

 

# 유사배열객체에 어레이메서드 쓰려고 할떄

const fucArguments = function () {
  arguments.pop(); // 에러뜸!
};

fucArguments('무찌','도리') // 타입에러. arguments에는 pop프로퍼티가 없어서 undefined인데 호출하려하니.

arguments객체는 객체다. length프로퍼티, 넘버값 프로퍼티로 배열처럼 써먹을수있지만 배열이 아니라서 배열메서드를 쓸수 없다.

 

 

# __proto__에의한 상호참조 에러

const parent = {};
const child = {};

child.__proto__ = parent;
parent.__proto__ = child;

이렇게하면 child의 프로토타입메서드를 찾으려고 할때 parent객체를 찾아가고 여기에도 없으니 parent인스턴스의 프로토타입메서드를 검색하는데 이게 또 child인스턴스니까 무한하게 꼬이곘지?

 

근데 이렇게 생성자함수의 프로토타입을 서로 교환하는것은 된다. 이건 꼬이는게 아니라서..

const Child = function () {};
const Parent = function () {};

const child = new Child();
const parent = new Parent();

Child.prototype = parent.__proto__; // 작동됨
Parent.prototype = child.__proto__; // 작동됨
child.__proto__ = Parent.prototype; // 작동안함
parent.__proto__ = Child.prototype; // 작동안함

console.log(Child.prototype); // Parent 생성자 함수 / 제대로 바꼈음
console.log(Parent.prototype); // Child 생성자 함수 / 제대로 바꼈음
console.log(child.__proto__); // Child 생성자함수 / 안바꼈음
console.log(parent.__proto__); // Parent생성자 함수 / 안바꼈음

위 코드처럼 서로 다른 생성자함수로 각 인스턴스를 생성하고,

생성자함수의 prototype프로퍼티에 인스턴스의 __proto__로 접근한 객체를 할당해준건 제대로 작동하였다.

하지만 인스턴스의 __proto__로 접근자프로퍼티 메서드를 호출하고 이곳에 직접 다른 생성자 함수의 prototype프로퍼티 객체를 할당하는건 (정확히는 매개변수로 넣어서 set __proto__ (~~.prototype)으로 호출하는거) 바뀌지 않았다.

 

암튼 이렇게 생성자함수의 프로토타입을 서로 바꾸고 새로 인스턴스를 만들면,

const newChild = new Child();
console.log(newChild.__proto__); //얘는 프로토타입이 Parent.prototype으로 생성됨.

이렇게 Child생성자 함수로 newChild 인스턴스를 만들었지만 이 인스턴스의 프로토타입체인은 Parent.prototype객체를 1순위로 거쳐가게 된다.

뭐 이런 ㅈ같은 코드를 짜지는 않겠지만 접근자프로퍼티로 새로운객체를 넣는건 어느정도 내부로직으로 검열하는듯.

근데 이게 아예 set __proto__ (객체) 가 동작하지 않는다는 의미는 아니다.

const child = new Child();
child.__proto__ = { constructor: Parent };
console.log(child.__proto__); // Parent.prototype객체 / 이렇게는 작동함.

이렇게 객체리터럴로 넣어주면 또 된다. 참 ㅈ같이도 만들어놨다.

 

 

..................UPDATING.................

'javaScript > error' 카테고리의 다른 글

react/ 빌드 전후 css 꼬임 (해결)  (0) 2024.07.30
react / eslint 무시하고 빌드하기  (0) 2024.07.29
etc  (0) 2023.05.04
js // reference error (참조오류)  (0) 2023.05.02
js // syntax error (구문오류)  (0) 2023.05.02