지난주에는 JS 객체, 함수의 일급 객체 특성, 스코프와 렉시컬 스코프를 배웠습니다. 핵심만 빠르게 짚어보겠습니다.
{ key: value } 형태로 선언, 프로퍼티와 메서드로 구성obj.key (점 표기법) 또는 obj['key']
(대괄호 표기법){name} 으로 축약 가능const fn = function() {}arr.map(fn) — 콜백 함수의 근거return function() {} — 고차 함수, 클로저의
근거const는 리모컨을 바꾸지 못하게 하는 것입니다. 하지만
리모컨이 가리키는 TV의 채널(객체 내부 값)은 마음대로 바꿀 수 있습니다.
// const는 리모컨(참조)을 고정할 뿐
const tv = { channel: 5 };
tv.channel = 11; // 가능 — TV 채널(내부 값) 변경
console.log(tv.channel); // 11
tv = { channel: 3 }; // TypeError — 리모컨 자체를 바꾸려 하면 에러!
프로토타입 체인은 족보와 같습니다. 내가 가진 게 없으면 부모
것을 쓰고, 부모도 없으면 조부모 것을 씁니다. 최상위
조상(Object.prototype)까지 올라가도 없으면 undefined입니다.
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function () {
return `${this.name}이(가) 소리를 냅니다`;
};
const dog = new Animal("멍멍이");
// 탐색 순서: dog 자신 → Animal.prototype → Object.prototype
dog.name; // "멍멍이" — 자신의 프로퍼티
dog.speak();
typeof로는 배열과 객체를 구분할 수 없습니다. 배열도 결국 객체이기
때문입니다.
typeof []; // 'object' — 배열인데 object!
typeof {}; // 'object' — 일반 객체도 object
typeof null; // 'object' — null도 object (버그)
// 배열 확인은 반드시 Array.isArray() 사용
Array.isArray([]); // true
Array.isArray({}); // false
Array.isArray(null); // false
Q1. 아래 코드의 실행 결과는 무엇인가요? Object.freeze()의 동작 방식을
설명하세요.
const arr = [1, 2, 3];
Object.freeze(arr);
arr.push(4);
Object.freeze()는 객체(배열 포함)를 동결하여 프로퍼티 추가, 삭제, 변경을
금지합니다. push()는 배열에 새 요소를 추가하므로
동결된 배열에서는 TypeError가 발생합니다. 단, 얕은
동결(shallow freeze)이므로 중첩된 객체 내부는 여전히 변경 가능합니다.
Q2. [] instanceof Array는 true이고, [] instanceof Object도
true입니다. 왜 빈 배열이 Object의 인스턴스이기도 한지, 프로토타입
체인으로 설명하세요.
[]의 프로토타입 체인은
[] → Array.prototype → Object.prototype → null입니다.
instanceof는 오른쪽 생성자의 prototype이 왼쪽 객체의 프로토타입 체인
어딘가에 존재하는지 확인합니다. Array.prototype도, Object.prototype도
체인에 있으므로 둘 다 true입니다. JS에서 거의 모든 객체의 체인 최상단에는
Object.prototype이 있습니다.
Q3. 배열인지 확인할 때 typeof를 사용하면 안 되는 이유를 설명하고, 올바른
확인 방법을 제시하세요. typeof []의 결과도 함께 답하세요.
typeof []는 "object"typeof는 배열과 일반 객체, null을 모두 "object"로 반환하므로 배열을
구분할 수 없습니다. 배열 확인에는 Array.isArray()를
사용해야 합니다. instanceof Array는 다른 실행 컨텍스트(iframe)에서 생성된
배열을 인식하지 못하는 경우가 있어 Array.isArray()가 더 안전합니다.
Q4. ES6의 class가 "프로토타입 기반 상속의 문법적 설탕(syntactic
sugar)"이라는 말의 의미를 설명하세요. class로 작성한 코드를 프로토타입
방식으로 바꾸면 어떤 구조가 되는지 보여주세요.
// class 방식
class Person {
constructor(name) {
this.name = name;
}
greet() {
return this.name;
}
}
// 프로토타입 방식 (동일 동작)
function Person(name) {
this.name = name;
}
Person.prototype.greet = function () {
return this.name
class는 새로운 상속 모델이 아니라
프로토타입 기반 상속을 더 읽기 쉽게 작성하는 문법입니다.
typeof로 class를 확인하면 "function"이 나옵니다. 다만 class에는 strict
mode 강제, TDZ(호이스팅 불가), new 없이 호출 불가 등 추가 제약이 있어 완전히
동일하지는 않습니다.
이번 주 범위와 관련된 실제 면접 질문들입니다. 정답을 외우기보다는 자신만의 말로 설명하는 연습을 해보세요.
아니오. const는 변수 바인딩만 고정합니다. 변수가 가리키는 메모리 주소(참조)를 바꿀 수 없을 뿐, 그 주소에 있는 객체 내부의 값은 자유롭게 변경할 수 있습니다.
const obj = { x: 1 };
obj.x = 99; // 가능 — 프로퍼티 변경
obj.y = 100; // 가능 — 프로퍼티 추가
obj = {}; // TypeError — 재할당만 불가
완전한 불변 객체를 만들려면 Object.freeze()를 사용해야
합니다. 단, freeze도 최상위 프로퍼티만 동결하는 얕은 동결(shallow
freeze)입니다. 중첩 객체까지 동결하려면 재귀적 deepFreeze가 필요합니다.
면접 팁: "const는 재할당을 막는 것이고, 불변성은 Object.freeze()로 별도로 처리해야 합니다. React에서 setState나 useState가 새 객체를 반환하는 것도 이 불변 패턴을 따르는 것입니다"라고 연결해서 답하면 좋습니다.
Q2. 프로토타입 체인(Prototype Chain)이란 무엇인가요?
객체에서 프로퍼티를 참조할 때 자신에게 없으면
[[Prototype]]이 가리키는 상위 프로토타입 객체에서 탐색하는 구조
입니다. 체인을 타고 올라가 최상단인 Object.prototype까지 탐색해도 없으면
undefined를 반환합니다.
function Person(name) {
this.name = name;
}
Person.prototype.greet = function () {
return `안녕하세요, ${this.name}입니다.`;
};
const p = new Person("철수");
p.greet(); // Person.prototype에서 찾음
p.hasOwnProperty("name"
면접 팁: "prototype에 메서드를 추가하면 모든 인스턴스가 메서드를 복사하지 않고 공유합니다. 메모리 효율이 좋고, 이것이 JS 상속의 근간입니다. ES6 class도 내부적으로는 같은 프로토타입 메커니즘을 사용합니다"라고 설명하면 좋습니다.
Q3. 런타임에 값의 타입을 정확히 확인하는 방법은 무엇인가요?
typeof는 null을 'object'로, 배열도 'object'로 반환하는 한계가
있습니다. 정확한 타입 확인에는 상황에 따라 다른 방법을 씁니다.
Array.isArray(value) — 가장 명확하고 안전value === null — typeof는 사용 불가value instanceof Constructor — 프로토타입
체인 탐색Object.prototype.toString.call(value) —
'[object Array]' 등 정확히 반환면접 팁: "TypeScript를 쓰면 이런 런타임 타입 체크의 대부분을 컴파일 타임으로 옮길 수 있습니다. React 프로젝트에서 TypeScript가 사실상 표준인 이유 중 하나입니다"라고 연결하면 좋습니다.
다음 주에는 JS에서 실무에서 가장 자주 마주치는 비동기 처리를 다룹니다. 콜백 패턴에서 시작해 Promise, 그리고 현대 JS의 표준인 async/await까지 흐름을 이어서 배웁니다. 비동기는 JS가 단일 스레드이면서도 I/O를 효율적으로 처리하는 방법이라, 처음엔 실행 순서가 낯설게 느껴질 수 있습니다. 미리 읽어오면 대면 때 훨씬 이해가 빠릅니다.
다음 주 학습 자료(week8)의 얄코 강의를 시청하거나, 스킵 진단 문제 10개를 풀어보세요. 클로저와 비동기는 React를 배울 때 매 순간 등장하는 개념들입니다.