본문 바로가기

카테고리 없음

자바스크립트 객체

 

일단 객체를 설명하기 전에 데이터 타입을 짚고 넘어가 보자

자바스크립트에서 데이터 타입은 크게 두 가지 카테고리로 나뉜다.

원시 데이터 (Primitive Data)

원시 데이터는 기본적인 유형의 데이터이며, 단일데이터라고도 한다

원시 데이터는 다음과 같은 유형이 있다.

  1. String: 문자열. ex) '안녕하세요', "Hello"
  2. Number: 숫자  ex)  1, 2, 3
  3. Boolean: 참(true) 또는 거짓(false)
  4. Null: 의도적으로 값이 없음을 나타냄
  5. Undefined: 변수가 선언되었지만 값이 할당되지 않은 상태
  6. Symbol: 고유하고 변경 불가능한 값으로, 주로 객체의 키로 사용

 

객체 데이터 (Object Data)

객체 데이터는 복합적인 구조를 가진 데이터이다. 그렇기에 복합데이터라고도 한다.

객체, 배열, 함수가 객체 데이터에 해당된다.

 

 

 

원시 데이터를 할당하면

stack이라는 메모리 공간에 값 자체를 저장하며,

변수에 사용할 때, 이 값이 복사 되어 사용된다.

 

let str1 = "가나다"
let str2 = "가나다"

console.log(str1 === str2); // true

그렇기 때문에 원시데이터는 메모리 공간을 가르키는 데이터 주소가 달라도

값이 같으면 동일하다는 결과가 나온다.

 

그러나 객체의 경우는 다르다

let obj1 = {str: '가나다'};
let obj2 = {str: '가나다'};

console.log(obj1 === obj2); // false

프로퍼티들이 완전히 같아도 false가 출력된다. 왜일까?

 

변수에 객체를 할당하면 heap이라는 메모리 공간에 객체가 저장된다.

그리고 변수는 객체의 값이 아닌 이 메모리 주소를 가지게 되는데 이를 참조한다고 한다.

 

그리고 위 예시에 obj1, obj2 가 참조하고 있는 메모리 주소는 각각 다르기 때문에 false 가 나오는 것이다.

 

다시 말하자면 객체가 할당된 변수를 비교하면 값이 아닌 주소를 비교하게 되어

서로 다른 메모리 공간에 존재하기 때문에 비교에서 같지 않다고 판단되는 것이다.

 

.. 라고 알아만 두자

 

 

 

객체(object)

위에서 설명한 객체데이터(object data)에서 보면

객체(object), 배열(array), 함수(function)이 있다고 했다

근데 다이어그램 이미지에 왜 array가 없느냐면 

 데이터 타입으로써 객체와 배열 둘다 object 이기 때문이다. 같은 단어가 계속 나와서 헷갈릴 수도 있을것 같다.

let arr1 = []

console.log(typeof arr1); // object

 

암튼 다시..

 

객체의 형태

Object literal { key : value };

key와 value는 마치 변수와 변수값과 같은 관계이다.

그러나 변수 선언, 할당과는 다른 부분이 있다

//객채 속성(property) 생성 시 key에 대하여
let Alice = {
    name         : 'alice', // 일반적인 키의 형태. value에만 따옴표가있는 모습
    'hair-color' : 'green', // - 와 같은 특수문자를 사용할 시에는 key 에도 따옴표가 있어야함
    25           : 'her age', // number도 key가 될 수 있다.
    ['job']      : 'programmer'// [] 대괄호를 씌울 수도 있다
}

문자열 말고도 다른 형태로 key를 사용할 수 있다는 것.

 

그리고 value는 원시데이터, 객체데이터 모두 사용할 수 있다. 이건 좀 있다가 설명하고,

이렇게 생성된 property들은 객체를 구성하고, 객체 내에 '존재' 한다.

변수처럼 스코프(유효 범위)를 가지는 것이 아니라 개발자 필요에 의해 접근하여 사용해야 한다.

 

 

객체 속성 접근하기

console.log(Alice.name); // alice

.점을 사용하여 접근할 수 있는데 이를 마침표 표기법(dot notation) 이라고 한다. 기본적인 방법이다.

 

그러나 'hair-color', ['job'] 과 같은 속성은

키에 특수문자가 있기때문에 .으로 접근할 수 없는데

 

이럴 때는 대괄호 표기법(bracket notation) 으로 속성에 접근 가능하다.

console.log(Alice['hair-color']); // green
console.log(Alice['job']);  // programmer
console.log(Alice['name']); // alice

.을 쓰지 않고 대괄호 내에 키값을 문자열로 한번 감싸주는 형태이다.

대괄호 표기법으로는 모든 속성에 접근 가능하다.

 

 

속성 추가,삭제

만약 객체에 존재하지 않는 key 값에 접근해서 값을 할당하면, 새로운 속성이 추가된다.

Alice.address = 'seoul'

console.log(Alice.address); // seoul

 

그리고 delete 객체에 존재하는 속성에 접근하여 삭제할 수 있다. 

delete Alice.address

console.log(Alice.address); // undefined


객체 value 재할당

let profile = {
    name: 'Alice',
    age: 22
};

// 값 변경하기
profile.age = 30; // 점 표기법
profile['name'] = '김철수'; // 대괄호 표기법

console.log(profile); // { name: '김철수', age: 31 }

 

 

 

 

동적으로 객체 속성 접근하기

객체 속성에 접근하는 방법은

마침표 표기법과 대괄호 표기법이 있는데 보통 많이 보이는 사용되는 것은 마침표 표기법이다.

그 이유는 key 값에 특수문자 등은 지양되고, 순수한 문자를 사용하는 것이 일반적이기 때문이다.

 

그러나 반드시 대괄호 표기법을 사용해야 하는 상황이 있는데

그것은 바로 매개변수로 동적 접근해야하는 상황이다.

const profile = {
	name: '홍길동',
	age: 22
}

function getValue(obj, key) {
	return obj.key;
}

console.log(getValue(profile, 'name')); // undefined

속성을 호출하는 함수를 만들었다.

 

obj.key 에서, profile 이라는 객체명은 대입되었지만

마침표 표기법은 객체에 실제로 존재하는 속성 이름만 사용할 수 있기에

profile.key로 해석이 된다.

그리고 객체 profile 에는 key 라는 속성이 없기에 당연히 undefined 이 출력되는 것이다.

 

const profile = {
	name: '홍길동',
	age: 22
}

function getValue(obj, key) {
	return obj[key];
}

console.log(getValue(profile, 'name')); //홍길동

대괄호 표기법을 사용해야 그제서 매개변수로 인식이된다.

 

그렇기에 이러한 동적인 접근에서는 대괄호 표기법을 사용해야 접근이 가능하다

const profile = {};

function addKey(obj, key, value) {
	obj[key] = value;
	
}

addKey(profile, 'name', '홍길동');

동적으로 속성 추가하는 상황이나

 

function deleteKey(obj, key) {
	delete obj[key];
}

deleteKey(profile, 'name');

 삭제하는 상황 등 여러 방면에서 사용되고 있다고 한다.

 

 

객체 축약형

객체의 key 값은 외부 변수에 아무런 영향을 받지 않고, 객체 내에서만 유효하다.

그렇기 때문에 접근하는 방법이 따로 존재하는 것이다.

const name = 'Alice'; //변수 name과 profime.name은 아무런 상관이 없다.
const profile = {
	name: '홍길동',
	age: 22
}

console.log(profile); //{ name: '홍길동', age: 22 }

 

이는 변수 뿐만이 아니라 매개변수도 마찬가지이다.

여기 객체를 반환하는 함수가 있다. 

function getProfile(name, age) {
	return {
		name: name,
		age: age
	}
}

console.log(getProfile('김철수', 20)); //{ name: '김철수', age: 20 }

 

위 예시를 보면 Key 값과 value의 변수가 같은데

이런 상황에서 key 값을 생략할 수 있다.

function getProfile(name, age) {
	return {
		name,
		age
	}
}

console.log(getProfile('김철수', 20)); //{ name: '김철수', age: 20 }

해당 변수가 자동으로 key값의 역할을 하게 된다 이것이 축약형

 

 

 

 

 

 

객체 관련 메서드

key값 반환

let profile = {
    name: 'Alice',
    age: 22
};

//Object 메소드
let keys = Object.keys(profile);

console.log(keys); //[ 'name', 'age' ]

 

Object.keys는 JS의 내장 메서드로, 매개변수의 key값을 배열로 반환 한다.

 

value값만 반환

let profile = {
    name: 'Alice',
    age: 22
};

let values = Object.values(profile);

console.log(values); //[ 'Alice', 22 ]

 

 

 

entries(key, value를 묶어서 배열로 반환)

let profile = {
    name: 'Alice',
    age: 22
};

let entries = Object.entries(profile);

console.log(entries); //[ [ 'name', 'Alice' ], [ 'age', 22 ] ]

 

 

assign(객체 데이터 복사하기)

let profile = {
    name: 'Alice',
    age: 22
};

let profile2 = {}; // 빈 객체

Object.assign(profile2, profile) // (복사받는객체, 원본)

console.log(profile2); //{ name: 'Alice', age: 22 }

객체의 데이터를 다른 객체에 복사하는 메서드이다.

 

profile2 = profile

이렇게 원본 값을 참조하는것과 다르다

독립된 개체에 데이터가 복사되는것이기 때문에 복사 된 이후에는 원본 데이터가 변경되어도 영향을 받지 않는다

 

Object.assign(profile2, profile, {name: "홍길동"}, {age: 25}, {address: "seoul"})

console.log(profile2); //{ name: '홍길동', age: 25, address: 'seoul' }

그리고 복사받을때, 세번째 매개변수 이후에 데이터를 입력하여 기존 데이터를 덮어쓰거나 새로 추가할 수 있다.

 

 

스프레드 연산자(spread operator)

let obj = {
    name: 'Alice',
    age: 22,
    address: 'Seoul'
};

// 객체의 모든 데이터를 불러옴
let dumped = { ...obj };

console.log(dumped); // { name: 'Alice', age: 22, address: 'Seoul' }


let arr = [1, 2, 3];
let dumpedArr = [...arr];
console.log(dumpedArr); // [1, 2, 3] // 배열도 된다

 

스프레드 연산자를 활용하여 객체 데이터 복사도 가능하다.

 

 

얕은 복사 (Shallow Copy)

그러나 assign과 스프레드 연산자로 복사를 하게 되면(배열에서는 Array.from , concat, slice 함수 등이 있음.)

객체의 속성이 다른 객체나 배열을 포함하고 있을 경우, 그 참조만 복사된다. 이를 얕은 복사라고 하는데,

얕은 복사는 객체의 최상위 속성만 복사하는 방식이다.

중첩된 객체는 원본과 동일한 참조를 공유하게 된다.

이로 인해 복사한 객체의 하위 속성을 변경하면 원본 객체에도 영향을 미치게 된다.

 

 

 

깊은 복사 (Deep Copy)

반면, 깊은 복사는 객체를 완전히 복사하여 중첩된 모든 객체와 배열도 새롭게 생성하는 방식이다.

이 경우 원본 객체와 복사된 객체는 서로 독립적으로 존재하며, 하나의 객체를 수정해도 다른 객체에는 영향을 미치지 않는다.

깊은 복사를 구현하기 위해서는 재귀 함수를 사용하거나, JSON.parse(JSON.stringify(obj))와 같은 방법을 사용할 수 있다. 이렇게 하면 모든 중첩된 속성이 완전히 복사되어, 원본 객체와 복사된 객체가 독립적으로 동작하게 된다.

function deepCopy(obj) {
    // 기본 데이터 타입은 그대로 반환
    if (obj === null || typeof obj !== 'object') {
        return obj;
    }

    // 배열인지 객체인지 확인
    const copy = Array.isArray(obj) ? [] : {};

    // 각 속성을 재귀적으로 복사
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            copy[key] = deepCopy(obj[key]);
        }
    }

    return copy;
}

// 사용 예
const original = {
    name: 'Alice',
    nested: {
        age: 25,
        hobbies: ['reading', 'gaming']
    }
};

const deepCopied = deepCopy(original);

// 깊은 복사된 객체의 속성 변경
deepCopied.nested.age = 30;
deepCopied.nested.hobbies[0] = 'traveling';

console.log(original.nested.age); // 25 (원본 객체는 변경되지 않음)
console.log(deepCopied.nested.age); // 30
console.log(deepCopied.nested.hobbies); // ['traveling', 'gaming']

 

 

불변성에 관한 내용은 알고 있었지만, 재귀함수로 복사하는 것은 이제 알게 되었다.

 

객체 매개변수 사용 시 주의점

function clog(data) { console.log(data);}여기 매개변수를 받아 그대로 콘솔로그로 출력해주는 함수가 있습니다 const value = 4;clog(value); //4value 라는 변수를 매개변수로 사용하면 그대로 4가 출력됩니다. fu

notion7815.tistory.com