JavaScript/ES6+

enhanced object functionality

jaiyah 2021. 2. 26. 18:39

이 글은 [인프런] Javascript ES6+ 제대로 알아보기 - 초급(정재남)를 토대로 작성되었음을 알려드립니다.


계산된 프로퍼티명, 고정된 프로퍼티 열거 순서

먼저 계산된 프로퍼티명에 대한 내용을 알아보도록 하자.

 

computed property name (계산된 프로퍼티명)

다음의 계산된 프로퍼티명에 대한 예제를 살펴보면서 알아보자.

js
var className = ' Class';
var obj = {};

obj.'ab cd' = 'AB CD'; // 잘못된 문법
obj['ab cd'] = 'AB CD'; // 올바른 문법

console.log( obj );

obj = {
    'ab cd' : 'AB CD'
};

// 규칙이 혼동스러운 부분
var obj2 = {
    'A' + className : 'A급'
};
obj2['A' + className] = 'A급';

ES5는 위와 같은 문법으로 혼동스러운 부분이 있었으나 ES6에서는 다음과 같이 객체 리터럴에서도 대괄호([]) 표기법을 제공하고 있습니다.

js
var className = ' Class';

var obj2 = {
    ['A' + className] : 'A급'
};
obj2['A' + className] = 'A급';

기존에는 객체를 선언하는 순간이 아닌 객체리터럴이 이미 생성(선언)된 이후에 프로퍼티 하나씩만 추가할 때에는 가능했지만 내부에서 변수명을 위와 같이 조합해서 작성하는 것이 불가능했었습니다.   즉, 외부에서만 작성이 가능했습니다.
이제  ES6부터는 객체리터럴을 선언하는 순간에도 바로 작성이 가능한 것입니다.

 

위에서 살펴봤 듯이 계산된 것이 가능하기 때문에 다음과 같은 코드 작성이 가능할 수 있습니다.

js
 let suffix = ' name';
let iu = {
    ['last' + suffix]: '이',
    ['first' + suffix]: '지은'
};

console.log(iu);

 

재미삼아 분석해 보는 쉬어가는 코너

js
// 너무 줄여놓은 거 아니야 ?! 좀 알아보게 해주면 안될까요? ㅠ
const counter = ((c) => () => c++)(0);

var obj = {
    [`a_${counter()}`] : counter(),
    [`a_${counter()}`] : counter(),
    [`a_${counter()}`] : counter()
};

console.log( obj );

 

Detail Info

1)  객체 리터럴 선언시 프로퍼티 키값에 대괄호 표기로 접근 가능

2)  대괄호([ ]) 내에는 값 또는 식을 넣어 조합할 수 있음

 

 

 

own property enumeration order (고정된 프로퍼티 열거 순서)

먼저 예제를 살펴보도록 하자.

js
const obj1 = {
    c: 1,
    2: 2,
    a: 3,
    0: 4,
    b: 5,
    1: 6
};

const keys1 = [];
for (const key in obj1) {
    keys1.push(key)
}

console.log(keys1);
console.log(Object.keys(obj1));
console.log(Object.getOwnPropertyNames(obj1));

위 에제는 객체와 빈 배열을 생성하여  for~in문을 사용해 빈 배열에  key 를 추가하는 코드입니다.
로그를 확인해 보면 숫자가 먼저 오고, 작은 수에서 큰 수로 그 다음 문자가 입력된 순서대로 출력되는 것을 알 수 있습니다.
이렇게 기존에는 의미없는 정렬을 하였지만  ES6부터는 숫자별, 문자별로 구성하여 차례로 열거 순서를 맞추어 나열하게 됩니다.

 

다른 예제를 살펴보도록 하겠습니다.

js
const obj2 = {
    '02': true,
    '10': true,
    '01': true,
    '2': true,
};

const keys2= [];
for(const key in obj2) {
    keys2.push(key)
}

console.log(keys2);
console.log(Object.keys(obj2));
console.log(Object.getOwnPropertyNames(obj2));
console.log(Reflect.ownKeys(obj2));

위에서 살펴본 내용에 따르면 위 예제는 숫자지만 문자열이기 때문에 문자는 입력된 순서대로 출력된다고 했는데 그렇지 않은 것을 알 수 있습니다.
잘 생각해 보면 객체 프로퍼티는 본래 문자열로 구성됩니다.   하지만 숫자를 입력 받았을 때 숫자로서의 조건들이 있습니다.
숫자인데 첫 글자가 0이 아닌 경우에 숫자로 인식하게 됩니다.

 

객체를 병합했을 경우의 예제를 살펴보도록 하자.

js
const obj1 = {
    c: 1,
    2: 2,
    a: 3,
    0: 4,
    b: 5,
    1: 6
};

const obj2 = {
    '02': true,
    '10': true,
    '01': true,
    '2': true,
};

const obj3 = Object.assign({}, obj1, obj2);

const keys3= [];
for(const key in obj3) {
    keys3.push(key)
}

console.log(keys3);
console.log(Object.keys(obj3));
console.log(Object.getOwnPropertyNames(obj3));
console.log(Reflect.ownKeys(obj3));

위 예제는 객체의 스태틱 메소드인  assign을 이용하여 객체를 병합하여  key를 열거해 보는 코드입니다.
로그를 확인해 보면 지금까지 확인해 본 규칙에 의해 출력되는 것을 확인할 수 있습니다.

 

 

Detail Info

1)   열거순서는 다음 규칙을 따른다.

  • number,  string,  symbol 의 순서로 정렬된다.
  • number key는 프로퍼티들 중 가장 앞에 위치하며, 오름차순이다.
  • string key는 객체에 추가된 당시의 순서를 유지하면서 숫자 뒤에 위치한다.
  • Symbol key는 객체에 추가된 당시의 순서를 유지하면서 제일 마지막에 위치한다.

2)  number(index)로 인식하는 key는 다음과 같다.

  • 0 이상의, 첫째자리가 0이 아닌 수는, 문자열로 입력해도 똑같이 숫자로 인식한다.
  • 첫 째자리가 0인 두자리 이상의 숫자는 문자열로 입력해야 하고, 문자열로 인식한다.
  • 음수는 문자열로 입력해야 하고, 문자열로 인식한다.

*  'index'로 인식할 수 있는 경우에 한해서만 작은 수부터 나열한다.

3)   열거순서를 엄격히 지키는 경우는 다음과 같다.

  • Object.getOwnPropertyNames()
  • Reflect.ownKeys()
  • Object.assign()

4)   ES5 하위문법인 다음의 경우에는 정확성을 보장하지 않는다.

  • for in
  • Object.keys()
  • JSON.stringify()

 

위 예제로 알아본 바 Object.keys() 는 순서를 보장한 것처럼 보이지만 이는 브라우저 제조사마다 제각각이기 때문에 주의해야 한다.
즉, 어떤 환경이느냐에 따라 출력 결과가 달라질 수 있지만 새로 등장한 ES6의 메소드들은 브라우저 제조사들 모두 표준 스펙을 잘 따르고 있기 때문에 순서를 보장합니다.   결론은  ES5 시절에 사용되던 문법은 순서를 보장하지 않는다는 점만 숙지하자.

 

 

Jaehee's WebClub