Javascript - DeepDive(5) : MixIn

­이승환·2021년 7월 21일
0

Javascript DeepDive

목록 보기
5/13

Mixin 함수란?

믹스인이란 특정 객체에 다른 객체가 가지고 있는 프로퍼티를 "합치는" 것을 말한다.
상속을 사용하지 않고 특정 객체의 프로퍼티를 동적으로 다른 객체에 추가할 수 있는 것이 특징이다. OOP 언어에서 사용하는 상속과 유사한 기능일 수도 있겠다는 생각이 있고, 비교적 자유로운 자바스크립트에서 나타나는 현상에 대해서 확인해 볼 필요가 있다.

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

위와 같은 함수를 통해 target 에 source 를 붙여넣을 수 있다.

아래 예제를 확인해보자.

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}

여기서 믹스인을 통해 복사되는 프로퍼티는 shallow copy 가 이루어짐을 명심해야 한다.

완벽한 Mixin에 대하여


Deep Copy 를 이용해 source 와 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 

위 예제의 경우 name 메소드에 setter 는 존재하지 않음에도 Mixin 을 활용한 이후에는 getter 가 setter 처럼 변하는 문제점이 발생한다.

따라서 getOwnPropertyDescriptor 를 이용하면 좀더 완벽하게 복사할 수 있다.

const perfectMixin = (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 = {};

perfectMixin(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 함수를 수정함으로 접근자 프로터피가 데이터 프로퍼티로 변하는 현상을 수정

완벽하게 외울 필요는 없을 것 같다. getOwnPrepertyDescriptor 라는 객체 참조 메소드를 이용해서 형식(getter) 까지 복사해올 수만 있으면 디버그 과정에서 수월할 것으로 예상된다.

profile
Mechanical & Computer Science

0개의 댓글

관련 채용 정보