diff --git "a/sep/sep-3rd/yujin/9\354\233\224_3\354\243\274\354\260\250(16\354\236\245)\354\240\225\353\246\254_\354\234\240\354\247\204.md" "b/sep/sep-3rd/yujin/9\354\233\224_3\354\243\274\354\260\250(16\354\236\245)\354\240\225\353\246\254_\354\234\240\354\247\204.md" new file mode 100644 index 0000000..c3e90b1 --- /dev/null +++ "b/sep/sep-3rd/yujin/9\354\233\224_3\354\243\274\354\260\250(16\354\236\245)\354\240\225\353\246\254_\354\234\240\354\247\204.md" @@ -0,0 +1,165 @@ +# 9월 3주차(16장) + +날짜: 2025년 9월 18일 + +# 16.1/16.2 프로퍼티 어트리뷰트와 디스크립터 객체 + +## 내부 슬롯과 내부 메소드 + +자바스크립트 엔진이 구현 알고리즘을 설명하기 위해 사용하는 의사 프로퍼티와 의사메소드 + +- 의사프로퍼티/의사 메소드: 실제로 있는 프로퍼티나 메소드가 아니지만 그렇게 동작하는 것 +- 개발자가 직접적으로 접근, 호출 불가 +- 일부 내부 슬롯과 내부 메소드에는 간접적으로 접근할 수 있는 수단 존재. + +## 프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체 + +- 프로퍼티 어트리뷰트: 프로퍼티의 상태를 나타냄 + - [[Value]] -프로퍼티 값 + - [[Writable]]-값의 변경 가능 여부 + + `Object.defineProperty` + + 1. 기존 객체에 새 프로퍼티를 정의할 때 + 2. 기존 프로퍼티의 디스크립터를 수정할 때 + + ```jsx + const myFamily ={ + human:"유진" + malecat:"후추" + femalecat:"체리" + } + ``` + + 1) malecat이 `[[Writable]]: true` (값 변경 가능) + + ```jsx + Object.defineProperty(myFamily, 'malecat', { + value: "후추", + writable: true + }); + + obj.malecat = "소금"; // 값 변경 가능 + console.log(obj.malecat); // "소금" + ``` + + 2) malecat이 `[[Writable]]: false` (값 변경 불가) + + ```jsx + Object.defineProperty(myFamily, 'malecat', { + value: "후추", + writable: false + }); + + obj.malecat = "소금"; // 값 변경 시도 무시 + console.log(obj.malecat); // "후추" + ``` + + - [[Enumerable]]-열거 가능 여부 + + ```jsx + const myFamily = { + human: "유진", + malecat: "후추", + femalecat: "체리" + }; + ``` + + 1-1) malecat이 `Enumerable: true`일 때 + + ```jsx + for (let key in myFamily) { + console.log(key); + } + //human + //malecat + //femalecat + ``` + + - 반복문으로 모두 접근 가능 + + ```jsx + console.log(Object.keys(myFamily)); //["human", "malecat", "femalecat"] + ``` + + --- + + ### 1-2) malecat이 `Enumerable: false`일 때 + + ```jsx + Object.defineProperty(myFamily, 'malecat', { + value: "후추", + enumerable: false + }); + + for (let key in myFamily) { + console.log(key); + } + //human + //femalecat + + ``` + + - malecat은 반복문에서 제외됨 + + ```jsx + console.log(Object.keys(myFamily));//["human", "femalecat"] + ``` + + 요약: [[Enumerable]] = true → 반복문/열거 가능, false → 반복문에서 숨김 + + - [[Configurable]]-프로퍼티 어트리뷰트 값의 변경 가능 여부 + - 프로퍼티 어트리뷰트 자체(writable, enumerable, configurable)와 삭제 가능 여부 결정 + - true → 어트리뷰트 변경 가능, 속성 삭제 가능 + - false → 어트리뷰트 변경 불가, 속성 삭제 불가 (값의 변경은 writable이면 가능) + + ```jsx + const obj = {}; + Object.defineProperty(obj, 'x', { value: 10, writable: true, configurable: false }); + + // 속성 변경 시도 + Object.defineProperty(obj, 'x', { emunerable: false }); // ❌ TypeError + Object.defineProperty(obj, 'x', { writable: false });//에러 안남 + delete obj.x; // ❌ 삭제 불가 + obj.x = 20; // ✅ 값 자체는 writable이면 변경 가능 + ``` + + > 한 번 configurable을 false로 지정하면 다시 true로 바꿀 수 없음 + > + + → why? configurable이 false이기 때문에 프로퍼티 어트리뷰트인 configurable의 값을 변경하지 못한다. + + ⚠️ 주의: `writable`은 예외적으로 `true → false`로 바꾸는 건 가능. + + - Q: 프로퍼티 어트리뷰트는 공유되는가? + - **각 프로퍼티마다 각각 가지고 있음** + - human, malecat, femalecat 각각 독립적으로 [[Writable]], [[Enumerable]], [[Configurable]] 상태를 가짐. + - 따라서 하나를 바꾼다고 다른 프로퍼티에는 영향 없음 + + ```jsx + Object.defineProperty(obj, 'malecat', { enumerable: false }); + console.log(Object.keys(obj)); // ["human", "femalecat"] + console.log(Object.getOwnPropertyDescriptor(obj, 'human').enumerable); + // true + //malecat만 false로 바꿨지만 human은 그대로 true유지 + ``` + +- 디스크립터 객체: 프로퍼티 어트리뷰트를 나타내는 객체 + + ```jsx + const myFamily = { + human: "유진", + malecat: "후추", + femalecat: "체리" + }; + + // 예시: 디스크립터 객체 가져오기 + console.log(Object.getOwnPropertyDescriptor(myFamily, "human")); + + { + value: "유진", // 프로퍼티 값 + writable: true, // 값 변경 가능 + enumerable: true, // 열거 가능 + configurable: true // 삭제하거나 어트리뷰트 변경 가능 + } + ``` \ No newline at end of file