Hits

🌟 Property attribute 와 Property descriptor.

자바스크립트 엔진은 프로퍼티를 생성할 때, 프로퍼티의 상태를 나타내는 Property Attribute를 기본값으로 자동 정의한다.

const person = {
  name: "Lee",
};
console.log(Object.getOwnPropertyDescriptor(person, "name"));
// {value: 'Lee', writable: true, enumerable: true, configurable: true}
const person = {
  name: "Lee",
};
console.log(Object.getOwnPropertyDescriptor(person, "name"));
// {value: 'Lee', writable: true, enumerable: true, configurable: true}

프로퍼티의 상태란 프로퍼티의 값(value), 갱신 가능 여부(writable), 열거 가능 여부(enumerable), 재정의 가능 여부(configurable)을 말한다.

Property attribute는 자바스크립트 엔진이 관리하는 내부 상태 값인 내부 슬롯이다. 따라서, 직접 접근할 수 없지만, Object.getOwnPropertyDescriptor 메서드를 사용해 간접적으로 확인할 수 있다.


🌟 Data property 와 Accesor property

프로퍼티는 데이터 프로퍼티(data property)접근자 프로퍼티(accesor property)로 구분할 수 있다
데이터 프로퍼티는 키와 값으로 구성된 일반적인 프로퍼티이다. (위에서 살펴본 value, writable, enumerable, configurable 이 데이터 프로퍼티의 프로퍼티 어트리뷰트이다)
접근자 프로퍼티는 자체적으로는 값을 갖지 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 호출되는 접근자 함수로 구성된 프로퍼티다.
접근자 프로퍼티는 다음과 같은 프로퍼티 어트리뷰트를 갖는다.

  • [[Get]] : 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 읽을 때 호출되는 접근자 함수다.
  • [[Set]] : 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 저장할 때 호출되는 접근자 함수다.
  • [[Enumerable]]
  • [[Configurable]]
    접근자 함수는 getter/setter 함수라고도 부른다.
const person = {
  firstName: "Ungmo",
  lastName: "Lee",
 
  //getter함수
  get fullName() {
    return `${this.firstName} ${this.lastName}`;
  },
 
  //setter함수
  set fullName(name) {
    [this.firstName, this.lastName] = name.split(" ");
  },
};
 
//데이터 프로퍼티를 통한 값의 참조
console.log(person.firstName + " " + person.lastName); // Ungmo Lee
 
//접근자 프로퍼티를 통한 값의 저장, setter함수 호출
person.fullName = "Heegun Lee";
console.log(person); // {firstName: 'Heegun', lastName: 'Lee'}
 
console.log(person.fullName); // Heegun Lee
 
let descriptor = Object.getOwnPropertyDescriptor(person, "firstName");
console.log(descriptor);
// {value: 'Heegun', writable: true, enumerable: true, configurable: true}
 
descriptor = Object.getOwnPropertyDescriptor(person, "fullName");
console.log(descriptor);
//fullName은 접근자 프로퍼티이기 때문에, 아래의 프로퍼티 어트리뷰트를 갖는다
// {enumerable: true, configurable: true, get: ƒ, set: ƒ}
const person = {
  firstName: "Ungmo",
  lastName: "Lee",
 
  //getter함수
  get fullName() {
    return `${this.firstName} ${this.lastName}`;
  },
 
  //setter함수
  set fullName(name) {
    [this.firstName, this.lastName] = name.split(" ");
  },
};
 
//데이터 프로퍼티를 통한 값의 참조
console.log(person.firstName + " " + person.lastName); // Ungmo Lee
 
//접근자 프로퍼티를 통한 값의 저장, setter함수 호출
person.fullName = "Heegun Lee";
console.log(person); // {firstName: 'Heegun', lastName: 'Lee'}
 
console.log(person.fullName); // Heegun Lee
 
let descriptor = Object.getOwnPropertyDescriptor(person, "firstName");
console.log(descriptor);
// {value: 'Heegun', writable: true, enumerable: true, configurable: true}
 
descriptor = Object.getOwnPropertyDescriptor(person, "fullName");
console.log(descriptor);
//fullName은 접근자 프로퍼티이기 때문에, 아래의 프로퍼티 어트리뷰트를 갖는다
// {enumerable: true, configurable: true, get: ƒ, set: ƒ}

메서드 앞에 get, set이 붙은 메서드가 있는데, 이것들이 바로 gettersetter함수이고, getter/setter함수의 이름 fullName이 접근자 프로퍼티이다.
접근자 프로퍼티는 자체적으로 값(value)를 갖지 않고 데이터 프로퍼티의 값을 읽거나 저장할 때 관여할 뿐이다.


🌟 프로퍼티 정의

프로퍼티 정의란 새로운 프로퍼티를 추가하면서 프로퍼티 어트리뷰트를 명시적으로 정의하건, 기존 프로퍼티의 프로퍼티 어트리뷰트를 재정의하는 것을 말한다.

const person = {};
 
// 데이터 프로퍼티 정의
Object.defineProperty(person, 'firstName',{
value : "ungmo",
writable : true,
enumerable : true,
configurable : true,
}
 
// 접근자 프로퍼티 정의
Object.defineProperty(person, 'fullName',{
get(){
return `${this.firstName} ${this.lastName}`
},
 
    set(name){
        [this.firstName,this.lastName] = name.split(' ');
    },
 
    enumerable : true,
    configurable : ture
 
}
const person = {};
 
// 데이터 프로퍼티 정의
Object.defineProperty(person, 'firstName',{
value : "ungmo",
writable : true,
enumerable : true,
configurable : true,
}
 
// 접근자 프로퍼티 정의
Object.defineProperty(person, 'fullName',{
get(){
return `${this.firstName} ${this.lastName}`
},
 
    set(name){
        [this.firstName,this.lastName] = name.split(' ');
    },
 
    enumerable : true,
    configurable : ture
 
}

🌟 객체 변경 방지

자바스크립트 객체는 변경 가능한 값이므로, 직접 변경할 수 있다. 이를 방지하는 다양한 메서드 또한 존재한다.

객체 확장 금지

Object.preventExtensions 메서드는 객체의 확장을 금지한다. 확장이 금지된 객체는 프로퍼티 추가가 금지된다.

const person = { name: "Lee" };
 
Object.preventExtensions(person);
 
person.age = 20;
// 프로퍼티 추가가 금지된다.
// strict mode에서는 에러발생
 
delete person.name;
// 프로퍼티 삭제는 가능
const person = { name: "Lee" };
 
Object.preventExtensions(person);
 
person.age = 20;
// 프로퍼티 추가가 금지된다.
// strict mode에서는 에러발생
 
delete person.name;
// 프로퍼티 삭제는 가능

객체 밀봉

Object.seal 메서드는 객체를 밀봉한다. 밀봉된 객체는 읽기와 쓰기만 가능하다.

const person = { name: "Lee" };
 
Object.seal(person);
 
person.age = 20; //금지
 
delete person.name; //삭제 또한 금지
 
person.name = "Kim"; //값 갱신은 가능
const person = { name: "Lee" };
 
Object.seal(person);
 
person.age = 20; //금지
 
delete person.name; //삭제 또한 금지
 
person.name = "Kim"; //값 갱신은 가능

객체 동결

Object.freeze 메서드는 객체를 동결한다. 동결된 객체는 읽기만 가능하다.

const person = { name: "Lee" };
 
Object.seal(person);
 
person.age = 20; //금지
 
delete person.name; //삭제 또한 금지
 
person.name = "Kim"; //갱신 또한 불가
const person = { name: "Lee" };
 
Object.seal(person);
 
person.age = 20; //금지
 
delete person.name; //삭제 또한 금지
 
person.name = "Kim"; //갱신 또한 불가