유사 배열을 진짜 배열로
함수의 매개변수를 입력하지 않았을 경우 arguments 객체, 즉 유사 배열로 값이 들어오게 되는데 이 유사배열을 진짜 배열로 바꾸고 싶을 때가 있다.
function foo() {
var arr = arguments.slice()
arr.push("bam");
console.log( arr );
}
foo("bar", "baz"); // Uncaught TypeError: arguments.slice is not a function
유사 배열인 arguments는 배열의 메소드인 slice()를 쓸 수 없다.
slice를 쓰고 싶다면, 모든 함수에 존재하고 있는 call() 메소드를 통해 기능을 빌려올 수 있다.
function foo() {
var arr = Array.prototype.slice.call( arguments );
arr.push( 'bam' );
console.log( arr );
}
foo( 'bar', 'baz' ); // ['bar', 'baz', 'bam']
call()과 applay()는 동일한 기능으로, 첫번째 인자는 'this로 사용할 객체' 를 넣으라고 하는데..말이 어렵다.
그냥 '빌려올 기능을 사용할 객체' 라고 생각하면 될거 같다.
여기서는 arguments.slice() 이렇게 쓰고 싶은거니까.그리고 두번째 인자부터 옵션인데, 빌려올 기능( 여기서는 slice(인수) )의 인수로 넣을 인자들을 넣어주면 된다.
call과 apply의 차이
- call
두번째, 세번째, 네번째 ... 이렇게 slice에 인수 넣듯이 넣으면 된다. ex) call(thisArg, arg1, ..., argN)
- apply
두번째 인자에 넣고 싶은 인자들을 배열로 하나만 넣어준다. ex) apply(thisArg, argsArray)
위의 코드는 결국 처음 보여준 아래 코드처럼 사용한거와 다를바 없다. (아래 코드는 실제로는 작동 안되겠지만)
slice()에 인자를 하나도 안넣었을 경우 배열의 첫번째 원소부터 끝까지 잘라내므로 동일한 배열을 복사(얕은 복사)한것과 같은 결과.
즉, arr에는 arguments와 동일한 진짜 배열인 ['bar', 'baz']가 할당 된다.
function foo() {
var arr = arguments.slice.();
arr.push( 'bam' );
console.log( arr );
}
foo( 'bar', 'baz' ); // ['bar', 'baz', 'bam']
ES6부터는 call() 을 쓰지 않고 Array.from()을 쓰면 된다.
function foo() {
var arr = Array.from(arguments);
arr.push( 'bam' );
console.log( arr );
}
foo( 'bar', 'baz' ); // ['bar', 'baz', 'bam']