1 오브젝트의 프로퍼티의 값을 불변하게 해보자
2 오브젝트의 숨은 프로퍼티에 대해 알아보자
3 프로토타입
4 OOP를 프로토타입으로 하는것, 클래스로 하는것 다른가?
5 this를 알아보자

JS 오브젝트의 숨은 프로퍼티에 대해 알아보자

bGV0IG9iamVjdCA9IHsgbmFtZTogJ2tpbScsIGFnZTogNDUgfTsKLy8g7J2065+wIOyYpOu4jOygne2KuOqwgCDsnojri6Tqs6Ag7ZWY7J6QCi8vIOydtCDsmKTruIzsoJ3tirjsnZgg7IaN7ISx7J2066aE7J2EIOyVjOyVhOuCtOuztOqzoOyekCDtlZzri6Qg64uk7J2M6rO8IOqwmeydtCDtlZjrqbQg65Cc64ukCgpjb25zb2xlLmxvZyhPYmplY3Qua2V5cyhvYmplY3QpKQovLyDrsLDsl7TtmJXtg5zroZwg7JWM7IiYIOyeiOqyjCDrkJjsl4jri6QKCmxldCBsaXN0ID0gWydoZWxsbycsICd3b3JsZCddOwovLyDsl6zquLAg67Cw7Je07J20IOyeiOuLpAoKY29uc29sZS5sb2coT2JqZWN0LmtleXMobGlzdCkpCi8vIOuwsOyXtOydmCDqsr3smrDrnbzrqbQg67KI7Zi466W8IOyVjOyVhOuCvCDsiJgg7J6I64ukCi8vIOuwsOyXtOydmCDqsr3smrDripQg7IaN7ISx7J2066aE7J20IOuyiO2YuOuhnCDrkJjslrTsnojri6Tqs6Ag7IOd6rCB7ZWY66m0IOuQnOuLpAovLyDrrLzroaAg7Jik67iM7KCd7Yq47LKY65+8IOydtOumhOydtCDrsojtmLjtmJXtg5zqsIAg7JWE64uMIOydtOumhOydhCDsho3shLHsnLzroZwg7JO47IiYIOyeiOuLpAoKbGlzdC5wcm9wID0gJ2hlbGxvJzsKLy8g7J207JmAIOqwmeydtCDqt7jrg6Ug66eI7LmYIOyYpOu4jOygne2KuOyXkCDsho3shLHqsJIg64Sj65Ov7J20IOuEo+ydhCDsiJgg7J6I64ukCgpjb25zb2xlLmxvZyhPYmplY3Qua2V5cyhsaXN0KSkKLy8g7ZWY6rOg7IScIOuLpOyLnCDsho3shLHsnbTrpoQg66qp66Gd7J2EIO2ZleyduO2VtOuztOuptCDstpTqsIDrkJjsnojripTqsoPsnYQg67O8IOyImCDsnojri6QKCmNvbnNvbGUubG9nKGxpc3QpCi8vIOydtOugh+qyjOq5jOyngCDtlZwg7ZuEIOqwnOuwnOyekOuPhOq1rOydmCBDb25zb2xl7YOt7JeQ7IScIOywje2ejOqyg+ydhCDtjrzss5DshJwg7ZmV7J247ZW067O066m0Ci8vIDAsIDEsIHByb3AsIGxlbmd0aCDsnZgg7IaN7ISx7J2EIO2ZleyduCDtlaAg7IiYIOyeiOuLpAovLyDqt7jrn7DrjbAg7J207IOB7ZWc6rKMIO2VmOuCmCDsnojri6QgbGVuZ3Ro656A6rG0IE9iamVjdC5rZXlzKGxpc3QpIOuhnCDtmZXsnbjtlojsnYTrlZAg7JeG7JeI64qU642w66eQ7J2064ukLi4KLy8g6re466as6rOgIGxlbmd0aOuKlCDri6TrpbjqsoPqs7wg64uk66W06rKMIOyDieydtCDsooAg7Ja065Gh64ukCi8vIOq3uOugh+uLpCBPYmplY3Qua2V5c+uhnOuKlCDsg4nsnbQg7Ja065GQ7Jq06rG0IOyViOuCmOyYqOuLpAovLyDtlZjsp4Drp4wg7Ja065Gh64uk7ZWY642U652864+EIOu2hOuqhSBsZW5ndGjrnbzripQg7IaN7ISx64+EIGxpc3TqsIAg6rCA7KeEIOyGjeyEseyehOydgCDrtoTrqoXtlZjri6QKCmNvbnNvbGUubG9nKE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobGlzdCwgJzAnKSkKY29uc29sZS5sb2coT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihsaXN0LCAnMScpKQpjb25zb2xlLmxvZyhPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKGxpc3QsICdwcm9wJykpCmNvbnNvbGUubG9nKE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobGlzdCwgJ2xlbmd0aCcpKQovLyDrqqjrk6Ag7IaN7ISx65Ok7J2YIOyGjeyEseydhCDtlZzrsoggT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvciDroZwg7ZmV7J247ZW067O07J6QCi8vIO2ZleyduOqysOqzvCBsZW5ndGjsnZgg6rK97Jqw66eMIOyhsOq4iCDri6TrpbTri6Qg7J2864uoIGVudW1lcmFibGXsnbQg64KY66i47KeEIHRydWXsnbjrjbAgbGVuZ3Ro66eMIGZhbHNl66GcIOuCmOyYpOuKlOygkOyXkCDso7zrqqntlZjsnpAKLy8g7J206rKD7J20IGZhbHNl66GcIO2RnOyLnOuQmOuptCDqsJzrsJzsnpDrj4TqtawgQ29uc29sZe2DreyXkOyEnCDtmZXsnbjtlbTrs7zrlYwg7KKAIOyWtOuRoeqyjCDrgpjsmKTqs6AgT2JqZWN0LmtleXProZzrj4Qg7ZmV7J247J20IOyViOuQmOuKlOqyg+ydtOuLpAovLyDqt7jrn6zrqbQgZW51bWVyYWJsZeydmCDsg4Htg5zrpbwgdHJ1ZeuhnCDrsJTqv5Trs7zquYw/CgpPYmplY3QuZGVmaW5lUHJvcGVydHkobGlzdCwgJ2xlbmd0aCcsIHsKICAgZW51bWVyYWJsZTogdHJ1ZSwKfSk7Ci8vIOydtOugh+qyjCDtlZjrqbQgbGVuZ3Ro7J2YIGVudW1lcmFibGXsho3shLHsnYQgdHJ1ZeuhnCDrsJTqvrjsnpDripTqsoPsnbjrjbAg7Iuk7ZaJ7ZW067O066m0IOyViOuQnOuLpAovLyDsl5Drn6zqsIAg64Kg6rG0642wIENhbm5vdCByZWRlZmluZSBwcm9wZXJ0eSDrnbzqs6Ag7ZWg6rKD7J2064ukLiDsnqzsoJXsnZgg67aI6rCA64ql7ZWY64uk6rOgIO2VnOuLpAovLyDsmZw/IOydtOqyg+ydmCBjb25maWd1cmFibGUg7IaN7ISx7J20IHRydWXsnbzrlYzrp4wg7J6s7KCV7J2Y6rCAIOqwgOuKpe2VmOuLpAovLyBjb25maWd1cmFibGXsnZgg7IOB7YOc64qUIOyGjeyEseydmCDrs4Dqsr0g6rCA64ql7Jes67aA66W8IOqysOygle2VmOuKlOqyg+ydtOuLpAovLyDqt7jrn6zrqbQgY29uZmlndXJhYmxl66W8IHRydWXroZwg67CU6r68IO2bhCDri6Tsi5wg7Iuc64+E7ZWY66m0IOuQoOq5jD8g7JWE64uI64ukIGNvbmZpZ3VyYWJsZeuPhCDsho3shLHsnbTquLAg65WM66y47J2064ukCgovLyDqt7jrn6zrqbQg6rKw6rWtIE9iamVjdC5rZXlz66Gc64qUIDAsIDEsIHByb3Drp4wg7ZmV7J24IOqwgOuKpe2VmOqzoCDslrTrkZDsmrQg7IOJ7Jy866GcIO2RnOyLnOuQmOuKlCDsho3shLEsIOymiSBlbnVtZXJhYmxl7IaN7ISx7J20IGZhbHNl7J24IOyGjeyEseydgCDtmZXsnbjsnbQg7JWI65CY64qU642wCi8vIOq3uOufvOyXkOuPhCDtmZXsnbjtlaAg67Cp67KVIOyXhuydhOq5jD8KCmNvbnNvbGUubG9nKE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKGxpc3QpKQovLyDsnbTroIfqsowg7ZWY66m0IOuQnOuLpCBPYmplY3Qua2V5cyDrjIDsi6AgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMg66GcIO2ZleyduO2VmOuptCDri6Qg64KY7Jio64ukCgpjb25zb2xlLmxvZyhsaXN0Lmhhc093blByb3BlcnR5KCcwJykpCmNvbnNvbGUubG9nKGxpc3QuaGFzT3duUHJvcGVydHkoJzEnKSkKY29uc29sZS5sb2cobGlzdC5oYXNPd25Qcm9wZXJ0eSgncHJvcCcpKQpjb25zb2xlLmxvZyhsaXN0Lmhhc093blByb3BlcnR5KCdsZW5ndGgnKSkKLy8g6rCd7LK07JeQ64qUIGhhc093blByb3BlcnR5652864qUIO2VqOyImOqwgCDrtpnslrTsnojripTrjbAg7J206rKD7J2AIOyduOyekOuhnCDrhKPsnYAg66y47J6Q7Je07J2YIOydtOumhOydhCDtlZwg7IaN7ISx7J20IO2VtOuLuSDqsJ3ssrTsl5Ag7KG07J6s7ZWY64qU7KeAIO2ZleyduO2VtOyjvOuKlOqxsOuLpAovLyDslrTrkZDsmrQg7IOJ7Jy866GcIO2RnOyLnOuQmOuKlCDsho3shLHrj4Qg7Ja07KiL65OgIO2VtOuLuSDqsJ3ssrTsnZgg7IaN7ISx7J2066+A66GcIOyeiOuLpOuKlCDsnZHri7UodHJ1ZSnsnYQg7Ja77Ja064K8IOyImCDsnojri6QKCmNvbnNvbGUubG9nKCcwJyBpbiBsaXN0KTsKY29uc29sZS5sb2coJzEnIGluIGxpc3QpOwpjb25zb2xlLmxvZygncHJvcCcgaW4gbGlzdCk7CmNvbnNvbGUubG9nKCdsZW5ndGgnIGluIGxpc3QpOwovLyBpbiDtgqTsm4zrk5zroZwg7ZmV7J247ZW067SQ64+EIGhhc093blByb3BlcnR57JmAIOqwmeydgCDqsrDqs7zrpbwg7Ja77J2EIOyImCDsnojri6QKLy8gKGluIO2CpOybjOuTnOqwgCBoYXNPd25Qcm9wZXJ0ee2VqOyImOyZgCDsmYTsoIQg64+Z7J287ZWcIOq4sOuKpeydhCDtlZzri6TripQg7J2Y66+464qUIOyVhOuLiOuLpCkKCmNvbnNvbGUubG9nKGxpc3QucHJvcGVydHlJc0VudW1lcmFibGUoJzAnKSkKY29uc29sZS5sb2cobGlzdC5wcm9wZXJ0eUlzRW51bWVyYWJsZSgnMScpKQpjb25zb2xlLmxvZyhsaXN0LnByb3BlcnR5SXNFbnVtZXJhYmxlKCdwcm9wJykpCmNvbnNvbGUubG9nKGxpc3QucHJvcGVydHlJc0VudW1lcmFibGUoJ2xlbmd0aCcpKQovLyDqsJ3ssrTsl5DripQgaGFzT3duUHJvcGVydHnsmbjsl5Drj4QgcHJvcGVydHlJc0VudW1lcmFibGXrnbzripQg7ZWo7IiY6rCAIOyeiOuLpAovLyDsnbTqsoPsnYAg7IKs7Jqp67KV7J2AIGhhc093blByb3BlcnR57JmAIOqwmeycvOupsCDtlbTri7kg7IaN7ISx7J20IGVudW1lcmFibGXtlZzsp4Drpbwg7ZmV7J247ZW07KSA64ukCgpmb3IgKGNvbnN0IHByb3BlcnR5IGluIGxpc3QpIHsKICAgY29uc29sZS5sb2cocHJvcGVydHkpOwp9Ci8vIGZvci4uLmluIO2Yle2DnOydmCDrsJjrs7XsnYQg7IKs7Jqp7ZW07IScIGxpc3Qg6rCd7LK066W8IOyInO2ajO2VtOuztOuptCDtlbTri7kg67CY67O166y47J2YIOuwmOuzte2an+yImOuKlCBsaXN0IOqwneyytOqwgCDqsIDsp4Dqs6Ag7J6I64qUIOyGjeyEseykkSBlbnVtZXJhYmxl7ZWcIOyGjeyEseydmCDqsK/siJjrp4ztgbwg67CY67O17ZWc64ukCi8vIOq3uOumrOqzoCDrsJjrs7XtlaDrlYzrp4jri6Qg7JyEIOyYiOyLnOy9lOuTnOyXkOyEnCDsoJXtlZwg67OA7IiY7J24IHByb3BlcnR567OA7IiY66GcIOuwmOuzte2VoOuVjOuniOuLpCDsho3shLHsnbTrpoTsnbQg65Ok7Ja06rCE64ukLiDsnbTrlYwgZW51bWVyYWJsZSDtlZjsp4Ag7JWK7J2AKOyWtOuRoeqyjCDtkZzsi5zrkJjripQpIOyGjeyEseydtOumhOydgCDtj6ztlajrkJjsp4Ag7JWK64qU64ukCi8vIOymiSBsZW5ndGjripQg7JWI64KY7Jio64ukCgpsZXQgeyBwcm9wLCBsZW5ndGggfSA9IGxpc3Q7Ci8vIOydtOqxtCDslrTrlqjquYw/Cgpjb25zb2xlLmxvZyhwcm9wKQpjb25zb2xlLmxvZyhsZW5ndGgpCi8vIGxlbmd0aOuPhCDtmZXsnbjsnbQg65Cc64ukIGVudW1lcmFibGUg7ZWo6rO8IOu5hOq1rOyhsO2ZlO2VoOuLueydgCDqtIDqs4TqsIAg7JeG7J2M7J20IO2ZleyduOuQnOuLpA==
let object = { name: 'kim', age: 45 }; // 이런 오브젝트가 있다고 하자 // 이 오브젝트의 속성이름을 알아내보고자 한다 다음과 같이 하면 된다 console.log(Object.keys(object)) // 배열형태로 알수 있게 되었다 let list = ['hello', 'world']; // 여기 배열이 있다 console.log(Object.keys(list)) // 배열의 경우라면 번호를 알아낼 수 있다 // 배열의 경우는 속성이름이 번호로 되어있다고 생각하면 된다 // 물론 오브젝트처럼 이름이 번호형태가 아닌 이름을 속성으로 쓸수 있다 list.prop = 'hello'; // 이와 같이 그냥 마치 오브젝트에 속성값 넣듯이 넣을 수 있다 console.log(Object.keys(list)) // 하고서 다시 속성이름 목록을 확인해보면 추가되있는것을 볼 수 있다 console.log(list) // 이렇게까지 한 후 개발자도구의 Console탭에서 찍힌것을 펼쳐서 확인해보면 // 0, 1, prop, length 의 속성을 확인 할 수 있다 // 그런데 이상한게 하나 있다 length란건 Object.keys(list) 로 확인했을땐 없었는데말이다.. // 그리고 length는 다른것과 다르게 색이 좀 어둡다 // 그렇다 Object.keys로는 색이 어두운건 안나온다 // 하지만 어둡다하더라도 분명 length라는 속성도 list가 가진 속성임은 분명하다 console.log(Object.getOwnPropertyDescriptor(list, '0')) console.log(Object.getOwnPropertyDescriptor(list, '1')) console.log(Object.getOwnPropertyDescriptor(list, 'prop')) console.log(Object.getOwnPropertyDescriptor(list, 'length')) // 모든 속성들의 속성을 한번 Object.getOwnPropertyDescriptor 로 확인해보자 // 확인결과 length의 경우만 조금 다르다 일단 enumerable이 나머진 true인데 length만 false로 나오는점에 주목하자 // 이것이 false로 표시되면 개발자도구 Console탭에서 확인해볼때 좀 어둡게 나오고 Object.keys로도 확인이 안되는것이다 // 그러면 enumerable의 상태를 true로 바꿔볼까? Object.defineProperty(list, 'length', { enumerable: true, }); // 이렇게 하면 length의 enumerable속성을 true로 바꾸자는것인데 실행해보면 안된다 // 에러가 날건데 Cannot redefine property 라고 할것이다. 재정의 불가능하다고 한다 // 왜? 이것의 configurable 속성이 true일때만 재정의가 가능하다 // configurable의 상태는 속성의 변경 가능여부를 결정하는것이다 // 그러면 configurable를 true로 바꾼 후 다시 시도하면 될까? 아니다 configurable도 속성이기 때문이다 // 그러면 결국 Object.keys로는 0, 1, prop만 확인 가능하고 어두운 색으로 표시되는 속성, 즉 enumerable속성이 false인 속성은 확인이 안되는데 // 그럼에도 확인할 방법 없을까? console.log(Object.getOwnPropertyNames(list)) // 이렇게 하면 된다 Object.keys 대신 Object.getOwnPropertyNames 로 확인하면 다 나온다 console.log(list.hasOwnProperty('0')) console.log(list.hasOwnProperty('1')) console.log(list.hasOwnProperty('prop')) console.log(list.hasOwnProperty('length')) // 객체에는 hasOwnProperty라는 함수가 붙어있는데 이것은 인자로 넣은 문자열의 이름을 한 속성이 해당 객체에 존재하는지 확인해주는거다 // 어두운 색으로 표시되는 속성도 어쨋든 해당 객체의 속성이므로 있다는 응답(true)을 얻어낼 수 있다 console.log('0' in list); console.log('1' in list); console.log('prop' in list); console.log('length' in list); // in 키워드로 확인해봐도 hasOwnProperty와 같은 결과를 얻을 수 있다 // (in 키워드가 hasOwnProperty함수와 완전 동일한 기능을 한다는 의미는 아니다) console.log(list.propertyIsEnumerable('0')) console.log(list.propertyIsEnumerable('1')) console.log(list.propertyIsEnumerable('prop')) console.log(list.propertyIsEnumerable('length')) // 객체에는 hasOwnProperty외에도 propertyIsEnumerable라는 함수가 있다 // 이것은 사용법은 hasOwnProperty와 같으며 해당 속성이 enumerable한지를 확인해준다 for (const property in list) { console.log(property); } // for...in 형태의 반복을 사용해서 list 객체를 순회해보면 해당 반복문의 반복횟수는 list 객체가 가지고 있는 속성중 enumerable한 속성의 갯수만큼 반복한다 // 그리고 반복할때마다 위 예시코드에서 정한 변수인 property변수로 반복할때마다 속성이름이 들어간다. 이때 enumerable 하지 않은(어둡게 표시되는) 속성이름은 포함되지 않는다 // 즉 length는 안나온다 let { prop, length } = list; // 이건 어떨까? console.log(prop) console.log(length) // length도 확인이 된다 enumerable 함과 비구조화할당은 관계가 없음이 확인된다