MDN wants to talk to developers like you: https://qsurvey.mozilla.com/s3/8d22564490d8

Function.prototype.apply()

Questa traduzione è incompleta. Collabora alla traduzione di questo articolo dall’originale in lingua inglese.

Il metodo apply() chiama una funzione passandole il "this" ed i parametri forniti sottoforma di array (o array-like object).

Nota: Mentre la sintassi di questa funzione è quasi completamente identica a quella di call(), la fondamentale differenza è che call() accetta una lista di parametri, mentre apply() accetta un singolo array contenente una lista di parametri.

Sintassi

fun.apply(thisArg, [argsArray])

Parametri

thisArg
Il valore del this da fornire alla chiama a fun. Nota che questo potrebbe non essere l'effettivo valore visto dal metodo: se il metodo non è eseguito in strict mode, null ed undefined saranno rimpiazzati dall'oggetto globale.
argsArray
Un array-like object che specifica i parametri con la quale la funzione fun deve essere chiamata. Può essere anche nullundefined nel caso nessun parametro dovesse essere passato. A partire da ECMAScript 5 questi parametri possono essere un qualunque array-like object invece di un semplice array. Vedi sotto per le compatibilità nei browser.

Descrizione

this solitamente si riferisce all'oggetto corrente, ma grazie ad apply è possibile scrivere un metodo una sola volta e riusarlo più volte su oggetti differenti passando ad apply, appunto, un this differente. Cosi viene eliminata la necessità di riscrivere di nuovo lo stesso metodo per un oggetto diverso.

apply è molto simile a call(), eccezion fatta per il modo in cui i parametri vengono passati. Puoi utilizzare un array di parametri invece della solita lista. Con apply, ad esempio, puoi utilizzare il seguente array literal: fun.apply(this, ['eat', 'bananas']), o il seguente oggetto Arrayfun.apply(this, new Array('eat', 'bananas')).

Puoi anche utilizzare arguments per il parametro argsArrayarguments è una variabile locale di tutte le funzioni. Può essere utilizzata per tutti i parametri non specificati dell'oggetto chiamato. In più, non è necessario che si conoscano i parametri dell'oggetto chiamato quando si utilizza apply.

Da ECMAScript 5 puoi anche usare qualunque tipo di array-like object. Ad esempio puoi utilizzare un NodeList o un oggetto come { 'length': 2, '0': 'eat', '1': 'bananas' }.

Note: La maggior parte dei browser, incluso Chrome 14 ed Internet Explorer 9, non accetto array-like objects e lanceranno una eccezione.

Esempi

Utilizzare apply per concatenare costruttori

Puoi utilizzare apply per concatenare costruttori per un oggetto, in maniera simile a Java. Nel seguente esempio creeremo una Function globale chiamata construct, che ti permetterà di utilizzare un array-like object con un costruttore anziché una lista di argomenti.

Function.prototype.construct = function (aArgs) {
  var oNew = Object.create(this.prototype);
  this.apply(oNew, aArgs);
  return oNew;
};

Note: Il metodo Object.create() usato nell'esempio sovrastante è relativamente nuovo. Per un alternativa che utilizza le closures considera questo pezzo di codice:

Function.prototype.construct = function(aArgs) {
  var fConstructor = this, fNewConstr = function() { 
    fConstructor.apply(this, aArgs); 
  };
  fNewConstr.prototype = fConstructor.prototype;
  return new fNewConstr();
};

Esempio d'uso:

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'

Note: Il metodo non nativo Function.construct non funzionerà con alcuni costruttori nativi (come Date). In questi casi devi usare Function.prototype.bind. Immagina ad esempio di avere un array come il seguente da utilizzare con il costruttore Date: [2012, 11, 4]; In questo caso dovresti scrivere qualcosa come: new (Function.prototype.bind.apply(Date, [null].concat([2012, 11, 4])))() — ad ogni modo questo non è il miglior modo di fare le cose e non andrebbe mai usato in produzione.

Utilizzare apply combinato alle funzioni built-in

Un intelligente uso di apply ti permette di utilizzare delle funzioni built-in per dei compiti che altrimenti sarebbero stati fatti, nel caso sottostante, ciclando l'array e scorrendo ogni suo elemento e sottoponendolo a dei controlli. L'esempio seguente dimostra come trovare il massimo / minimo valore all'interno di un array utilizzando 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); 
// 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];
  }
}

Ma tieni a mente che nell'usare apply in questo modo si corre il rischio di superare il limite imposto dal motore JavaScript degli argomenti che possono essere passati ad una funzione.
Le conseguenze nel fare ciò variano da motore a motore (ad esempio JavaScriptCore ha il limite settato a mano di 65536 parametri), perché il limite non è specificato. Alcuni motori lanceranno una eccezione. Altri invece limiteranno arbitrariamente il numero dei parametri passati alla funzione su cui viene usato il metodo apply(). (Un esempio di quest'ultimo caso potrebbe essere quello di un motore che ha questo limite settato a 4 e, nell'esempio sovrastante, gli unici parametri che effettivamente saranno passati alla funzione saranno 5, 6, 2, 3, piuttosto che l'intero array.) Una decisione saggia, nel caso si prevede la possibilità di raggiungere un enorme numero di parametri, sarebbe quella di parzializzare il numero di parametri per lotti:

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]);

Usare apply come "monkey-patch"

L'attività del "monkey-patching" consiste nel modificare il funzionamento di un metodo senza dover andare a mettere mano al codice sorgente (cosa da evitare sempre e comunque). Difatti Apply può rivelarsi il modo migliore di modificare il funzionamento, ad esempio, di una funzione interna a Firefox o di una qualunque altra libreria JS. Data una funzione someobject.foo, è possibile modificarne il funzionamento in questo modo:

var originalfoo = someobject.foo;
someobject.foo = function() {
  // Do stuff before calling function
  console.log(arguments);
  // Call the function as it would have been called normally:
  originalfoo.apply(this, arguments);
  // Run stuff after, here.
}

Questo metodo ritorna particolarmente utile quando vuoi debuggare eventi e interfacce con qualcosa che non espone API come i diversi eventi .on([event]... (usabili anche dal Devtools Inspector).

Specifiche

Specifica Stato Commento
ECMAScript 3rd Edition (ECMA-262) Standard Definizione iniziale. Implementato in JavaScript 1.3.
ECMAScript 5.1 (ECMA-262)
The definition of 'Function.prototype.apply' in that specification.
Standard  
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Function.prototype.apply' in that specification.
Standard  
ECMAScript 2017 Draft (ECMA-262)
The definition of 'Function.prototype.apply' in that specification.
Draft  

Compatibilità Browser

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Supporto base (Yes) (Yes) (Yes) (Yes) (Yes)
ES 5.1 generico array-like object come arguments ? 4.0 (2.0) ? ? ?
Feature Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Supporto base (Yes) (Yes) (Yes) (Yes) (Yes) (Yes)
ES 5.1 generico array-like object come arguments ? ? 4.0 (2.0) ? ? ?

Vedi anche

Tag del documento e collaboratori

 Hanno collaborato alla realizzazione di questa pagina: giacomocerquone
 Ultima modifica di: giacomocerquone,