JS - Object.Method

sarang_daddy·2023년 2월 5일
0

Javascript

목록 보기
14/26
post-thumbnail

Object 객체

  • 자바스크립트는 원시 값을 제외한 나머지 값(함수, 배열, 정규식 등)이 모두 객체로 구성되어있다.
  • 원시 값은 변경 불가능한 값(immutable)이지만 객체 타입의 값은 변경 가능한 값(mutable)이다.
  • 객체는 0개 이상의 프로퍼티로 구성된 집합이며, 프로퍼티는 key와 value로 구성된다.

  • 자바스크립트의 함수는 일급객체이므로 프로퍼티의 값으로 사용할 수 있다.
    객체의 프로퍼티 값이 함수로 사용될 때 이를 메서드라 부른다.

    즉, 객체는 상태를 나타내는 프로퍼티와 상태(프로퍼티)를 참조하고 조작하는 메서드로 이루어진 집합체다.

객체생성

클래스 기반 객체지향 언어는 클래스를 정의하고 필요한 시점에 new 연산자와 함께 생성자를 호출하여 인스턴스를 생성하는 방식으로 객체를 생성한다.
자바스크립트는 프로토타입 기반의 객체지향 언어로 다양한 방식으로 객체를 생성한다. 물론 클래스 방식으로의 생성 또 한 가능하다.

JS에서의 객체 생성 방법

객체 프로퍼티 접근

프로퍼티에는 마침표와 대괄호 접근 연산자로 접근 가능하다.

var person = {
  name: "kim",
};

console.log(person.name); // kim
console.log(person["name"]); // kim 
console.log(person[name]); // name is not defined

주의해야 할 점은 대괄호 연산자로 접근시 key를 ''로 감싼 문자열이여야 한다.
''가 없다면 name을 식별자(평가대상)으로 판단하여 찾지 못한다.
(key가 숫자인 경우는 '' 생략 가능하다.)

객체 프로퍼티 갱신, 생성, 삭제

var person = {
  name: "kim",
};

person.name = "Lee";
person.age = "30";

console.log(person);
// { name: 'Lee', age: '30' }

delete person.age;
console.log(person);
// { name: 'Lee' }

프로퍼티 key 생략 기능

let x = 1;
let y = 2;

let obj = {
  x: x,
  y: y,
};
console.log(obj); // { x: 1, y: 2 }

let obj2 = { x, y };
console.log(obj2); // { x: 1, y: 2 }

프로퍼티 값으로 변수를 사용하는 경우 변수 이름과 프로퍼티 key가 동일한 이름일 때 프로퍼티 key를 생략할 수 있다. key는 변수 이름으로 생성된다.

프로퍼티 key 동적 생성

const ex = "ex";
let i = 0;

const obj = {
  [`${ex}-${++i}`]: i,
  [`${ex}-${++i}`]: i,
  [`${ex}-${++i}`]: i,
};

console.log(obj);
// { 'ex-1': 1, 'ex-2': 2, 'ex-3': 3 }

얕은 복사 vs 깊은 복사

값에 의한 전달

변수에 변수를 할당했을 때 무엇이 어떻게 전달 될까?

var score = 80;
var copy = score;

console.log(score) // 80
console.log(copy) // 80 <- 값에 의한 전달

위처럼 변수에 변수를 할당하면 원시값 80이 전달 된다.
이를 값에 의한 전달이라고 한다.

다만, 값 80은 다른 메모리 공간에 저장된 별개의 값이다.

score = 100;
console.log(copy) // ? // 80 이다.

값에 의한 전달 후 score의 값을 변경해도 copy의 값은 변경되지 않는다.
최초 전달 때 별개의 저장공간에 값이 저장되었기 때문이다.

이처럼 "값에 의한 전달"은 사실 값을 전달하는 것이 아닌 메모리 주소를 전달 한다고 할 수 있다.

  • 80이 저장된 메모리 주소를 전달
  • score는 재할당으로 100이 저장된 메모리 주소를 참조 (원시값은 불변이기 때문에)
  • copy는 전달 받은 80이 저장된 메모리 주소를 계속 참조

하지만 객체는 원시값과는 다르게 mutable(변경가능) 하다.

  • 원시 값을 갖는 변수는 값을 변경하려면 재할당 해야한다.
  • 객체를 갖는 변수는 재할당 없이 객체를 변경 할 수 있다.
  • 이는 메모리의 효율성이 높아진다.
  • 하지만 여러개의 식별자가 하나의 객체를 공유 하는 부작용이 있다.(참조 주소가 같으니깐)

객체 복사의 부작용

객체의 mutable한 이유로 객체를 복사하는 경우 얕은 복사와 깊은 복사로 나뉜다.

얕은 복사

객체를 프로퍼티로 갖는 객체의 경우 한 단계(1차원)까지만 복사
: 중접된 객체는 참조 값만 복사해온다.

깊은 복사

객체에 중접되어 있는 객체(다차원)까지 모두 복사
: 중접된 객체까지 원시값처럼 복사한다.

const obj = { x: { y: 1 } };

const obj1 = { ...obj }; // 얕은 복사
console.log(obj1 === obj); // false
console.log(obj1.x === obj.x); // true

// lodash의 cloneDeep을 사용한 깊은 복사
// "npm install lodash"로 lodash 설치 후 실행
const _ = require("lodash");

const obj2 = _.cloneDeep(obj); // 깊은 복사
console.log(obj2 === obj); // false
console.log(obj2.x === obj.x); // false

즉, 원시값을 할당한 변수를 다른 변수에 할당하면 깊은 복사
객체를 할당한 변수를 다른 변수에 할당하는 것을 얕은 복사라고 할 수 있다.

  • 일반적으로 사용하는 Object.assign, ...Object는 1차원에서는 깊은 복사지만 2차원 이상 부터는 얕은 복사다.
  • 함수도 객체이기에 동일하게 적용된다.
  • 깊은 복사를 하기 위해서는 lodash같은 기능을 가져와야한다.

얕은, 깊은 복사 더 공부하기

Object 메서드 (📝 Updating)

Object.assign()

타겟 객체에 소스 객체를 복사하여 붙여 넣는다.
Object.assign(타겟객체, 소스객체)
어떤 객체를 복사하여 새로운 객체를 만들때 사용한다.

const obj1 = { 1: 1, 2: 2, 3: 3 };
const newObj = Object.assign({}, obj1);
console.log(newObj); // { '1': 1, '2': 2, '3': 3 }

const obj2 = { 1: 1, 4: 1 };
const newObj2 = Object.assign({ obj1, obj2 });
console.log(newObj2);
// { obj1: { '1': 1, '2': 2, '3': 3 }, obj2: { '1': 1, '4': 1 } }

Object.entries()

객체의 [key, value] 쌍의 배열을 반환한다.

const obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]

// array like object
const obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.entries(obj)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]

// non-object argument will be coerced to an object
console.log(Object.entries('foo')); // [ ['0', 'f'], ['1', 'o'], ['2', 'o'] ]

// Or, using array extras
Object.entries(obj).forEach(([key, value]) => {
console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});

const obj = { foo: 'bar', baz: 42 };
const map = new Map(Object.entries(obj));
console.log(map); // Map { foo: "bar", baz: 42 }

Object.freeze()

객체를 불변성으로 만들어 준다.
동결된 객체는 속성 추가, 제거, 변경이 불가해진다.

const obj = {
  prop: 42
};

Object.freeze(obj);

obj.prop = 33;
// Throws an error in strict mode

console.log(obj.prop);
// Expected output: 42

불변객체 만들기 추가 학습자료

Object.fromEntries()

[key, value] 쌍의 목록을 객체로 만든다. ex) 배열 -> 객체
Object.entries()의 반대 역할

const arr = [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ];
const obj = Object.fromEntries(arr);
console.log(obj); // { 0: "a", 1: "b", 2: "c" }

const map = new Map([ ['foo', 'bar'], ['baz', 42] ]);
const obj = Object.fromEntries(map);
console.log(obj); // { foo: "bar", baz: 42 }

const object1 = { a: 1, b: 2, c: 3 };
const object2 = Object.fromEntries(
  Object.entries(object1)
  .map(([ key, val ]) => [ key, val * 2 ])
);

console.log(object2);
// { a: 2, b: 4, c: 6 }

Object.getOwnPropertyNames()

객체의 속성을 배열로 반환한다.

var arr = ["a", "b", "c"];
console.log(Object.getOwnPropertyNames(arr));
// [ '0', '1', '2', 'length' ]

var obj = { 0: "a", 1: "b", 2: "c" };
console.log(
  Object.getOwnPropertyNames(obj).forEach((v) =>
    console.log(v + " -> " + obj[v])
  )
);

/* 
0 -> a
1 -> b
2 -> c
*/

Object.values()

객체의 속성값들을 배열로 반환한다.

var obj = { foo: 'bar', baz: 42 };
console.log(Object.values(obj)); // ['bar', 42]

// 유사 배열 (숫자를 속성으로 사용하는 객체)
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.values(obj)); // ['a', 'b', 'c']

// 유사 배열의 경의 속성으로 사용한 숫자의 크기 순으로 정렬되어 반환됩니다.
var an_obj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.values(an_obj)); // ['b', 'c', 'a']

// getFoo는 열거 가능한 속성이 아니라서 배열에 포함되지 않습니다.
var my_obj = Object.create({}, { getFoo: { value: function() { return this.foo; } } });
my_obj.foo = 'bar';
console.log(Object.values(my_obj)); // ['bar']

// 객체가 아닌 경우에는 객체로 강제로 변환되어 적용됩니다.
console.log(Object.values('foo')); // ['f', 'o', 'o']

Object.keys()

객체의 key값들을 배열로 반환한다.

// 단순 배열
const arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']

// 배열형 객체
const obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2']

// 키와 순서가 무작위인 배열형 객체
const anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); // console: ['2', '7', '100']

// getFoo 는 열거할 수 없는 속성입니다.
const myObj = Object.create({}, {
  getFoo: {
    value: function () { return this.foo; }
  }
});

모던 자바스크립트 Deep Dive를 참고했습니다.

profile
한 발자국, 한 걸음 느리더라도 하루하루 발전하는 삶을 살자.

0개의 댓글