1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
|
---
title: Function.prototype.apply()
slug: Web/JavaScript/Reference/Global_Objects/Function/apply
tags:
- Function
- JavaScript
- Method
- Reference
translation_of: Web/JavaScript/Reference/Global_Objects/Function/apply
---
<div>{{JSRef}}</div>
<p><strong><code>apply()</code></strong> 메서드는 주어진 <code>this</code> 값과 배열 (또는 <a href="/en-US/docs/Web/JavaScript/Guide/Predefined_Core_Objects#Working_with_Array-like_objects">유사 배열 객체</a>) 로 제공되는 <code>arguments</code> 로 함수를 호출합니다.</p>
<div class="note">
<p><strong>참고:</strong> 이 함수의 구문은 거의 {{jsxref("Function.call", "call()")}} 구문과 유사합니다. 근본적인 차이점은 <code>call()</code> 은 함수에 전달될 <strong>인수 리스트</strong>를 받는데 비해, <code>apply()</code> 는 <strong>인수들의 단일 배열</strong>을 받는다는 점입니다.</p>
</div>
<p>{{EmbedInteractiveExample("pages/js/function-apply.html")}}</p>
<h2 id="구문">구문</h2>
<pre class="syntaxbox"><code><var>func</var>.apply(<var>thisArg, </var>[<var>argsArray</var>])</code></pre>
<h3 id="매개변수">매개변수</h3>
<dl>
<dt><code>thisArg</code></dt>
<dd>옵션. <code>func</code> 를 호출하는데 제공될 <code>this</code> 의 값. <code>this</code> 는 메소드에 의해 실제로 보여지는 값이 아닐 수 있음을 유의합니다. 메소드가 {{jsxref("Strict_mode", "non-strict mode", "", 1)}} 코드의 함수일 경우, {{jsxref("null")}} 과 {{jsxref("undefined")}} 가 전역 객체로 대체되며, 기본 값은 제한됩니다.</dd>
<dt><code>argsArray</code></dt>
<dd>옵션. <em><code>func</code></em> 이 호출되어야 하는 인수를 지정하는 유사 배열 객체, 함수에 제공된 인수가 없을 경우 {{jsxref("null")}} 또는 {{jsxref("undefined")}}. ECMAScript 5 의 시작으로 이러한 인수들은 배열 대신 제네릭 유사 배열 객체로 사용될 수 있습니다. 아래의 {{anch("Browser_compatibility", "브라우저 호환성")}} 정보를 보세요.</dd>
</dl>
<h3 id="반환값">반환값</h3>
<p>지정한 <strong><code>this</code></strong> 값과 인수들로 호출한 함수의 결과.</p>
<h2 id="Description" name="Description">설명</h2>
<p>이미 존재하는 함수를 호출할 때 다른 <code>this</code> 객체를 할당할 수 있습니다. <code>this</code> 는 현재 객체, 호출하는 객체를 참조합니다. <code>apply</code> 를 사용해, 새로운 객체마다 메소드를 재작성할 필요없이 한 번만 작성해 다른 객체에 상속시킬 수 있습니다.</p>
<p><code>apply</code> 는 지원되는 인수의 타입만 제외하면 {{jsxref("Function.call", "call()")}} 과 매우 유사합니다. 인수(파라미터)의 리스트 대신 인수들의 배열을 사용할 수 있습니다. 또한 <code>apply</code> 를 사용해, 배열 리터럴이나 (예, <em>func</em>.apply(this, ['eat', 'bananas']), {{jsxref("Array")}} 객체 (예, <em>func</em>.apply(this, new Array('eat', 'bananas'))) 를 사용할 수 있습니다.</p>
<p><code>argsArray</code> 파라미터를 위한 {{jsxref("Functions/arguments", "arguments")}} 를 사용할 수도 있습니다. <code>arguments</code> 는 함수의 지역 변수입니다. 이는 호출된 객체의 지정되지 않은 모든 인수에 대해 사용할 수 있습니다. 따라서, <code>apply</code> 메소드를 사용할 때 호출된 객체의 인수를 알 필요가 없습니다. <code>arguments</code> 를 사용해 모든 인수들을 호출된 객체로 전달할 수 있습니다. 그럼 호출된 객체는 그 인수들을 처리할 수 있게 됩니다.</p>
<p>ECMAScript 5번 째 판의 시작으로, 모든 유사 배열 객체 타입을 사용할 수 있으며, 실제로 이는 프로퍼티 <code>length</code> 와 범위 <code>(0..length-1)</code> 내의 정수 프로퍼티를 갖는 다는 것을 의미합니다. 예를 들면, 이제 {{domxref("NodeList")}} 또는 <code>{ 'length': 2, '0': 'eat', '1': 'bananas' }</code> 와 같은 커스텀 객체를 사용할 수 있습니다.</p>
<div class="blockIndicator note">Chrome 14와 Internet Explorer 9를 포함한 대부분의 브라우저는 아직 유사배열객체를 apply에 사용할 수 없으며 오류가 출력됩니다.</div>
<h2 id="Examples" name="Examples">예제</h2>
<h3 id="Example_Using_apply_to_chain_constructors" name="Example:_Using_apply_to_chain_constructors">배열에 배열을 붙이기 위해 <code>apply</code> 사용하기</h3>
<p><code>push</code> 를 사용하여 요소를 배열에 추가 할 수 있습니다. <code>push</code> 는 가변 인수를 허용하기 때문에 여러 요소를 동시에 추가 할 수 있습니다. 그러나 <code>push</code> 에 배열을 전달하면 요소를 개별적으로 추가하는 대신 실제로 해당 배열을 단일 요소로 추가하므로 결국 배열 내부에 배열로 끝납니다. 그것이 우리가 원하는 것이 아니라면? 이 경우 <code>concat</code> 은 우리가 원하는 동작을 하지만 실제로는 기존 배열에 추가되지 않고 새 배열을 만들어 반환 합니다. 그러나 우리는 기존 배열에 추가하고 싶었습니다 ... 그럼 이제 어쩌죠? 루프를 작성 할까요? 분명히 아니죠?</p>
<p>방법은 <code>apply</code> !</p>
<pre class="brush: js">var array = ['a', 'b'];
var elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array); // ["a", "b", 0, 1, 2]
</pre>
<h3 id="apply_와_내장함수_사용"><code>apply</code> 와 내장함수 사용</h3>
<p><code>apply</code> 를 보다 효과적으로 이용하면 일부 내장 함수는 어떤 작업에 대해서는 배열과 루프없이 쉽게 처리됩니다. 다음 예제에서는 배열에서 최대값과 최소값을 구하기 위해 <code>Math.max</code>/<code>Math.min</code> 함수를 이용하고 있습니다.</p>
<pre class="brush: js">// 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];
}
}
</pre>
<p>하지만 이러한 방식으로 <code>apply</code> 를 사용하는 경우 주의해야 합니다. JavaScript 엔진의 인수 길이 제한을 초과하는 위험성에 대해 이해할 필요가 있습니다. 함수에 너무 많은(대략 몇 만개 이상) 인수를 줄 때의 상황은 엔진마다 다른데(예를 들어 JavaScriptCore의 경우 <a href="https://bugs.webkit.org/show_bug.cgi?id=80797">인수의 개수 제한은 65536</a>), 상한이 특별히 정해져 있지 않기 때문입니다. 어떤 엔진은 예외를 던집니다. 더 심한 경우는 실제 함수에 인수를 전달했음에도 불구하고 참조할 수 있는 인수의 수를 제한하고 있는 경우도 있습니다(이러한 엔진에 대해 더 자세히 설명하면, 그 엔진이 arguments의 상한을 4개로 했다고 하면[실제 상한은 물론 더 위일 것입니다], 위 예제 코드의 전체 배열이 아니라 <code>5, 6, 2, 3</code> 만 <code>apply</code> 에 전달되어 온 것처럼 작동합니다).</p>
<p>만약 사용하는 배열 변수의 수가 수만을 초과하는 경우에는 복합적인 전략을 강구해야할 것입니다:한 번에 전달할 배열을 분할하여 사용하기:</p>
<pre class="brush: js">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]);
</pre>
<h3 id="생성자_체이닝을_위한_apply_사용">생성자 체이닝을 위한 <code>apply</code> 사용</h3>
<p>Java 와 유사하게, 객체를 위한 {{jsxref("Operators/new", "constructors", "", 1)}} 체이닝을 위해 <code>apply</code> 를 사용할 수 있습니다. 다음 예제에서 인수 리스트 대신 생성자로 유사 배열 객체를 사용할 수 있게 해주는 <code>construct</code> 라는 전역 {{jsxref("Function")}} 메소드를 생성할 것입니다. </p>
<pre><code>Function.prototype.construct = function(aArgs) {
var oNew = Object.create(this.prototype);
this.apply(oNew, aArgs);
return oNew;
};</code></pre>
<div class="blockIndicator note">
<p><strong>알림:</strong> 위에서 사용된 <code>Object.create()</code> 메소드는 상대적으로 새로운 것입니다. 대안으로, 다음 접근법 중 하나를 고려하세요.</p>
<p>{{jsxref("Object/__proto__", "Object.__proto__")}} 사용</p>
<pre><code>Function.prototype.construct = function (aArgs) {
var oNew = {};
oNew.__proto__ = this.prototype;
this.apply(oNew, aArgs);
return oNew;
};</code></pre>
<p><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Closures">클로져</a> 사용:</p>
<pre><code>Function.prototype.construct = function(aArgs) {
var fConstructor = this, fNewConstr = function() {
fConstructor.apply(this, aArgs);
};
fNewConstr.prototype = fConstructor.prototype;
return new fNewConstr();
};</code></pre>
<p>{{jsxref("Function")}} 생성자 사용</p>
<pre><code>Function.prototype.construct = function (aArgs) {
var fNewConstr = new Function("");
fNewConstr.prototype = this.prototype;
var oNew = new fNewConstr();
this.apply(oNew, aArgs);
return oNew;
};</code></pre>
</div>
<p>사용 예제</p>
<pre><code>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'</code></pre>
<p><strong>알림:</strong> 네이티브가 아닌 <code>Function.construct</code> 메소드는 {{jsxref("Date")}} 와 같은 일부 네이티브 생성자와 동작하지 않을 것입니다. 그런 경우, {{jsxref("Function.prototype.bind")}} 메소드를 사용해야 합니다. 예를 들어, 다음과 같은 배열이 있다고 할 때, {{jsxref("Global_Objects/Date", "Date")}} 생성자: <code>[2012, 11, 4]</code> 와 함께 사용되려면 다음과 같이 작성해야 합니다: <code>new (Function.prototype.bind.apply(Date, [null].concat([2012, 11, 4])))()</code>. 이는 가장 좋은 방법이 아니며, 어떤 상용 환경에서도 사용되지 않을 수 있습니다.</p>
<h2 id="명세">명세</h2>
<table>
<tbody>
<tr>
<th scope="col">명세</th>
<th scope="col">상태</th>
<th scope="col">코멘트</th>
</tr>
<tr>
<td>{{SpecName('ES3')}}</td>
<td>{{Spec2('ES3')}}</td>
<td>초기 정의. JavaScript 1.3 에 구현됨.</td>
</tr>
<tr>
<td>{{SpecName('ES5.1', '#sec-15.3.4.3', 'Function.prototype.apply')}}</td>
<td>{{Spec2('ES5.1')}}</td>
<td></td>
</tr>
<tr>
<td>{{SpecName('ES6', '#sec-function.prototype.apply', 'Function.prototype.apply')}}</td>
<td>{{Spec2('ES6')}}</td>
<td></td>
</tr>
<tr>
<td>{{SpecName('ESDraft', '#sec-function.prototype.apply', 'Function.prototype.apply')}}</td>
<td>{{Spec2('ESDraft')}}</td>
<td></td>
</tr>
</tbody>
</table>
<h2 id="브라우저_호환성">브라우저 호환성</h2>
<p>{{Compat("javascript.builtins.Function.apply")}}</p>
<h2 id="함께_보기">함께 보기</h2>
<ul>
<li>{{jsxref("Functions/arguments", "arguments")}} 객체</li>
<li>{{jsxref("Function.prototype.bind()")}}</li>
<li>{{jsxref("Function.prototype.call()")}}</li>
<li>{{jsxref("Functions", "Functions and function scope", "", 1)}}</li>
<li>{{jsxref("Reflect.apply()")}}</li>
</ul>
|