ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JavaScript - 객체
    Frontend/JavaScript 2021. 7. 6. 15:43

    - 객체 정렬 방식

    • 특별한 방식으로 정렬
      • 정수 프로퍼티는 자동으로 정렬
      • 그 외의 프로퍼티는 객체에 추가한 순서 그대로 정렬
    let codes = {
      "49": "독일",
      "41": "스위스",
      "44": "영국",
      // ..,
      "1": "미국"
    };
    
    for (let code in codes) {
      alert(code); // 1, 41, 44, 49
    }
    let user = {
      name: "John",
      surname: "Smith"
    };
    user.age = 25; // 프로퍼티를 하나 추가합니다.
    
    // 정수 프로퍼티가 아닌 프로퍼티는 추가된 순서대로 나열됩니다.
    for (let prop in user) {
      alert( prop ); // name, surname, age
    }

     

    - 정수 프로퍼티란?

    • 변형 없이 정수에서 왔다 갔다 할 수 있는 문자열을 의미
    • 문자열 '49'는 정수로 변환하거나 변환한 정수를 다시 문자열로 바꿔도 변형이 없기 때문에 정수 프로퍼티이지만,
      '+49' 와 '1.2'는 정수 프로퍼티가 아니다.
    // 함수 Math.trunc는 소수점 아래를 버리고 숫자의 정수부만 반환합니다.
    alert( String(Math.trunc(Number("49"))) ); // '49'가 출력됩니다. 기존에 입력한 값과 같으므로 정수 프로퍼티입니다.
    alert( String(Math.trunc(Number("+49"))) ); // '49'가 출력됩니다. 기존에 입력한 값(+49)과 다르므로 정수 프로퍼티가 아닙니다.
    alert( String(Math.trunc(Number("1.2"))) ); // '1'이 출력됩니다. 기존에 입력한 값(1.2)과 다르므로 정수 프로퍼티가 아닙니다.

    - 참조에 의한 객체 복사

    • 객체와 원시 타입의 근본적인 차이 중 하나는 객체는 '참조에 의해(by reference)' 저장되고 복사된다는 것
      (원시값은 '값 그대로' 저장,할당되고 복사된다.)
    • 원시값은 두 개의 독립된 변수에 각각 문자열 'Hello!'가 저장된다.
    let message = "Hello!";
    let phrase = message;

    • 객체는 변수에 객체가 그대로 저장되는 것이 아닌, 객체가 저장되어있는 '메모리 주소'인 객체에 대한 '참조 값'이 저장된다.
      • 객체는 메모리 내 어딘가에 저장되고, 변수 user엔 객체를 '참조'할 수 있는 값이 저장
      • 객체가 할당된 변수를 복사할 땐 객체의 참조 값이 복사되고 객체는 복사되지 않는다.
    let user = {
      name: "John"
    };

    • 변수는 두개이지만 각 변수엔 동일 객체에 대한 참조 값이 저장
      • 객체에 접근하거나 객체를 조작할 땐 여러 변수 사용 가능
    let user = { name: "John" };
    
    let admin = user; // 참조값을 복사함

    let user = { name: 'John' };
    
    let admin = user;
    
    admin.name = 'Pete'; // 'admin' 참조 값에 의해 변경됨
    
    alert(user.name); // 'Pete'가 출력됨. 'user' 참조 값을 이용해 변경사항을 확인함

     

    - 참조에 의한 비교

    • 객체 비교 시 동등 연산자(==)와 일치 연산자(===)는 동일하게 동작
    • 비교 시 피연산자인 두 객체가 동일한 객체인 경우에 참을 반환
    let a = {};
    let b = a; // 참조에 의한 복사
    
    alert( a == b ); // true, 두 변수는 같은 객체를 참조합니다.
    alert( a === b ); // true
    • 두 객체가 모두 비어있다는 점에서 같아 보이지만, 독립된 객체이기 때문에 일치,동등 비교하면 거짓이 반환
    let a = {};
    let b = {}; // 독립된 두 객체
    
    alert( a == b ); // false

     

    - 객체 복제, 병합과 Object.assign

    • 기존에 있던 객체와 동일하면서 독립적인 객체를 만들고 싶은 경우
    let user = {
      name: "John",
      age: 30
    };
    
    let clone = {}; // 새로운 빈 객체
    
    // 빈 객체에 user 프로퍼티 전부를 복사해 넣습니다.
    for (let key in user) {
      clone[key] = user[key];
    }
    
    // 이제 clone은 완전히 독립적인 복제본이 되었습니다.
    clone.name = "Pete"; // clone의 데이터를 변경합니다.
    
    alert( user.name ); // 기존 객체에는 여전히 John이 있습니다.
    • Object.assign 메서드를 사용해 여러 객체를 하나로 병합
    let user = { name: "John" };
    
    let permissions1 = { canView: true };
    let permissions2 = { canEdit: true };
    
    // permissions1과 permissions2의 프로퍼티를 user로 복사합니다.
    Object.assign(user, permissions1, permissions2);
    
    // now user = { name: "John", canView: true, canEdit: true }
    • 목표 객체(user)에 동일한 이름을 가진 프로퍼티가 있는 경우 기존 값이 덮어씌워 진다.
    let user = { name: "John" };
    
    Object.assign(user, { name: "Pete" });
    
    alert(user.name); // user = { name: "Pete" }
    • Object.assign을 사용하면 반복문 없이도 간단하게 객체를 복제할 수 있다.
    let user = {
      name: "John",
      age: 30
    };
    
    let clone = Object.assign({}, user);
    • ES6 spread 연산자를 통해 객체 복제 가능. 단, 1레벨에서의 얕은 복제만 가능하다.
    let user = { name: "John" };
    let clone = {...user};
    
    clone.age = 30;
    
    alert(user);     // { name: 'John' }
    alert(clone);    // { name: 'John', age: 30 }

     

    - 중첩 객체 복제

    • 객체의 프로퍼티가 객체인 경우 위와 같은 방법(Object.assign, spread 연산자)으로 복제 불가능
    let user = {
      name: "John",
      sizes: {
        height: 182,
        width: 50
      }
    };
    
    alert( user.sizes.height ); // 182
    • clone.sizes = user.sizes로 프로퍼티를 복사하는 것만으론 객체를 복제할 수 없다.
      • user.sizes는 객체이고 참조 값이 복사되기 때문
      • 위와 같이 프로퍼티를 복사하면 clone과 user는 같은 sizes를 공유하게 된다.
    let user = {
      name: "John",
      sizes: {
        height: 182,
        width: 50
      }
    };
    
    let clone = Object.assign({}, user);
    
    alert( user.sizes === clone.sizes ); // true, 같은 객체입니다.
    
    // user와 clone는 sizes를 공유합니다.
    user.sizes.width++;       // 한 객체에서 프로퍼티를 변경합니다.
    alert(clone.sizes.width); // 51, 다른 객체에서 변경 사항을 확인할 수 있습니다.
    • 중첩 객체를 복제하라면, 그 값을 검사하면서 객체인 경우 객체의 구조도 복사해주는 반복문을 사용해야 한다.
      이런 방식을 깊은 복사(deep cloning)이라고 한다.
    • 깊은 복사 시 사용되는 표준 알고리즘인 Structured cloning algorithm 을 사용하면 중첩 객체 복제 가능
    • lodash 메서드인 _.cloneDeep(obj)을 사용하면 직접 구현하지 않고도 깊은 복제 처리 가능

    [ 참고자료 ]

    https://ko.javascript.info/object

     

    객체

     

    ko.javascript.info

    https://ko.javascript.info/object-copy

     

    참조에 의한 객체 복사

     

    ko.javascript.info

     

    댓글

Designed by Tistory.