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
229
230
231
232
233
234
|
---
title: Function.prototype.apply()
slug: Web/JavaScript/Reference/Global_Objects/Function/apply
tags:
- Function
- JavaScript
- Method
- función
- metodo
translation_of: Web/JavaScript/Reference/Global_Objects/Function/apply
original_slug: Web/JavaScript/Referencia/Objetos_globales/Function/apply
---
<div>{{JSRef("Objetos_globales", "Function")}}</div>
<h2 id="Summary" name="Summary">Resumen</h2>
<p>El método <strong>apply()</strong> invoca una determinada función asignando explícitamente el objeto <strong>this</strong> y un array o similar (<a href="/en-US/docs/JavaScript/Guide/Predefined_Core_Objects#Working_with_Array-like_objects" title="/en-US/docs/JavaScript/Guide/Predefined_Core_Objects#Working_with_Array-like_objects">array like object</a>) como parámetros (<strong>argumentos)</strong> para dicha función.</p>
<div class="note"><strong>NOTA:</strong> Aunque la sintaxis de esta función es casi idéntica a {{jsxref("Function.call", "call()")}}, la diferencia fundamental es que <code>call()</code> acepta una lista de argumentos, mientras que <code>apply()</code> acepta un simple array con los argumentos.</div>
<h2 id="Syntax" name="Syntax">Sintaxis</h2>
<pre class="syntaxbox"><code><em>fun</em>.apply(<em>thisArg</em>[, <em>argsArray</em>])</code></pre>
<h3 id="Parameters" name="Parameters">Parámetros</h3>
<dl>
<dt><code>thisArg</code></dt>
<dd>El valor del objeto <strong>this</strong> a utilizar dentro de la llamada a <em>fun</em>. Cabe mencionar que éste puede no ser el valor visto por el método: si el método es una función del tipo {{jsxref("Functions_and_function_scope/Strict_mode", "non-strict mode", "", 1)}}, {{jsxref("Global_Objects/null", "null")}} o {{jsxref("Global_Objects/undefined", "undefined")}} será reemplazado por el objeto global, y los valores primitivos serán encapsulados.</dd>
<dt><code>argsArray</code></dt>
<dd>Un objeto similar a un array (<a href="/en-US/docs/JavaScript/Guide/Predefined_Core_Objects#Working_with_Array-like_objects" title="/en-US/docs/JavaScript/Guide/Predefined_Core_Objects#Working_with_Array-like_objects">array like object</a>), que contiene los parámetros con los que será llamada <em><code>fun</code></em>, o <code>null</code> o {{jsxref("undefined")}} si ningún argumento es estipulado. Desde la versión 5 de ECMAScript estos parámetros pueden estar en un objeto similar a un array en lugar de un array. Véase {{anch("Browser_compatibility", "browser compatibility")}} para mayor información.</dd>
<dt>
<h3 id="Valor_de_retorno">Valor de retorno</h3>
<p>El resultado de llamar a la función con el valor dado <code><strong>this</strong></code> y argumentos.</p>
</dt>
</dl>
<h2 id="Description" name="Description">Descripción</h2>
<p>Puede estipularse un objeto <code>this</code> diferente al llamar una función. <code>this</code> se refiere al objeto actual, el objeto haciendo la llamada. Con <code>apply</code>, puede escribirse un método una vez y heredarlo a otro objeto, sin necesidad de reescribir el método para adecuarlo al nuevo objeto.</p>
<p><code>apply</code> es muy similar a {{jsxref("Function.call", "call()")}}, excepto por el tipo de argumentos que soporta. Puede utilizarse un arreglo de parámetros en lugar de un conjunto de pares nombre-valor. Con <code>apply</code>, puede utilizarse un arreglo literal, por ejemplo, <code><em>fun</em>.apply(this, ['eat', 'bananas'])</code>, o un objeto <code>Array</code>, por ejemplo, <code><em>fun</em>.apply(this, new Array('eat', 'bananas'))</code>.</p>
<p>Puede también utilizarse {{jsxref("Funciones/arguments", "arguments")}} como parámetro <code>argsArray</code>. <code>arguments</code> es una variable local a la función. Puede utilizarse para acceder a todos los argumentos no específicados en la llamada al objeto. Por lo tanto, no se requiere conocer todos los argumentos del objeto invocado cuando se utiliza el método <code>apply</code>. Puede utilizarse <code>arguments</code> para pasar los argumentos al objeto invocado. El objeto invocado es entonces responsable por el manejo de los argumentos.</p>
<p>Desde la 5ta edición de ECMAScript se puede utilizar también cualquier tipo de objeto similar a un arreglo, que en términos prácticos significa que tendrá una propiedad <code>length</code> y propiedades integer en el rango (<code>0...length)</code>. Por ejemplo, ahora puede utilizarse un {{domxref("NodeList")}} o un objeto personalizado como: <code>{'length': 2, '0': 'eat', '1': 'bananas'}</code>.</p>
<div>{{ note("La mayoría de los navegadores, incluidos Chrome 14 e Internet Explorer 9, aún no soportan el uso de objetos similares a un array y arrojarán una excepción.") }}</div>
<div> </div>
<h2 id="Examples" name="Examples">Ejemplos</h2>
<h3 id="Using_apply_to_chain_constructors" name="Using_apply_to_chain_constructors">Utilizando <strong><code>apply</code></strong> para encadenar constructores</h3>
<p>Puedes utilizar <code>apply</code> para encadenar {{jsxref("Operadores/new", "constructors")}} para un objeto, similar a Java. En el ejemplo siguiente se crea un método global a {{jsxref("Function")}} llamado <code>construct</code>, en cual posibilita el uso de un objeto similar a un arreglo en un constructor en lugar de una lista de argumentos.</p>
<pre class="brush: js">Function.prototype.construct = function (aArgs) {
var fConstructor = this, fNewConstr = function () { fConstructor.apply(this, aArgs); };
fNewConstr.prototype = fConstructor.prototype;
return new fNewConstr();
};</pre>
<p>Ejemplo de uso:</p>
<pre class="brush: js">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);
alert(myInstance.property1); // alerts "Hello world!"
alert(myInstance instanceof MyConstructor); // alerts "true"
alert(myInstance.constructor); // alerts "MyConstructor"</pre>
<div class="note"><strong>Nota:</strong> El método <code>Function.construct</code> no nativo no funcionará con algunos constructores nativos (como {{jsxref("Date")}}, por ejemplo). En estos casos se deberá utilizar el método {{jsxref("Function.bind")}} (por ejemplo, supóngase un arreglo como el siguiente para utilizar con el constructor <code>Date</code>: <code>[2012, 11, 4]</code>; en este caso se tendría que escribir algo como: <code>new (Function.prototype.bind.apply(Date, [null].concat([2012, 11, 4])))()</code> – de cualquier manera, ésta no es la mejor manera de hacerlo y probablemente no debería utilizarse en ningún entorno en producción).</div>
<h3 id="apply_and_built-in_functions" name="apply_and_built-in_functions"><strong><code>apply</code></strong> y funciones <strong>built-in</strong></h3>
<p>El uso inteligente de <strong><code>apply</code></strong> permite utilizar funciones built-in para algunas tareas que, de otra manera, habrían sido escritas recorriendo los valores del arreglo dentro de un bucle. Como ejemplo, vamos a utilizar <code>Math.max</code>/<code>Math.min </code>para encontrar el máximo/mínimo valor en un arreglo.</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); /* This about equal to Math.max(numbers[0], ...) or 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>Pero cuidado: utilizando <code>apply</code> de esta manera estás corriendo el riesgo de exceder el límite de argumentos permitido por el motor de JavaScript. Las consecuencias de aplicar una función con demasiados argumentos (imagínate más de decenas de miles de argumentos) varían entre los distintos motores (JavaScriptCore tiene un <a href="https://bugs.webkit.org/show_bug.cgi?id=80797">límite de argumentos fijo de 65536</a>), porque el límite (de hecho, incluso el comportamiento de cualquier pila excesivamente larga) no está especificado. Algunos motores lanzarán una excepción. Más perniciosamente, otros limitarán de manera arbitraria el número de argumentos que se están pasando en realidad a la función. (Para ilustrar este último caso: si un motor tuviera un límite de cuatro argumentos [por supuesto, los límites reales son significamente mayores], sería como si los argumentos 5, 6, 2 y 3 hubieran sido pasados a <code>apply</code> en los ejemplos anteriores, en lugar del arreglo completo). Si el valor de tu arreglo pudiera crecer en decenas de miles, utiliza una estrategia híbrida: aplica a tu función trozos del array a la vez:</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="Utilizando_apply_en_monkey-patching">Utilizando apply en "monkey-patching" </h3>
<p>(Reemplazando de manera dinámica los argumentos en tiempo de ejecución)</p>
<p><code>apply </code>puede ser la mejor manera de reemplazar dinámicamente una función 'built-in' de Firefox, o de una librería de JavaScript. Dada una función <code>someobject.foo</code>, puedes modificar la función de una forma 'hacker', como ésta:</p>
<pre><code>var originalfoo = someobject.foo;
someobject.foo = function() {
// Haz algo antes de llamar a la función
console.log(arguments);
// Llama a la función como la hubieras llamado normalmente
originalfoo.apply(this, arguments);
// Aquí, ejecuta algo después
}</code></pre>
<p>Este método es especialmente útil cuando quieres depurar eventos, o interfaces con algún elemento que no tiene API, al igual que los diversos <code>.on</code> (eventos<code> [event]..., </code>como los que se usan en el <a href="https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector#Developer_API">Devtools Inspector</a>)</p>
<h2 id="Especificaciones">Especificaciones</h2>
<table>
<tbody>
<tr>
<th scope="col">Especificación</th>
<th scope="col">Estado</th>
<th scope="col">Comentario</th>
</tr>
<tr>
<td>{{SpecName('ES3')}}</td>
<td>{{Spec2('ES3')}}</td>
<td>Definición Inicial. Implementada in 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="Compatibilidad_entre_navegadores">Compatibilidad entre navegadores</h2>
<p>{{CompatibilityTable}}</p>
<table>
<tbody>
<tr>
<th>Feature</th>
<th>Chrome</th>
<th>Firefox (Gecko)</th>
<th>Internet Explorer</th>
<th>Opera</th>
<th>Safari</th>
</tr>
<tr>
<td>Basic support</td>
<td>{{CompatVersionUnknown}}</td>
<td>{{CompatVersionUnknown}}</td>
<td>{{CompatVersionUnknown}}</td>
<td>{{CompatVersionUnknown}}</td>
<td>{{CompatVersionUnknown}}</td>
</tr>
<tr>
<td>ES 5.1 generic array-like object as {{jsxref("Functions/arguments", "arguments")}}</td>
<td>{{CompatUnknown}}</td>
<td>{{CompatGeckoDesktop("2.0")}}</td>
<td>{{CompatUnknown}}</td>
<td>{{CompatUnknown}}</td>
<td>{{CompatUnknown}}</td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<th>Feature</th>
<th>Android</th>
<th>Chrome for Android</th>
<th>Firefox Mobile (Gecko)</th>
<th>IE Mobile</th>
<th>Opera Mobile</th>
<th>Safari Mobile</th>
</tr>
<tr>
<td>Basic support</td>
<td>{{CompatVersionUnknown}}</td>
<td>{{CompatVersionUnknown}}</td>
<td>{{CompatVersionUnknown}}</td>
<td>{{CompatVersionUnknown}}</td>
<td>{{CompatVersionUnknown}}</td>
<td>{{CompatVersionUnknown}}</td>
</tr>
<tr>
<td>ES 5.1 generic array-like object as {{jsxref("Functions/arguments", "arguments")}}</td>
<td>{{CompatUnknown}}</td>
</tr>
</tbody>
</table>
<h2 id="See_also" name="See_also">Véase también</h2>
<ul>
<li>{{jsxref("Funciones/arguments", "arguments")}} objetos</li>
<li>{{jsxref("Function.prototype.bind()")}}</li>
<li>{{jsxref("Function.prototype.call()")}}</li>
</ul>
|