[JavaScript] 자바스크립트에서 배열과 객체에 독자적인 메소드 추가하기

2022. 8. 9. 12:41Program/JavaScript

270_자바스크립트에서 배열과 객체에 독자적인 메소드 추가하기

[적용]

  • 배열에 셔플 함수를 추가하고 싶을 때
  • 객체에 JSON 변환 메소드를 추가하고 싶을 때

[문법]

구문 의미
객체.prototype[심볼] = function() {} 객체에 독자적인 메소드 추가 
객체[심볼]() 독자적인 메소드 실행 

[내용]

Array, Date, Object 등 기존의 객체(빌트인 객체)에 독자적인 메소드를 추가하고 싶을 떄는 다음과 같이 프로토타입(Prototype)과 심볼(Symbol)을 사용한다.

 

JavaScript         

// 'myMethod' 이름의 심볼 생성
const myMethod = Symbol();

// 독자적인 메소드 추가
Array.prototype[myMethod] = function() {
  console.log('독자적인 메소드입니다.');
}

// 독자적으로 추가한 메소드 실행
const array = [1, 2, 3];
array[myMethod]();  // 결과: '독자적인 메소드입니다.'

 

배열에 셔플용 메소드를 추가하는 샘플을 확인해 보자.

 

JavaScript         

// 'shuffle'이라는 이름의 심볼
const shuffle = Symbol();

// 배열의 셔플 함수 추가
Array.prototype[shuffle] = function() {
  // 셔플 처리
  const arrayLength = this.length;
  for (let i = arrayLength -1; i > >= 0; i--) {
    const randomIndex = Math.floor(Math.random() * (i + 1));
    [this[i], this[randomIndex]] = [this[randomIndex], this[i]];
  }
  
  // 자기 자신 반환
  return this;
};

// 셔플 함수 테스트
// 배열의 짝수 값을 뽑아 셔플 작업 후 곱하기 100
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

array.filter((value) => value % 2 === 0)[shuffle]().map((value) => value * 100);

 

프로토타입은 객체(Object)에 멤버(멤버 변수, 멤버 함수)를 추가하는 속성이다.

Array, Date, Function은 모두 Object를 계승하는 객체(빌트인 객체)이므로 모든 객체에 프로토타입이 존재한다.

 

console.dir()을 사용해 프로토타입의 내부를 확인하면 다음과 같은 멤버의 확인이 가능하다.

  • 문자열(String 객체)의 length나 indexOf() 등 모든 멤버
  • 배열(Array 객체)의 map()이나 filter() 등 모든 멤버
  • Date 객체의 getDate()나 getFullYear() 등 모든 멤버

JavaScript         

console.dir(String.prototype);
console.dir(Array.prototype);
console.dir(Date.prototype);

실행결과

구글 크롬 개발자 도구로 console.dir(String.prototype);을 실행한 결과

프로토타입에 멤버를 추가하면 '객체.멤버명' 접근으로 사용할 수 있다.

JavaScript         

Array.prototype.myMethod = function() {
  console.log('안녕하세요.');
};

const array = [1, 2, 3];
array.myMethod();  // 결과: "안녕하세요."

 

사용된 멤버명을 재사용해 정의하면 덮어쓰기 작업이 이루어진다.

JavaScript         

Array.prototype.filter = function() {
  console.log('기존의 filter 멤버를 덮어쓰는 메소드');
};

const array = [1, 2, 3];
// "기존의 filter 멤버를 덮어쓰는 메소드" 출력
//  새로운 filter()가 기존의 filter()를 대체하여 정의됨
array.filter();

 

Array.prototype.shuffle()의 shuffle()을 재정의한 상황을 가정해 보자.

지금의 자바스크립트에는 배열의 멤버 shuffle()이 존재하지 않지만, 

이후 업데이트 버전에서는 추가될 가능성도 배제할 수 없다.

그렇게 되면 기존의 정의를 덮어쓰게 되어 의도하지 않은 결과로 이어질 수 있다(프로토타입 오염).

 

이 문제를 방지하기 위해 유일한 값의 보장이 가능한 심볼을 사용할 수 있다.

다음과 같이 심볼을 생성해 확장 메소드의 이름으로 사용하면 중복되는 일 없이 안전하게 사용할 수 있다.

JavaScript         

const shuffle = Symbol();

// Array.prototype의 'shuffle' 멤버에 함수 추가
Array.prototype[shuffle] = function() {};

 

이와 같이 심볼을 사용하면 배열에 shuffle()이 추가되어도 중복되는 일이 없다.

const shuffle = Symbol();

Array.prototype[shuffle] = function() {};

const array = [1, 2, 3];

// 정의한 shuffle() 메소드
array[shuffle]();
// 공식적으로 추가되었을 경우의 shuffle() 메소드
array.shuffle();

 

 


 

 

 

 

 

참조 :
실무에 바로 적용하는 자바스크립트 코드레시피 278
아케다 야스노부, 카노 타케시 지음 / 이춘혁 옮김