일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 호이스팅
- 코테
- 백준
- 자바스크립트
- CSS
- KAKAO
- cpu
- 컴퓨터공학
- 컴퓨터과학
- 부트캠프
- 국비지원취업
- 코딩테스트
- BFS
- 야놀자
- js
- github
- git
- CS
- nodejs
- 패스트캠퍼스
- html/css/js
- 그리디
- LinkSnap
- Javascript
- computerscience
- 프론트엔드개발자
- 알고리즘
- 너비우선탐색
- 국비지원
- DFS
- Today
- Total
My Boundary As Much As I Experienced
내부 슬롯과 내부 메서드, 프로퍼티 어트리뷰트 본문
정의
내부 슬롯과 내부 메서드는 ECMAScript에서 정의한 의사 프로퍼티Pseudo Property, 의사 메서드Pseudo Method이다.
(css의 가상 선택자Pseudo Selector처럼, 실제로 있는 태그는 아니지만 기능 상 존재하는..? 느낌인듯!)
ECMAScript 사양에 정의된 대로 구현되고 JS 엔진에서 실제로 동작하는 방식을 구성한다.
그러나 개발자가 직접 접근하거나 호출할 수 있도록 공개된 객체의 프로퍼티는 아니다.
내부 슬롯과 내부 메서드는 형태는 이중 대괄호로 감싸서 표현된다.
실제 확인 방법
우리가 한 번 쯤 들어본 [[prototype]]도 내부 슬롯이다. 직접 [[prototype]]을 프로퍼티 체이닝으로 접근할수는 없지만
객체를 console.log해보면 개발자 도구에서 맨 하단에서 확인할 수 있다.
const o = {};
// 내부 슬롯은 자바스크립트 엔진의 내부 로직이므로 직접 접근할 수 없다.
o.[[prototype]] // -> Uncaught SyntaxError: Unexpected token '['
// 단, 일부 내부 슬롯과 내부 메서드에 한하여 간접적으로 접근할 수 있는 수단을 제공하기는 한다.
o.__proto__ // -> Object.prototype
내부 슬롯은 자바스크립트 엔진의 내부 로직이므로 원칙적으로 직접 접근할 수 없지만 [[Prototype]] 내부 슬롯의 경우, __proto__를 통해 간접적으로 접근할 수 있다.
__proto__는 [[Prototype]]이란 내부 슬롯에 접근하기 위한 프로퍼티이지만 es6부터는 공식적인 표준은 아니게 되었다.
대신에 Object.getPrototypeOf() 및 Object.setPrototypeOf() 메서드를 사용하여 객체의 프로토타입에 접근하는 것이 권장된다.
직접적으로 접근할 수 없는 이유
캡슐화(encapsulation): 내부 슬롯은 객체의 내부 상태를 나타내며, 이를 외부에서 직접적으로 조작하는 것은 객체의 캡슐화 원칙을 위반할 수 있다. 객체의 내부 상태에 대한 접근을 허용하면 다른 코드에서 이를 부적절하게 변경할 수 있으며, 이는 코드의 안정성과 예측 가능성을 저해할 수 있기 때문이다.
호환성과 보안(Security): 직접적인 내부 슬롯 접근은 보안 문제를 야기할 수 있다. 언어의 특정 구현에 의존하는 코드는 플랫폼이나 환경에 따라 다르게 동작할 수 있으며, 이는 코드의 이식성과 호환성을 저해할 수 있다.
프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체
자바스크립트 엔진은 프로퍼티를 생성할 때 프로퍼티의 상태를 나타내는 프로퍼티 어트리뷰트(property attributes)를 기본값으로 자동 정의한다.
프로퍼티의 상태란 프로퍼티의 값[[Value]], 값의 갱신 가능여부[[Writable]], 열거 가능 여부[[Enumerable]], 재정의 가능 여부[[Configurable]] 등이 있다.
이런 프로퍼티 어트리뷰트에 직접 접근할 수는 없지만, Object.getOwnPropertyDescriptor() 메서드를 사용하여 간접적으로 확인할 수는 있다.
이 때 첫 번째 매개변수에 객체의 참조, 두 번째 매개변수에는 프로퍼티 키를 문자열로 전달하면 프로퍼티 디스크립터 객체(property attributes)를 반환합니다. 만약 존재하지 않는 프로퍼티를 제공하면 undefined가 뜬다.
Object.getOwnPropertyDescriptor(객체참조, 프로퍼티키)
const person = {
name: 'Lee'
};
// 프로퍼티 어트리뷰트 정보를 제공하는 프로퍼티 디스크립터 객체를 반환한다.
console.log(Object.getOwnPropertyDescriptor(person, 'name'));
// {value: "Lee", writable: true, enumerable: true, configurable: true}
데이터 프로퍼티, 접근자 프로퍼티란?
데이터 프로퍼티
키와 값으로 구성된 일반적인 프로퍼티, 모든 프로퍼티는 데이터 프로퍼티이다. (앞서 예시로 든 것들은 모두 데이터 프로퍼티다)
- [[Value]] : 프로퍼티 키를 통해 프로퍼티 값을 접근하면 반환되는 값이다. 프로퍼티 키를 통해 프로퍼티 값을 변경하면 [[Value]]에 값을 재할당한다. 이 때 프로퍼티가 없으면 프로퍼티를 동적 생성하고 생성된 프로퍼티 [[Value]]에 값을 저장한다.
- [[Writable]] : 프로퍼티 값의 변경 가능 여부를 나타내며 boolean 값을 갖는다.
- [[Enumerable]] : 프로퍼티의 열거 가능 여부를 나타내며 boolean 값을 갖는다. false이면 for ... in 이나 Object.keys 메서드 등으로 열거할 수 없다.
- [[Configurable]] : 프로퍼티의 재정의 가능 여부를 나타내며 boolean값을 갖는다. false이면 삭제나 변경이 금지 된다. 단, [[Writable]]이 true인 경우는 value 변경과 writable을 false로 변경하는 것이 허용된다.
접근자 프로퍼티
자체적으로 값을 갖지 않고, 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 호출되는 접근자 함수(accessor function)로 구성된 프로퍼티이다.
- [[Get]] : 접근자 프로퍼티를 통해 데이터 프로퍼티 값을 읽을 때 호출되는 접근자 함수이다. 즉, 접근자 프로퍼티 키로 프로퍼티 값에 접근하면 프로퍼티 어트리뷰트 [[Get]]의 값, getter 함수가 호출되고 그 결과가 프로퍼티 값으로 반환되는 것이다.
- [[Set]] : 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 저장할 때 호출되는 접근자 함수이다. 즉, 접근자 프로퍼티 키로 프로퍼티 값을 저장하면 프로퍼티 어트리뷰트 [[Set]]값, 즉 setter 함수가 호출되고 그 결과가 프로퍼티 값으로 저장된다.
- [[Enumerable]] : 데이터 프로퍼티의 enumerable과 같다.
- [[Configurable]] : 데이터 프로퍼티의 configurable과 같다.
접근자 함수는 getter/setter라고 불리고 정의가능하다.
프로퍼티 정의 (프로퍼티 어트리뷰트 정의)
프로퍼티 정의란 새로운 프로퍼티를 추가하면서 프로퍼티 어트리뷰트를 명시적으로 정의하거나, 기존 프로퍼티의 프로퍼티 어트리뷰트를 재정의하는 것을 말한다. 예를 들어 프로퍼티 값을 갱신 가능하도록 할 것인지, 프로퍼티를 열거 가능하도록 할 것인지, 프로퍼티를 재정의 가능하도록 할 것인지 정의할 수 있다. 이를 통해 객체의 프로퍼티가 어떻게 동작해야 하는지를 명확히 정의할 수 있다.
Object.defineProperty() 메서드를 사용하면 프로퍼티의 어트리뷰트를 정의할 수 있다. 인수로는 객체의 참조와 데이터 프로퍼티의 키인 문자열, 프로퍼티 디스크립터 객체를 전달한다.
- Object.defineProperty 메서드 : 한번에 하나의 프로퍼티만 정의할 수 있다.
- Object.defineProperties 메서드 : 여러 개의 프로퍼티를 한 번에 정의할 수 있다.
[[Writable]]을 수정 못하게 막는 예시
const person = {};
Object.defineProperty(person, 'name',{
writable: false, // 값 수정 불가 처리
configurable: true,
enumerable: true,
value: 'name'
});
person.name = 'sungIn'; // 수정을 못하게 해서 변경되지 않습니다.
console.log(person.name); // name
객체 변경 감지 (확장금지, 밀봉, 동결)
Object.preventExtension(obj) => 추가가 안 된다.
Object.seal(obj) => 추가, 삭제, 재정의가 안 된다.
Object.freeze(obj) => 읽기 빼곤 다 안 된다.
'FrontEnd > Javascript(Vanilla)' 카테고리의 다른 글
함수와 일급 객체 (+ arguments 객체) (0) | 2024.02.26 |
---|---|
생성자 함수와 callable, constructor (0) | 2024.02.22 |
변수 호이스팅 [심화] (0) | 2024.02.19 |
XMLHttpRequest는 뭐고 AJAX는 뭘까? (1) | 2023.12.10 |
정확히 Promise객체는 뭘까? (1) | 2023.12.09 |