본문 바로가기
JavaScript

유사배열객체에 배열메서드 적용(call, apply)

by whoyoung90 2022. 1. 30.
반응형

앞 게시물에서는 상황별로 this에 어떤 값이 바인딩되는지를 알아봤다면,

이러한 규칙을 깨고 this에 별도의 대상을 바인딩하는 방법이 있다.

 

바로 call / apply 메서드이다.

call / apply 메서드에서 소개해 볼 세가지 기능은 아래와 같다.

1.  this에 별도의 대상 바인딩 (this에 원하는 값을 지정해서 호출)
2. 유사배열객체에 배열메서드 적용
3. 문자열에 배열메서드 적용

 

1.  this에 별도의  대상 바인딩

함수로서 호출하면 this는 전역객체를 참조하고

메서드로서 호출하면 this는 프로퍼티명 앞의 객체를 참조하지만,

 

call / apply 메서드를 이용하면 임의의 객체를 this로 지정할 수 있다.

 

1-1. 함수로서 호출

let func = function (a, b, c) {
  console.log(this, a, b, c);
};

func(1, 2, 3);                          // 전역객체 window  1 2 3
func.call({ x: 'test' }, 1, 2, 3);      // { x: 'test' } 1 2 3  
func.apply({ x: 'test' }, [1, 2, 3]);   // { x: 'test' } 1 2 3

/* 명시적으로 this에 { x: 'test' }객체를 지정할 수 있다! */

 

1-2. 메서드로서 호출

let obj = {
  method: function (x, y) {
    console.log(this, x, y);
  }
};

obj.method(1,2);                         // obj 1 2
obj.method.call({ x: 'test'}, 1, 2);     // { x: 'test' } 1 2
obj.method.apply({ x: 'test'}, [1, 2]);  // { x: 'test' } 1 2

/* 명시적으로 this에 { x: 'test' }객체를 지정할 수 있다! */

 

2. 유사배열객체에 배열메서드 적용 (ES5)

- 유사배열 객체란?
   키가 0 또는 양의 정수인 프로퍼티가 존재하고 length 프로퍼티의 값이 0 또는 양의정수객체.
   arguments, NodeList
(querySelectorAll, getElementsByClassName ..) 포함

 

"객체"에 "배열 메서드"를 직접 적용할 수는 없지만

유사배열객체의 경우 call / apply 메서드를 이용해 모든 배열 메서드를 적용할 수 있다! (ex. push, slice)

/* 유사 배열 객체 */
let arr_Obj = {
  0: 'one',
  1: 'two',
  length: 2
};

Array.prototype.push.call(arr_Obj, 'three');
console.log(arr_Obj);     // { '0': 'one', '1': 'two', '2': 'three', length: 3 }

/* slice는 매개변수를 아무것도 넘기지 않을 경우, 원본 배열의 얕은 복사 */
let changeArr = Array.prototype.slice.call(arr_Obj);
console.log(changeArr);   // [ 'one', 'two', 'three' ]
/* 함수 내부에서 접근할 수 있는 arguments 객체도 유사배열객체 */
function innerfunc() {
  console.log(arguments);
};
innerfunc('a','b');    // { '0': 'a', '1': 'b', length: 2}


function argu() {
  let change = Array.prototype.slice.call(arguments);
  console.log(change);
};
argu(1,2,3);           // [1, 2, 3]

 

3. 문자열에 배열메서드 적용 (ES5)

배열처럼 인덱스와 length 프로퍼티를 지니는 "문자열"에도 적용할 수 있다!

 

단, 문자열의 length 프로퍼티는 읽기 전용이기 때문에

원본을 변경하는 메서드(push, pop, shift, unshift, splice 등)는 에러를 출력하고

concat은 에러는 나지 않지만 다른 결과가 나오게 된다.

 

적용가능한 배열메서드는 every, some, map, reduce 등이 있겠다!

let str = 'woo young';

Array.prototype.every.call(str, function(char) {
  return char !== ''
});                      // false

Array.prototype.some.call(str, function(char) {
  return char === ''
});                      // true

let strToArr = Array.prototype.map.call(str, function(char) {
  return char
});
console.log(strToArr);   // [ 'w', 'o', 'o', ' ', 'y', 'o', 'u', 'n', 'g' ]

let newStr = Array.prototype.reduce.call(str, function(acc, cur, idx) {
  return acc + cur + idx  },'');
console.log(newStr)      // 'w0o1o2 3y4o5u6n7g8'

 

4. 유사배열객체 + 문자열을 배열로 전환 (ES6)

ES6에서는 유사배열객체 또는 순회 가능한 모든 종류의 데이터 타입을

 

배열로 전환하는 Array.from 메서드를 새로 도입하였다.

let obj = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
};
let newArr = Array.from(obj);
console.log(newArr);             // [ 'a', 'b', 'c' ]


let str = 'woo young';
let newArr1 = Array.from(str);
console.log(newArr1);            // [ 'w', 'o', 'o', ' ', 'y', 'o', 'u', 'n', 'g' ]

 

 

반응형

'JavaScript' 카테고리의 다른 글

콜백 함수도 함수로서 호출이다  (1) 2022.02.26
forEach / for-in / for-of 차이점  (0) 2022.01.31
This에 대한 정리  (0) 2022.01.22
continue 문  (0) 2022.01.05
스코프 체인 예시  (0) 2021.12.25

댓글