Mixin

Doum Kim·2020년 3월 20일
0

Javascript

목록 보기
4/23
post-thumbnail
post-custom-banner

📌 Mixin 함수

믹스인이란 특정 객체에 다른 객체가 가지고 있는 프로퍼티를 붙여 넣어 '뒤섞는' 기법을 말한다.
상속을 사용하지 않고 특정 객체의 프로퍼티를 동적으로 다른 객체에 추가한다.

const mixin = (target , source) => {
  for(let prop in source) {
    if(source.hasOwnProperty(prop)) {
      target[prop] = source[prop];
    }
  }
  return target;
}

mixin 함수의 첫 번째 인수가 타깃 객체이며 두 번째 인수가 프로퍼티를 제공하는 원본 객체이다. 문자열을 키로 가지는 프로퍼티만 복사한다. 즉 심벌을 키로 갖는 프로퍼티를 복사하지 않는다.

const mixin = (target, source) => {
  for (let prop in source) {
    if (source.hasOwnProperty(prop)) {
      target[prop] = source[prop];
    }
  }
  return target;
};

const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };

const mixedObj = mixin(obj1, obj2);

console.log(obj1 === obj2); // false
console.log(obj1 === mixedObj);  // true
console.log(obj2 === mixedObj); // false
console.log(mixedObj); // Object {a: 1, b: 3, c: 4}
console.log(obj1); // Object {a: 1, b: 3, c: 4}

target 객체에 이미 있는 프로퍼티는 덮어쓰기, 없는 값은 추가를 한다. 이때 shallow copy가 이루어진다.

📌 좀 더 완전한 Mixin 함수

위에서 사용한 Mixin함수는 접근자 프로퍼티를 데이터 프로퍼티로 바꾸어 복사하는 문제점이 있다.

const mixin = (target, source) => {
  for (let prop in source) {
    if (source.hasOwnProperty(prop)) {
      target[prop] = source[prop];
    }
  }
  return target;
};

const user1 = {
  _name: "Kim",
  get name() {
    return this._name;
  }
};
const user2 = {};

mixin(user2, user1);

console.log(user1); // Object {_name: "Kim", name: "Kim"}
console.log(user1.name); // Kim

try {
  user1.name = 123;
} catch (e) {
  console.error(e);
}
//TypeError: Cannot set property name of #<Object> which has only a getter

user2.name = "Lee";
//setter 함수가 없는데 user2의 name 값이 바뀌는 현상이 발생
console.log(user2); //Object {_name: "Kim", name: "Lee"}
console.log(user2.name); //Lee 

따라서 이 문제점을 해결하고자 Mixin 함수에서 프로퍼티를 직접 복사해서 쓰는 방식이 아닌 Object.getOwnPropertyDescriptor를 이용해 넣어 줄 프로티를 디스크립터까지 참조해서 Object.defineProperty로 넘겨준다. 이렇게 하면 데이터 프로퍼티와 접근자 프로퍼티가 속성이 바뀌는 문제점을 방지할 수 있다.

const mixin = (target, source) => {
  const keys = Object.keys(source);
  for (let i = 0; i < keys.length; i++) {
    let descriptor = Object.getOwnPropertyDescriptor(source, keys[i]);
    Object.defineProperty(target, keys[i], descriptor);
  }
  return target;
};

const user1 = {
  _name: "Kim",
  get name() {
    return this._name;
  }
};

const user2 = {};

mixin(user2, user1);

console.log(user2); // Object {_name: "Kim", name: "Kim"}

try {
  user2.name = "Lee";
} catch (e) {
  console.error(e); // TypeError: Cannot set property name of #<Object> which has only a getter
}

console.log(user2); // Object {_name: "Kim", name: "Kim"}
//mixin 함수를 수정함으로 접근자 프로터피가 데이터 프로퍼티로 변하는 현상을 수정

우리가 Mixin을 왜 쓰는지에 대해서 보고 싶다면 이 링크를 참조하자

참조

  1. 모던 자바스크립트 입문
  2. https://velog.io/@moggy/Javascript-%EB%AF%B9%EC%8A%A4%EC%9D%B8-%EA%B8%B0%EB%B2%95Mixin-technique
post-custom-banner

0개의 댓글