2022. 4. 21. 17:00ㆍ프론트엔드/HTML, CSS, Javascript
면접에서 몰랐던 부분이라 한 번 찾아봤다.
4줄 요약하면 다음과 같다.
혹시 모르니 코드로도 써놓겠다.
const a = {};
a.__proto__ === Object.prototype
a.__proto__.goldfish = "good"
Object.prototype.goldfish
한줄 한줄 살펴보자
const a = {};
a라는 변수를 객체 리터럴로 선언을 하였다.
객체 리터럴이란 ECMAScript 2015에서 지원된 방법으로,
기존 생성자를 이용하지 않고 중괄호로 표현하는 방식이다.
const a = {}
const b = { a: 4 }
이 오염 이슈는 객체 리터럴에서 발생한다.
왜냐하면 객체 리터럴로 생성된 객체의 __proto__는
Object.prototpe과 같기 때문이다.
a.__proto__ === Object.prototype
두번째 줄은 실제로 객체 리터럴로 생성된 a의 __proto__와
Object.prototype이 같은지 보는 것이다.
참고로 결과는 참이다.
a.__proto__.goldfish = "good"
세번째 줄에서는 a.__proto__에 goldfish라는 프로퍼티를 넣었다.
Object.prototype.goldfish
그랬더니 실제로 Object.prototype.goldfish가
세번재 줄에서 대입한 "good"이 된 것을 알 수 있다.
그래서?
그러고 보니 Object.prototype이 바뀐게 무슨 소용인가 싶을 수 있다.
이 세가지를 생각해보자
프로토타입의 프로퍼티는 해당 프로토타입을 가지는 모든 객체가 사용할 수 있다.
이런 식으로 어떤 리터럴 객체를 생성하던간에
goldfish의 값을 가지고 있음을 알 수 있다.
오염 방법
근데 물론 이건 코드에서 실행하지 않으면 의미가 없다.
그렇기 때문에 어떻게든 실행시키기 위해 이런 방법을 쓴다.
a[id][name] = valueFromFront;
별 문제 없어보인다.
하지만 값이 다음과 같다면 어떻게 될까?
const id = "__proto__";
cosnt name = "goldfish";
const valueFromFront = "good";
a[id][name] = valueFromFront;
// a["__proto__"]["goldfish"] = "good"
징하다 진짜...
기타 방식으로는 객체를 깊은 복사하거나,
객체에 key를 넣는 유틸함수을 이용해 적용시킬 수 있다.
해결 방법
1. Object.freeze를 이용해 변경을 못하게 한다.
2. 외부에서 들어오는 입력값을 검증한다 (avj 등)
3. key / value를 저장하는데 객체를 사용하지 않고 Map을 사용한다.
후기
이런거 뚫는 사람들 정말 대단한 사람들이라는 생각이 들고,
왜 면접에서 Typescript의 장점이나 ~하지 않는 이유같은 걸
계속해서 물어봤는지 알 것 같다.
'프론트엔드 > HTML, CSS, Javascript' 카테고리의 다른 글
XSS (cross-site-script)이란? - Javascript (0) | 2022.05.15 |
---|---|
문자 이스케이프란? - HTML (0) | 2022.05.15 |
브라우저 객체 모델 - BOM (0) | 2022.04.21 |
[HTML] 글자 사이에 원하는 길이만큼 공백 넣기 (feat. React) (0) | 2022.02.08 |
CSS에서 Flex를 해보자. (0) | 2021.10.19 |