본문 바로가기
js/개발

js object

by 냉면돈가스 2024. 11. 9.

string,array,number와 같이 object라는 자료형이 있다.

 

//오브젝트
const food = {
	name : 'hamburger',
	price : 1500
}

//배열
const foods = ['hamburger','pasta','salad']

 

배열(array)을 예를 들어 설명하자면

 

1. 먼저 둘다 여러 값들이 들어 갈 수 있다.

2. 다만 배열은 특정한 특징을 정하고 그 안에 속하는 여러가지

데이터들이 존재하는 것이고,

  -  [ foods란 배열을 특징으로 삼고 그안에 속하는 'hamburger', 'pasta', 'salad' 들이 있다. ]

3. 오브젝트는 특정한 객체를 정하고 그 객체에 대해 '팔은 두개고 다리는 세개야' 라고 하는 것처럼 설명해준다고 보면 된다.

  -  [ food의 이름은 'hamburger' 이고 가격은 1500이야 ]

 


이 오브젝트에 접근하기 위해서는

 

console.log(food.name)  // 'hamburger'
console.log(food.price) // 1500

 

' 오브젝트의 이름 뒤에 . 기호를 붙인 후 key( 속성명 )을 붙여주면 접근할 수 있다.

 

여기서 알아둘 점은 오브젝트엔 [ key ]과 [ value ] 이란 것이 있는데.

food 오브젝트의 [ name , price ] 처럼 각 값들의 id를 담당하는 부분이 [ key ]이고

그에 해당하는 [ 'hamburger' , 1500 ]과 같은 값들을 [ value ] 라고 한다.

 


※꿀팁

 

가끔 오브젝트를 다루다보면 

오브젝트의 키로 호출할때

"나는 food 오브젝트의 key로 keyName 이란 변수에 담긴 값을 쓰고 싶어";

 

이 말이 뭐냐 더 자세히 설명하면

나는 food의 price를 호출할껀데

그냥 호출하는게 아닌 keyName이란 변수에 price문자를 담아서 호출하고싶다.

ex1) //그냥 호출하는것
food.price



ex2) //변수에 key이름을 담아 호출하는것
const keyName = 'price'
food.keyName

위의 ex2)와 같은 식으로 사용해야 할 때가 있다.

이름값을 받아온후, 그걸이용해서 오브젝트를 호출해야 할 때가..

그럴때 ex2) 처럼 사용해버리면 컴퓨터는 

food의 'price'로 key를 잡는게 아니라

food의 'keyName'으로 key를 그냥 잡아버린다.

 

즉 keyname을 변수로 인식하지 못하고 string으로 인식해버린다.

 

 

이렇게 변수에 담긴 string을 이용해서 오브젝트의 key를 잡고 싶을땐

아래와 같이 사용해 주면 됨

food.keyName     // x
food[keyName] // o

보유함수들

 

- assign

 

객체의 값을 복사한다.

유사 함수로는 "spread operator"가 있음

spread operator는 기존객체를 수정하지않지만,

assign은 기존객체를 수정할 수 있다.

let a = { name: 'a' }
let b = Object.assign({age:15},a)
a // { name: 'a' }
b // { name: 'a', age: 15 }

위 예시는 assign 사용시 인자 순서의 중요성을 보면 됨
Object.assign({age:15},a)
{age:15} 라는 리터럴 객체가 앞에 위치해있음
이는 {age:15} 라는 리터럴 객체에 추가로 a 객체를 덧붙이란 뜻임
그래서 a객체가 그대로 유지될 수 있음

let a = { name: 'a' }
let b = Object.assign(a,{age:15})
a // { name: 'a', age: 15 }
b // { name: 'a', age: 15 }

위 예시는 반대로 a인자가 앞에 위치하였고,
a 객체에 추가적인 리터럴 객체를 붙이는것이기 때문에
a와 b객체가 동일한 데이터를 지니게됨

spread operator는 위 문제를 신경쓸 이유가 없다.
주관적인 생각으론 assign을 굳이 쓸 이유가 없어보임

1.
let a = { name: 'a' }
let b = { age: 15, ...a }

2.
let a = { name: 'a' }
a = { ...a, age: 15 }

assign 함수를 이용해 데이터 복사문제를 생각하기보단
a를 이용하여 새로운 변수를 생성하고 싶다면 1 예시처럼
그냥 a에 추가 데이터를 넣고 싶다면 2예시처럼 사용하면 됨

 

 

- create

 

객체를 생성하며 "부여받을 프로토타입", "프로퍼티 설정" 을 한번에 할 수 있음

다만 사용도는 낮지않을까 생각함

let o = Object.create(Object.prototype,{
  foo: { writable: true, configurable: true, value: "hello" }
});

인자로 상속받을 prototype과 상세한 속성스펙을 전달한다.
다만 보통의 경우에선 특별하게 prototype 상속을 기입한다거나,
속성스펙도 수정할 일이 적어 잘 사용하지 않을 것 같음

클래스나 프로토타입을 따로 만들어 상속하고
+ 속성스펙도 수정불가하게만든다거나 하는 설정이
동시에 들어가야하는게 아닌이상 쓰지 않을 것 같다..

 

 

- defineProperties

 

위의 create 함수 기능중 "프로토타입 설정" 을 제외한 함수

"프로퍼티 설정" 만을 상세하고 간편하게 할 수 있음

create보단 사용도가 높을듯

물론 "defineProperty" 함수를 통해 개별 프로퍼티만 설정이 가능하다.

const object1 = {};

let c = Object.defineProperties({}, {
  property1: {
    value: 42,
    writable: true,
  },
  property2: {},
});

 

 

- entries

 

Object 객체의 "키,값" 정보를 배열로 반환해 주는 함수

const object1 = {
  a: 'somestring',
  b: 42,
};

let b = Object.entries(object1)
b // [["a",'somestring'],['b',42]]

이를 이용해 forEach, for of 등 반복문 수행이 수월해짐

예시1.
Object.entries(object1).forEach((e)=>{console.log(e)});

예시2.
for (const [key, value] of Object.entries(object1)) {
  console.log(`${key}: ${value}`);
}

"Object.keys", "Object.values" 함수를 통해 키나 값만 배열로 받아올 수도 있음

 

 

- fromEntries

 

['key', 'value'] 유형의 배열객체를 Object.entries와 반대로 객체형태로 반환해 주는 함수

const cctv = [
 {cctvCd:'01',name:'첫번째'},
 {cctvCd:'02',name:'두번째'},
 {cctvCd:'03',name:'세번째'}
]

위 배열을 재구성하여 새 객체를 생성함
fromEntries에 전달할 인자는 ["key", "value"] 배열로 구성되어야 함

(예시)
cctv 배열객체를 아래와 같이 수정하려한다.
{ 
 01: {
  cctvCd: '01',
  name: '첫번째'
 },
 02: {
  cctvCd: '02',
  name: '두번째'
 },
 03: {
  cctvCd: '03',
  name: '세번째'
 }
} 
그러려면 [[01,{cctvCd: '01', name: '첫번째'}]] 처럼 인자 데이터 형식이 구성되어야함

let a = Object.fromEntries([
 [01,{cctvCd: '01', name: '첫번째'}],
 [02,{cctvCd: '02', name: '두번째'}],
 [03,{cctvCd: '03', name: '세번째'}]
])
a // { 
 1: {cctvCd: '01', name: '첫번째' }, 
 2: {...}, 
 3: {...} 
}

그런데 위 예시처럼 일일히 인자를 넣어주긴 귀찮으니
map함수와 같이 반복함수를 사용하여 콜백형태로 이용

Object.fromEntries(cctv.map((value) => [
    value.cctvCd, value
]));

추가예시 (단순 형태변경이 아닌 추가 계산도 가능)
Object.fromEntries(cctv.map((value,i) => [
    value.cctvCd + 3 , {...value, index:i}
]));

 

 

- freeze, seal, preventExtensions

 

ㄱ. freeze

객체동결기능 제공

defineProperty를 통해

writable과 configurable을 설정해 동결시킬 수 있지만,

freeze를 통해 간편하게 동결가능

Object.isFreeze 메서드를 통해 확인가능

let a = {age:15};
Object.freeze(a);

 

ㄴ. seal

freeze보다 약한동결

writable: true인 값에 한해 value만 변경 가능

객체의 구조자체만 유지하고싶다면 freeze보다 seal이 적당함

isSealed 메서드를 통해 확인가능

let a = {age:15};
Object.seal(a);
delete a.age; // error or 무변화
a.age = 13 // 정상작동

 

ㄷ. preventExtensions

삭제,수정 가능

단 확장 불가

isExtensible 메서드를 통해 확인가능

let a = {age:15};
Object.preventExtensions(a);

delete a.age; // 
a // {}

a.age = 13;
a // {}

 

 

- groupBy

 

배열객체를 기준에 따라 그룹핑해줌

 

예시 1
const a = [1,2,3,4,5]
Object.groupBy(a,(c)=>{return c>3 ? 'small' : 'big'});
// {big: Array(3), small: Array(2)}

예시 2
const students = [
  { name: 'a', grade: 'A' },
  { name: 'b', grade: 'B' },
  { name: 'c', grade: 'A' },
  { name: 'd', grade: 'C' },
  { name: 'e', grade: 'B' }
];
Object.groupBy(students, (c) => {return c.grade});
// 위 결과는 아래와 같음
{
  A: [
    {
      name: 'a', 
      grade: 'A'
    },
    {
      name: 'c', 
      grade: 'A'}
  ],
  B: [
    {
      name: 'b', 
      grade: 'B'
    },
    {
      name: 'e', 
      grade: 'B'}
  ],
  C: [
    {
      name: 'd', 
      grade: 'C'
    },
  ]
}

 


- getOwnPropertyDescriptor

- getOwnPropertyDescriptors

- getOwnPropertyNames

 

프로퍼티의 정보를 가져옴

const a = {
  name: 'a'
};

Object.getOwnPropertyDescriptor(a,'name') // value, writable, enumerable 등을 반환받음
// 첫번째 인자로 오브젝트, 두번째 인자로 프로퍼티명을 전달

Object.getOwnPropertyDescriptors(a) // {name:{value:'a',writable:true,...}, ...} 
// 인자로 오브젝트를 전달

Object.getOwnPropertyNames(a) // ['name']
Object.keys(a) // ['name']

keys와 getOwnPropertyNames의 차이는 반환값 필터에 enumerable 값을 체크함
keys: 
  enumerable true인것만 반환
getOwnPropertyNames: 
  enumerable false것도 반환
  
Object.defineProperty(a,'test',{value:'test',enumerable:false})
Object.getOwnPropertyNames(a) // ['name','test']
Object.keys(a) // ['name']

 

 

- valueOf

- toString

 

valueOf는 객체의 원시값, toString은 객체의 문자열형태로 반환함

유사점은

  valueOf는 객체의 비교시 자동으로 valueOf의 반환값을 이용해 비교하고,

  toString은 +를 이용하여 다른 문자열과 연산시 자동으로 toString을 이용해 문자화한다.

 

비교시,연산시에는 객체의 값을 순수하게 반환하는데,

toStirng이나 valueOf 메소드를 재정의하여 상수값이나, 추가 계산이 첨부된 값을 반환하는것도 가능하다.

const a = {}
a.valueOf = () => 100;
a == 100 // true

 

 

- is

 

두 값이 같은 값인지 평가

==, ===와 다르다함

얼핏보기엔 ===와 유사

(일반적인상황에선 사용성이 높지않아보임)

 

+0, -0을 비교할때

===는 결국 같은값을 가리키고 있기때문에 true를 반환함

그러나 Object.is에서는 false를 반환함

이유는 명확하게 모르겠음

 [],[] 를 인자로 주었을땐 '===' 와 같이 false를 반환함

 

'js > 개발' 카테고리의 다른 글

js Class  (0) 2024.10.15
js 2진수, 8진수 사용하기  (0) 2024.10.13
js Object Literal Syntax Extension (키 값 동적으로 생성)  (0) 2024.10.13
js rest parameters  (0) 2024.10.08
js async & await  (0) 2024.08.07

댓글