Function.prototype.apply()
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
apply()
메서드는 주어진 this
값과 배열 (또는 유사 배열 객체) 로 제공되는 arguments
로 함수를 호출합니다.
참고 :
이 함수의 구문은 거의 call()
구문과 유사합니다. 근본적인 차이점은 call()
은 함수에 전달될 인수 리스트를 받는데 비해, apply()
는 인수들의 단일 배열을 받는다는 점입니다.
시도해보기
구문
func.apply(thisArg, [argsArray]);
매개변수
thisArg
-
옵션.
func
를 호출하는데 제공될this
의 값.this
는 메소드에 의해 실제로 보여지는 값이 아닐 수 있음을 유의합니다. 메소드가 non-strict mode 코드의 함수일 경우,null
과undefined
가 전역 객체로 대체되며, 기본 값은 제한됩니다. argsArray
-
옵션.
func
이 호출되어야 하는 인수를 지정하는 유사 배열 객체, 함수에 제공된 인수가 없을 경우null
또는undefined
. ECMAScript 5 의 시작으로 이러한 인수들은 배열 대신 제네릭 유사 배열 객체로 사용될 수 있습니다. 아래의 브라우저 호환성 정보를 보세요.
반환값
지정한 this
값과 인수들로 호출한 함수의 결과.
설명
이미 존재하는 함수를 호출할 때 다른 this
객체를 할당할 수 있습니다. this
는 현재 객체, 호출하는 객체를 참조합니다. apply
를 사용해, 새로운 객체마다 메소드를 재작성할 필요없이 한 번만 작성해 다른 객체에 상속시킬 수 있습니다.
apply
는 지원되는 인수의 타입만 제외하면 call()
과 매우 유사합니다. 인수(파라미터)의 리스트 대신 인수들의 배열을 사용할 수 있습니다. 또한 apply
를 사용해, 배열 리터럴이나 (예, func.apply(this, ['eat', 'bananas']), Array
객체 (예, func.apply(this, new Array('eat', 'bananas'))) 를 사용할 수 있습니다.
argsArray
파라미터를 위한 arguments
를 사용할 수도 있습니다. arguments
는 함수의 지역 변수입니다. 이는 호출된 객체의 지정되지 않은 모든 인수에 대해 사용할 수 있습니다. 따라서, apply
메소드를 사용할 때 호출된 객체의 인수를 알 필요가 없습니다. arguments
를 사용해 모든 인수들을 호출된 객체로 전달할 수 있습니다. 그럼 호출된 객체는 그 인수들을 처리할 수 있게 됩니다.
ECMAScript 5번 째 판의 시작으로, 모든 유사 배열 객체 타입을 사용할 수 있으며, 실제로 이는 프로퍼티 length
와 범위 (0..length-1)
내의 정수 프로퍼티를 갖는 다는 것을 의미합니다. 예를 들면, 이제 NodeList
또는 { 'length': 2, '0': 'eat', '1': 'bananas' }
와 같은 커스텀 객체를 사용할 수 있습니다.
참고 : Chrome 14와 Internet Explorer 9를 포함한 대부분의 브라우저는 아직 유사배열객체를 apply에 사용할 수 없으며 오류가 출력됩니다.
예제
배열에 배열을 붙이기 위해 apply
사용하기
push
를 사용하여 요소를 배열에 추가 할 수 있습니다. push
는 가변 인수를 허용하기 때문에 여러 요소를 동시에 추가 할 수 있습니다. 그러나 push
에 배열을 전달하면 요소를 개별적으로 추가하는 대신 실제로 해당 배열을 단일 요소로 추가하므로 결국 배열 내부에 배열로 끝납니다. 그것이 우리가 원하는 것이 아니라면? 이 경우 concat
은 우리가 원하는 동작을 하지만 실제로는 기존 배열에 추가되지 않고 새 배열을 만들어 반환 합니다. 그러나 우리는 기존 배열에 추가하고 싶었습니다 ... 그럼 이제 어쩌죠? 루프를 작성 할까요? 분명히 아니죠?
방법은 apply
!
var array = ["a", "b"];
var elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array); // ["a", "b", 0, 1, 2]
apply
와 내장함수 사용
apply
를 보다 효과적으로 이용하면 일부 내장 함수는 어떤 작업에 대해서는 배열과 루프없이 쉽게 처리됩니다. 다음 예제에서는 배열에서 최대값과 최소값을 구하기 위해 Math.max
/Math.min
함수를 이용하고 있습니다.
// min/max number in an array
var numbers = [5, 6, 2, 3, 7];
// using Math.min/Math.max apply
var max = Math.max.apply(null, numbers);
// 이는 Math.max(numbers[0], ...) 또는 Math.max(5, 6, ...)
// 와 거의 같음
var min = Math.min.apply(null, numbers);
// vs. simple loop based algorithm
(max = -Infinity), (min = +Infinity);
for (var i = 0; i < numbers.length; i++) {
if (numbers[i] > max) {
max = numbers[i];
}
if (numbers[i] < min) {
min = numbers[i];
}
}
하지만 이러한 방식으로 apply
를 사용하는 경우 주의해야 합니다. JavaScript 엔진의 인수 길이 제한을 초과하는 위험성에 대해 이해할 필요가 있습니다. 함수에 너무 많은(대략 몇 만개 이상) 인수를 줄 때의 상황은 엔진마다 다른데(예를 들어 JavaScriptCore의 경우 인수의 개수 제한은 65536), 상한이 특별히 정해져 있지 않기 때문입니다. 어떤 엔진은 예외를 던집니다. 더 심한 경우는 실제 함수에 인수를 전달했음에도 불구하고 참조할 수 있는 인수의 수를 제한하고 있는 경우도 있습니다(이러한 엔진에 대해 더 자세히 설명하면, 그 엔진이 arguments의 상한을 4개로 했다고 하면[실제 상한은 물론 더 위일 것입니다], 위 예제 코드의 전체 배열이 아니라 5, 6, 2, 3
만 apply
에 전달되어 온 것처럼 작동합니다).
만약 사용하는 배열 변수의 수가 수만을 초과하는 경우에는 복합적인 전략을 강구해야할 것입니다:한 번에 전달할 배열을 분할하여 사용하기:
function minOfArray(arr) {
var min = Infinity;
var QUANTUM = 32768;
for (var i = 0, len = arr.length; i < len; i += QUANTUM) {
var submin = Math.min.apply(null, arr.slice(i, Math.min(i + QUANTUM, len)));
min = Math.min(submin, min);
}
return min;
}
var min = minOfArray([5, 6, 2, 3, 7]);
생성자 체이닝을 위한 apply
사용
Java 와 유사하게, 객체를 위한 constructors 체이닝을 위해 apply
를 사용할 수 있습니다. 다음 예제에서 인수 리스트 대신 생성자로 유사 배열 객체를 사용할 수 있게 해주는 construct
라는 전역 Function
메소드를 생성할 것입니다.
Function.prototype.construct = function (aArgs) {
var oNew = Object.create(this.prototype);
this.apply(oNew, aArgs);
return oNew;
};
참고: 알림: 위에서 사용된
Object.create()
메소드는 상대적으로 새로운 것입니다. 대안으로, 다음 접근법 중 하나를 고려하세요.
Object.prototype.__proto__
사용:
Function.prototype.construct = function (aArgs) {
var oNew = {};
oNew.__proto__ = this.prototype;
this.apply(oNew, aArgs);
return oNew;
};
클로져 사용:
Function.prototype.construct = function(aArgs) {
var fConstructor = this, fNewConstr = function() {
fConstructor.apply(this, aArgs);
};
fNewConstr.prototype = fConstructor.prototype;
return new fNewConstr();
};
Function
생성자 사용
Function.prototype.construct = function (aArgs) {
var fNewConstr = new Function("");
fNewConstr.prototype = this.prototype;
var oNew = new fNewConstr();
this.apply(oNew, aArgs);
return oNew;
};
사용 예제
function MyConstructor() {
for (var nProp = 0; nProp < arguments.length; nProp++) {
this["property" + nProp] = arguments[nProp];
}
}
var myArray = [4, "Hello world!", false];
var myInstance = MyConstructor.construct(myArray);
console.log(myInstance.property1); // logs 'Hello world!'
console.log(myInstance instanceof MyConstructor); // logs 'true'
console.log(myInstance.constructor); // logs 'MyConstructor'
알림: 네이티브가 아닌 Function.construct
메소드는 Date
와 같은 일부 네이티브 생성자와 동작하지 않을 것입니다. 그런 경우, Function.prototype.bind
메소드를 사용해야 합니다. 예를 들어, 다음과 같은 배열이 있다고 할 때, Date
생성자: [2012, 11, 4]
와 함께 사용되려면 다음과 같이 작성해야 합니다: new (Function.prototype.bind.apply(Date, [null].concat([2012, 11, 4])))()
. 이는 가장 좋은 방법이 아니며, 어떤 상용 환경에서도 사용되지 않을 수 있습니다.
명세
Specification |
---|
ECMAScript Language Specification # sec-function.prototype.apply |
브라우저 호환성
BCD tables only load in the browser