2015년 4월 15일 수요일

[JavaScript] 자바스크립트 객체(Object)의 프로퍼티(Property)와 속성(Property Attribute)

예전에 적었던 자바스크립트 객체 소개글에서 말했던것 처럼, 객체란 여러가지 자료(Data)들과 함수(Function)들의 집합이다. 매우 간단하게 선언할 수 있고 접근될 수 있다. 이 글에서는 객체의 프로퍼티(Property)에 대해 이야기 해볼까 한다.

프로퍼티(Property)란 객체에 속한 데이터(Data)를 뜻한다. 아래의 코드에서는 name, age, occupationperson 객체의 프로퍼티가 되겠다.


var person = {
 name: "Jason",
 age: 25,
 occupation: "Student",
 getPersonProfile: function() {
  return "Name : " + this.name +
   "\nAge : " + this.age +
   "\nOccupation : " + this.occupation;
 }
};
person.newProperty = "newProperty";

console.log(person);
// { name: 'Jason',
//   age: 25,
//   occupation: 'Student',
//   getPersonProfile: [Function],
//   newProperty: 'newProperty' }

delete person.newProperty;

console.log(person);
// { name: 'Jason',
//   age: 25,
//   occupation: 'Student',
//   getPersonProfile: [Function] }

console.log(person.getPersonProfile());
// Name : Jason
// Age : 25
// Occupation : Student


위의 코드를 보면 person 객체 내부에 저 값들이 모두 저장된것 같지만, 사실 name, age, occupation 은 모두 값(Data)들이 저장된 메모리 위치를 가리킬 뿐이다. 그러므로, 프로퍼티에 저장된된 Data의 수정, 변경등은 모두 프로퍼티가 가리키는 메모리 위치에서 이루어 지는 일이다.

우리가 흔히 메소드(Method)라 부르는 항목은, 객체 내부에서 프로퍼티로 선언된 함수(Function)을 뜻하며, 위의 코드에서는 returnPersonProfile 프로퍼티가 바로 메소드 이다.

프로퍼티는 객체 선언시점에서와, 선언된 이후 시점 모두에서 추가가 가능하며, delete 키워드를 이용해서 삭제가 가능하다.

프로퍼티는 named data property, named accessor property 2가지 종류로 나뉘지며 named data propertynamed accessor property든, 프로퍼티들은 총 4가지의 속성(Attribute)으로 이루어지는데, 이러한 속성(Attribute)들은 특정 조건에서 프로퍼티의 행동양식(Behavior)을 저장하며, 또한 프로퍼티의 값(Value)를 저장한다.

Data Property와 Accessor Property는 2개의 같은 속성들(Configurable, Enumerable)과 2개의 다른 다른 속성들([Writable, Value], [Get, Set])로 구성된다

Named Data Property(데이터 프로퍼티)


저장된 Data 값에 관련된 프로퍼티이며 Value를 제외한 모든 속성(Attribute)들이 true||false, boolean 값으로 이루어져 있다. 위의 Person 객체에서는 name, age, occupation 프로퍼티들이 데이터 프로퍼티에 속한다
  • Configurable
    • 해당 프로퍼티가 delete 키워드 등으로 재정의(Redefine)될 수 있음을 가리킨다
    • 객체 프로퍼티 생성시 기본값으로 true 값을 가지며 false로 변경할 경우,  해당 프로퍼티 삭제되지 못하며, 이는 해당 프로퍼티의 속성(Attribute)에도 적용된다.
    • 객체 선언시 정의되지 않은 프로퍼티 같은경우에는 기본으로 false 값을 가진다.
  • Enumerable
    • 객체가 for-in 루프를 통과할시, 해당 프로퍼티가 for-in 루프에서 반환되어야(읽혀져야) 할지를 가리킨다.
    • 기본값으로는 true 값을 가진다.
    • 객체 선언시 정의되지 않은 프로퍼티 같은경우에는 기본으로 false 값을 가진다.
  • Writable
    • 프로퍼티의 Data 값이 수정될 수 있음을 가리킨다.
    • 기본값으로는 true 값을 가진다.
  • Value
    • 프로퍼티의 Data 값이다.
    • Value가 정해지지 않은경우에는 undefined값을 가진다.
    • 위의 Person 객체의 name 프로퍼티의 value 값은 "Jason"이다.

Named Accessor Property(접근 프로퍼티)


접근 속성은 프로퍼티의 데이터 값(Value)에 대한 접근에 관련된 속성이다. 데이터를 읽어(Retrieve)오는 Get 속성과 데이터를 저장하는 Set 속성을 가지며, 프로퍼티를 읽어오고 수정하는 기능을 한다. 위의 Person 객체에서는 getPersonProfile 메소드가 바로 Get의 역할을 한다 할 수 있다.

  • Configurable
    • 해당 프로퍼티가 delete 키워드 등으로 재정의(Redefine)될 수 있음을 가리킨다
    • 프로퍼티 생성시 기본값으로 true 값을 가지며 false로 변경할 경우,  해당 프로퍼티 삭제되지 못하며, 이는 해당 프로퍼티의 속성(Attribute)에도 적용된다.
    • 객체 선언시 정의되지 않은 프로퍼티 같은경우에는 기본으로 false 값을 가진다.
  • Enumerable
    • 객체가 for-in 루프를 통과할시, 해당 프로퍼티가 for-in 루프에서 반환되어야(읽혀져야) 할지를 가리킨다.
    • 기본값으로는 true 값을 가진다.
    • 객체 선언시 정의되지 않은 프로퍼티 같은경우에는 기본으로 false 값을 가진다.
  • Get
    • 프로퍼티가 읽어질 때, 호출되는 함수를 정한다. 이 속성을 통해 프로퍼티가 읽어져 반환되기 전에 어떠한 과정을 수행할지를 정할 수 있다.
    • Get 속성에 어싸인된 함수는 Parameter를 받을 수가 없다.
    • 기본값은 undefined.
  • Set
    • 프로퍼티가 수정될 때, 호출되는 함수를 정한다. 이 속성을 통해 프로퍼티가 수정되기 전에 어떠한 과정을 수행할지를 정할 수 있다.
    • Set 속성에 어싸인된 함수는 2개 이상의 Parameter를 받을 수가 없다.
    • 기본값은 undefined.

이러한 속성을 이용해서 아래와 같이 getPersonProfile 메소드를 대체할 수 있다.


var person = {
  name: "Jason",
  age: 25,
  occupation: "Student",
};

Object.defineProperty(person, "profile", {
  get: function() {
    return "Name : " + this.name +
      "\nAge : " + this.age +
      "\nOccupation : " + this.occupation;;
  }
});

console.log(person.profile);
// Name : Jason
// Age : 25
// Occupation : Student


프로퍼티(Property) 속성(Attribute) 정의하기


프로퍼티의 속성은
  • Object.defineProperty()
  • Object.defineProperties()
두가지 메소드를 이용해서 정의가 가능하다. 두 메소드의 차이는 단일 프로퍼티를 정의하는지(defineProperty), 여러가지 프로퍼티를 정의하는지(defineProperties)이다.

Object.defineProperty()

Object.defineProperty() 메소드는 프로퍼티를 소유한 객체, 프로퍼티의 이름, 프로퍼티 속성(Attribute) 정의객체(Descriptor Object), 이렇게 3개의 매개변수(Parameter)를 받는다.

사용법은 아래와 같다.


var person = {
  name: "Jason",
  age: 25,
  occupation: "Student",
  returnPersonProfile: function() {
    return "Name : " + this.name +
      "\nAge : " + this.age +
      "\nOccupation : " + this.occupation;
  }
};

//"name" 프로퍼티 속성을 정의한다
Object.defineProperty(person, "name", {
  configurable: true,
  enumerable: false,
  writable: false,
  value: "Laura"
});

console.log(person.name); //값이 Jason에서 Laura로 변경됬다

//프로퍼티 정의 객체 이기때문에 이렇게 객체를 선언해 사용할 수도 있다
var propertyDescriptor = {
  configurable: false,
  enumerable: false,
  writable: false,
  value: "New Property Value"
};

Object.defineProperty(person, "newProperty", propertyDescriptor);

//프로퍼티를 원하는 속성으로 생성할 수도 있다.
console.log(person.newProperty);

// configurable 을 false로 설정했기 때문에 아래 코드는 에러를 발생시킨다.
delete person.newProperty;
Object.defineProperty(person, "newProperty", {
  enumerable : true
});


Object.defineProperties()


defineProperties()가 여러개의 프로퍼티를 한꺼번에 정의한다. 매개변수로는 프로퍼티를 정의할 객체, 그리고 프로퍼티들의 속성 정의객체.

사용법은 아래와 같다.


var person = {
  name: "Jason",
  age: 25,
  occupation: "Student",
};

Object.defineProperties(person, {
  name: {
    configurable: false,
    enumerable: true,
    writable: false,
    value: "Laura"
  },

  profile: {
    get: function() {
      return "Name : " + this.name +
        "\nAge : " + this.age +
        "\nOccupation : " + this.occupation;;
    }
  }
});

console.log(person.profile);
// Name : Laura
// Age : 25
// Occupation : Student


프로퍼티 속성 읽어오기


프로터티의 속성은 Object.getOwnPropertyDescriptor() 메소드를 이용해 읽어올 수 있다. 매개변수로는 프로퍼티가 속한 객체와, 프로퍼티의 이름을 받는다.


var person = {
  name: "Jason",
  age: 25,
  occupation: "Student",
};

Object.defineProperty(person, "profile", {
  get: function() {
    return "Name : " + this.name +
      "\nAge : " + this.age +
      "\nOccupation : " + this.occupation;;
  }
});

var propertyDescriptor_name = Object.getOwnPropertyDescriptor(person, "name");

console.log(propertyDescriptor_name);
// { value: 'Jason',
//   writable: true,
//   enumerable: true,
//   configurable: true }

var propertyDescriptor_age = Object.getOwnPropertyDescriptor(person, "age");
console.log(propertyDescriptor_age);
// { value: 25,
//   writable: true,
//   enumerable: true,
//   configurable: true }


var propertyDescriptor_occupation = Object.getOwnPropertyDescriptor(person, "occupation");
console.log(propertyDescriptor_occupation);
// { value: 'Student',
//   writable: true,
//   enumerable: true,
//   configurable: true }

var propertyDescriptor_Profile = Object.getOwnPropertyDescriptor(person, "profile");
console.log(propertyDescriptor_Profile);
// { get: [Function],
//   set: undefined,
//   enumerable: false,
//   configurable: false }
// 객체 선언시 내부에서 정의된 프로퍼티가 아니기 때문에 configurable 과 enumerable 값이 모두 false 이다.

댓글 없음:

댓글 쓰기