--- title: Function.prototype.bind() slug: Web/JavaScript/Reference/Global_Objects/Function/bind translation_of: Web/JavaScript/Reference/Global_Objects/Function/bind ---
Il metodo bind()
crea una nuova funzione che, quando chiamata, ha parola chiave this
impostata sul valore fornito, con una data sequenza di argomenti che precede quella fornita quando viene chiamata la nuova funzione
{{EmbedInteractiveExample("pages/js/function-bind.html", "taller")}}
La fonte per questo esempio interattivo è memorizzata in un repository GitHub. Se desideri contribuire al progetto di esempi interattivi, ti preghiamo di clonare. https://github.com/mdn/interactive-examples e inviarci una richiesta di pull.
function
.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg
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, ...
Una copia della funzione data con specificato this
valore e gli argomenti iniziali.
La funzione bind()
crea una nuova funzione associata (BF, bound function). Un BF è un exotic function object (oggetto funzione esotico, 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:
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 chiamata alla funzione.
Una funzione associata (bound function) può anche essere costruita usando l'operatore new: agendo in tal modo si comporta come se la funzione obiettivo fosse stata invece costruita. Il valore this
fornito viene ignorato, mentre gli argomenti preposti sono forniti alla funzione emulata.
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
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]
setTimeout
Di default all'interno di {{domxref("window.setTimeout()")}}, la parola chiave this
verrà impostata sull'oggetto {{ domxref("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'
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 {{jsxref("Operators/new", "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 {{jsxref("Operators/new", "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 {{jsxref("Operators/new", "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 {{jsxref("Operators/new", "new")}}, or only by calling it, the target function must enforce that restriction.
bind()
is also helpful in cases where you want to create a shortcut to a function which requires a specific this
value.
Take {{jsxref("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 {{jsxref("Function.prototype.apply()", "apply()")}} function of {{jsxref("Function.prototype")}}, with the this
value set to the {{jsxref("Array.prototype.slice()", "slice()")}} function of {{jsxref("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);
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:
arguments
properties that throw a {{jsxref("Global_Objects/TypeError", "TypeError")}} upon get, set, or deletion. (This could be added if the implementation supports {{jsxref("Object.defineProperty")}}, or partially implemented [without throw-on-delete behavior] if the implementation supports the {{jsxref("Object.defineGetter", "__defineGetter__")}} and {{jsxref("Object.defineSetter", "__defineSetter__")}} extensions.)prototype
property. (Proper bound functions have none.)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!
Specification | Status | Comment |
---|---|---|
{{SpecName('ES5.1', '#sec-15.3.4.5', 'Function.prototype.bind')}} | {{Spec2('ES5.1')}} | Initial definition. Implemented in JavaScript 1.8.5. |
{{SpecName('ES2015', '#sec-function.prototype.bind', 'Function.prototype.bind')}} | {{Spec2('ES2015')}} | |
{{SpecName('ESDraft', '#sec-function.prototype.bind', 'Function.prototype.bind')}} | {{Spec2('ESDraft')}} |
{{Compat("javascript.builtins.Function.bind")}}