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

Il metodo bind() crea una nuova funzione che, quando chiamata, ha la sua parola chiave impostata sul valore fornito, con una data sequenza di argomenti che precede quella fornita quando viene chiamata la nuova funzione

Sintassi

function.bind(thisArg[, arg1[, arg2[, ...]]])

Parametri

thisArg
Il valore va passato come parametro alla funzione target quando viene chiamata la funzione associata. Il valore viene ignorato se la funzione associata viene costruita utilizzando l'operatore new. Quando si utilizza bind per creare una funzione (fornita come callback) all'interno di un setTimeout, qualsiasi valore primitivo passato come thisArg viene convertito in oggetto. Se non vengono forniti argomenti per vincolarlo, l'esecuzione viene considerata come thisArg per la nuova funzione.
arg1, arg2, ...
Argomenti da anteporre agli argomenti forniti alla funzione associata quando si richiama la funzione di destinazione.

Valore restituito

Una copia della funzione data con specificato this valore e gli argomenti iniziali.

Descrizione

La funzione bind() crea una nuova funzione associata (BF). Un BF è un oggetto una funzione exotic (un termine di ECMAScript 2015) che racchiude l'oggetto funzione originale. Chiamare un BF generalmente comporta l'esecuzione della sua funzione wrapped (avvolta).
Un BF ha le seguenti proprietà interne:

  • [[BoundTargetFunction]] - l'oggetto funzione avvolto;
  • [[BoundThis]] - il valore che viene sempre passato come questo valore quando si chiama la funzione wrapped.
  • [[BoundArguments]] - un elenco di valori i cui elementi vengono utilizzati come primi argomenti per qualsiasi chiamata alla funzione wrapped.
  • [[Call]] - esegue il codice associato a questo oggetto. Invocato tramite un'espressione di chiamata di funzione. Gli argomenti del metodo interno sono un valore e un elenco contenente gli argomenti passati alla funzione da un'espressione di chiamata.

Quando viene chiamata la funzione associata, chiama il metodo interno [[Call]] su [[BoundTargetFunction]], con i seguenti argomenti Call (boundThis, args). Dove, boundThis è [[BoundThis]], args è [[BoundArguments]] seguito dagli argomenti passati dalla funzione call.

Una funzione legata (bound function) può anche essere costruita usando il nuovo operatore: agendo in tal modo si comporta come se la funzione obiettivo fosse stata invece costruita. Fornito questo valore this viene ignorato, mentre gli argomenti preposti sono forniti alla funzione emulata.

Esempi

Creare una funzione associata

L'uso più semplice di bind() è di creare una funzione che, indipendentemente da come viene chiamata, viene chiamata con un particolare valore. Un errore comune per i nuovi programmatori JavaScript consiste nell'estrarre un metodo da un oggetto, in seguito chiamare tale funzione e aspettarsi che utilizzi l'oggetto originale come tale (ad esempio, utilizzando tale metodo nel codice basato sul callback). Senza particolare cura, tuttavia, l'oggetto originale viene solitamente perso. La creazione di una funzione associata dalla funzione, utilizzando l'oggetto originale, risolve in modo chiaro questo problema:

this.x = 9;    // questo si riferisce all'oggetto "finestra" globale qui nel browser
var module = {
  x: 81,
  getX: function() { return this.x; }
};

module.getX(); // 81

var retrieveX = module.getX;
retrieveX();   
// returns 9 - restituisce 9 - La funzione viene richiamata nell'ambito globale

// Create a new function with 'this' bound to module
// Crea una nuova funzione con 'this' associato al modulo
// I nuovi programmatori potrebbero confondere il
// global var x con la proprietà del modulo x var boundGetX = retrieveX.bind(module);
boundGetX(); // 81

Funzioni parzialmente applicate

Il prossimo uso più semplice di bind() è quello di creare una funzione con argomenti iniziali pre-specificati. Questi argomenti (se presenti) seguono il valore fornito e vengono quindi inseriti all'inizio degli argomenti passati alla funzione di destinazione, seguiti dagli argomenti passati alla funzione associata, ogni volta che viene chiamata la funzione associata.

function list() {
  return Array.prototype.slice.call(arguments);
}

var list1 = list(1, 2, 3); // [1, 2, 3]

// Crea una funzione con un argomento principale preimpostato
var leadingThirtysevenList = list.bind(null, 37);

var list2 = leadingThirtysevenList(); 
// [37]

var list3 = leadingThirtysevenList(1, 2, 3);
// [37, 1, 2, 3]

Con setTimeout

Di default all'interno di window.setTimeout(), la parola chiave this verrà impostata sull'oggetto window (or global). Quando si lavora con metodi di classe che richiedono questo this riferimento alle istanze di classe, è possibile associarlo esplicitamente alla funzione di callback, al fine di mantenere l'istanza.

function LateBloomer() {
  this.petalCount = Math.floor(Math.random() * 12) + 1;
}

// Dichiarare apertura dopo un ritardo di 1 secondo
LateBloomer.prototype.bloom = function() {
  window.setTimeout(this.declare.bind(this), 1000);
};

LateBloomer.prototype.declare = function() {
  console.log('Sono un bel fiore con ' +
    this.petalCount + ' petali!');
};

var flower = new LateBloomer();
flower.bloom();  
// dopo 1 secondo, attiva il metodo 'declare'

Funzioni associate utilizzate come costruttori

Warning: Questa sezione dimostra capacità JavaScript e documenta alcuni casi limite del metodo bind(). I metodi mostrati di seguito non sono il modo migliore di fare le cose e probabilmente non dovrebbero essere usati in nessun ambiente di produzione.

Le funzioni associate sono automaticamente utilizzabili con l'operatore new per costruire nuove istanze create dalla funzione target. Quando una funzione associata viene utilizzata per costruire un valore, la condizione viene ignorata. Tuttavia, gli argomenti forniti sono ancora preposti alla chiamata del costruttore:

function Point(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.toString = function() { 
  return this.x + ',' + this.y; 
};

var p = new Point(1, 2);
p.toString(); // '1,2'

// non supportato nel polyfill di seguito,
// funziona bene con il bind nativo:

var YAxisPoint = Point.bind(null, 0/*x*/);


var emptyObj = {};
var YAxisPoint = Point.bind(emptyObj, 0/*x*/);

var axisPoint = new YAxisPoint(5);
axisPoint.toString(); // '0,5'

axisPoint instanceof Point; // true
axisPoint instanceof YAxisPoint; // true
new Point(17, 42) instanceof YAxisPoint; // true

Note that you need do nothing special to create a bound function for use with new. The corollary is that you need do nothing special to create a bound function to be called plainly, even if you would rather require the bound function to only be called using new.

// Example can be run directly in your JavaScript console
// ...continuing from above

// Can still be called as a normal function 
// (although usually this is undesired)
YAxisPoint(13);

emptyObj.x + ',' + emptyObj.y;
// >  '0,13'

If you wish to support the use of a bound function only using new, or only by calling it, the target function must enforce that restriction.

Creating shortcuts

bind() is also helpful in cases where you want to create a shortcut to a function which requires a specific this value.

Take Array.prototype.slice, for example, which you want to use for converting an array-like object to a real array. You could create a shortcut like this:

var slice = Array.prototype.slice;

// ...

slice.apply(arguments);

With bind(), this can be simplified. In the following piece of code, slice is a bound function to the apply() function of Function.prototype, with the this value set to the slice() function of Array.prototype. This means that additional apply() calls can be eliminated:

// same as "slice" in the previous example
var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.apply.bind(unboundSlice);

// ...

slice(arguments);

Polyfill

You can partially work around this by inserting the following code at the beginning of your scripts, allowing use of much of the functionality of bind() in implementations that do not natively support it.

if (!Function.prototype.bind) {
  Function.prototype.bind = function(oThis) {
    if (typeof this !== 'function') {
      // closest thing possible to the ECMAScript 5
      // internal IsCallable function
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }

    var aArgs   = Array.prototype.slice.call(arguments, 1),
        fToBind = this,
        fNOP    = function() {},
        fBound  = function() {
          return fToBind.apply(this instanceof fNOP
                 ? this
                 : oThis,
                 aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    if (this.prototype) {
      // Function.prototype doesn't have a prototype property
      fNOP.prototype = this.prototype; 
    }
    fBound.prototype = new fNOP();

    return fBound;
  };
}

Some of the many differences (there may well be others, as this list does not seriously attempt to be exhaustive) between this algorithm and the specified algorithm are:

  • The partial implementation relies on Array.prototype.slice(), Array.prototype.concat(), Function.prototype.call() and Function.prototype.apply(), built-in methods to have their original values.
  • The partial implementation creates functions that do not have immutable "poison pill" caller and arguments properties that throw a TypeError upon get, set, or deletion. (This could be added if the implementation supports Object.defineProperty, or partially implemented [without throw-on-delete behavior] if the implementation supports the __defineGetter__ and __defineSetter__ extensions.)
  • The partial implementation creates functions that have a prototype property. (Proper bound functions have none.)
  • The partial implementation creates bound functions whose length property does not agree with that mandated by ECMA-262: it creates functions with length 0, while a full implementation, depending on the length of the target function and the number of pre-specified arguments, may return a non-zero length.

If you choose to use this partial implementation, you must not rely on those cases where behavior deviates from ECMA-262, 5th edition! With some care, however (and perhaps with additional modification to suit specific needs), this partial implementation may be a reasonable bridge to the time when bind() is widely implemented according to the specification.

Please check https://github.com/Raynos/function-bind for a more thorough solution!

Specifications

Specification Status Comment
ECMAScript 5.1 (ECMA-262)
The definition of 'Function.prototype.bind' in that specification.
Standard Initial definition. Implemented in JavaScript 1.8.5.
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Function.prototype.bind' in that specification.
Standard  
ECMAScript Latest Draft (ECMA-262)
The definition of 'Function.prototype.bind' in that specification.
Draft  

Browser compatibility

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidEdge MobileFirefox for AndroidOpera for AndroidiOS SafariSamsung InternetNode.js
Basic supportChrome Full support 7Edge Full support YesFirefox Full support 4IE Full support 9Opera Full support 11.6Safari Full support 5.1WebView Android Full support 4Chrome Android Full support 18Edge Mobile Full support YesFirefox Android Full support 4Opera Android Full support 11.5Safari iOS Full support 6Samsung Internet Android Full support Yesnodejs Full support Yes

Legend

Full support  
Full support

See also

Tag del documento e collaboratori

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