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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
|
---
title: Function.prototype.bind()
slug: Web/JavaScript/Reference/Global_Objects/Function/bind
translation_of: Web/JavaScript/Reference/Global_Objects/Function/bind
---
<div>{{JSRef}}</div>
<p>Il metodo <code><strong>bind()</strong></code> crea una nuova funzione che, quando chiamata, ha parola chiave <strong><code>this</code></strong> impostata sul valore fornito, con una data sequenza di argomenti che precede quella fornita quando viene chiamata la nuova funzione</p>
<p>{{EmbedInteractiveExample("pages/js/function-bind.html", "taller")}}</p>
<p class="hidden">La fonte per questo esempio interattivo è memorizzata in un repository GitHub. Se desideri contribuire al progetto di esempi interattivi, ti preghiamo di clonare. <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> e inviarci una richiesta di pull.</p>
<h2 id="Sintassi">Sintassi</h2>
<pre class="syntaxbox"><code><var>function</var></code>.bind(<var>thisArg</var>[, <var>arg1</var>[, <var>arg2</var>[, ...]]])</pre>
<h3 id="Parametri">Parametri</h3>
<dl>
<dt><code>thisArg</code></dt>
<dd>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 {{jsxref("Operators/new", "new")}}. Quando si utilizza <code>bind</code> per creare una funzione (fornita come callback) all'interno di un setTimeout, qualsiasi valore primitivo passato come <code>thisArg</code> viene convertito in oggetto. Se non vengono forniti argomenti per vincolarlo, l'esecuzione viene considerata come <code>thisArg</code> per la nuova funzione.</dd>
<dt><code>arg1, arg2, ...</code></dt>
<dd>Argomenti da anteporre agli argomenti forniti alla funzione associata quando si richiama la funzione di destinazione.</dd>
</dl>
<h3 id="Valore_restituito">Valore restituito</h3>
<p>Una copia della funzione data con specificato <strong><code>this</code></strong> valore e gli argomenti iniziali.</p>
<h2 id="Descrizione">Descrizione</h2>
<p>La funzione <code>bind()</code> crea una nuova <strong>funzione associata</strong> <strong>(BF, bound function)</strong>. Un BF è un <em>exotic function object </em>(oggetto funzione esotico, un termine di ECMAScript 2015) che racchiude l'oggetto funzione originale. Chiamare un BF generalmente comporta l'esecuzione della sua funzione <em>wrapped</em> (avvolta).<br>
Un BF ha le seguenti proprietà interne:</p>
<ul>
<li><strong>[[BoundTargetFunction]]</strong> - l'oggetto funzione avvolto;</li>
<li><strong>[[BoundThis]]</strong> - il valore che viene sempre passato come questo valore quando si chiama la funzione wrapped.</li>
<li><strong>[[BoundArguments]] - </strong>un elenco di valori i cui elementi vengono utilizzati come primi argomenti per qualsiasi chiamata alla funzione wrapped.</li>
<li><strong>[[Call]]</strong> - 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.</li>
</ul>
<p>Quando viene chiamata la funzione associata, chiama il metodo interno <strong>[[Call]]</strong> su<strong> [[BoundTargetFunction]]</strong>, con i seguenti argomenti <code>call(boundThis, ...args)</code>. Dove, <code>boundThis</code> è <strong>[[BoundThis]]</strong>, <code>args</code> è <strong>[[BoundArguments]] </strong>seguito dagli argomenti passati dalla chiamata alla funzione.</p>
<p>Una funzione associata (bound function) può anche essere costruita usando l'operatore <a href="/it/docs/Web/JavaScript/Reference/Operators/new">new</a>: agendo in tal modo si comporta come se la funzione obiettivo fosse stata invece costruita. Il valore <code>this</code> fornito viene ignorato, mentre gli argomenti preposti sono forniti alla funzione emulata.</p>
<h2 id="Esempi">Esempi</h2>
<h3 id="Creare_una_funzione_associata">Creare una funzione associata</h3>
<p>L'uso più semplice di <code>bind()</code> è 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:</p>
<pre class="brush: js">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 <code>var boundGetX = retrieveX.bind(module);</code>
boundGetX(); // 81
</pre>
<h3 id="Funzioni_parzialmente_applicate">Funzioni parzialmente applicate</h3>
<p>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.</p>
<pre class="brush: js">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]
</pre>
<h3 id="Con_setTimeout">Con <code>setTimeout</code></h3>
<p>Di default all'interno di {{domxref("window.setTimeout()")}}, la parola chiave <code>this</code> verrà impostata sull'oggetto {{ domxref("window") }} (or <code>global</code>). Quando si lavora con metodi di classe che richiedono questo <code>this</code> riferimento alle istanze di classe, è possibile associarlo esplicitamente alla funzione di callback, al fine di mantenere l'istanza.</p>
<pre class="brush: js">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'</pre>
<h3 id="Funzioni_associate_utilizzate_come_costruttori">Funzioni associate utilizzate come costruttori</h3>
<div class="warning">
<p><strong>Warning:</strong> 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.</p>
</div>
<p>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:</p>
<pre class="brush: js">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
</pre>
<p>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")}}.</p>
<pre class="brush: js">// 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'
</pre>
<p>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.</p>
<h3 id="Creating_shortcuts">Creating shortcuts</h3>
<p><code>bind()</code> is also helpful in cases where you want to create a shortcut to a function which requires a specific <strong><code>this</code></strong> value.</p>
<p>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:</p>
<pre class="brush: js">var slice = Array.prototype.slice;
// ...
slice.apply(arguments);
</pre>
<p>With <code>bind()</code>, this can be simplified. In the following piece of code, <code>slice</code> is a bound function to the {{jsxref("Function.prototype.apply()", "apply()")}} function of {{jsxref("Function.prototype")}}, with the <strong><code>this</code></strong> value set to the {{jsxref("Array.prototype.slice()", "slice()")}} function of {{jsxref("Array.prototype")}}. This means that additional <code>apply()</code> calls can be eliminated:</p>
<pre class="brush: js">// same as "slice" in the previous example
var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.apply.bind(unboundSlice);
// ...
slice(arguments);
</pre>
<h2 id="Polyfill">Polyfill</h2>
<p>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 <code>bind()</code> in implementations that do not natively support it.</p>
<pre class="brush: js">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;
};
}
</pre>
<p>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:</p>
<ul>
<li>The partial implementation relies on {{jsxref("Array.prototype.slice()")}}, {{jsxref("Array.prototype.concat()")}}, {{jsxref("Function.prototype.call()")}} and {{jsxref("Function.prototype.apply()")}}, built-in methods to have their original values.</li>
<li>The partial implementation creates functions that do not have immutable "poison pill" {{jsxref("Function.caller", "caller")}} and <code>arguments</code> 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.)</li>
<li>The partial implementation creates functions that have a <code>prototype</code> property. (Proper bound functions have none.)</li>
<li>The partial implementation creates bound functions whose {{jsxref("Function.length", "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.</li>
</ul>
<p>If you choose to use this partial implementation, <strong>you must not rely on those cases where behavior deviates from ECMA-262, 5th edition!</strong> 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 <code>bind()</code> is widely implemented according to the specification.</p>
<p>Please check <a href="https://github.com/Raynos/function-bind">https://github.com/Raynos/function-bind</a> for a more thorough solution!</p>
<h2 id="Specifications">Specifications</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Specification</th>
<th scope="col">Status</th>
<th scope="col">Comment</th>
</tr>
<tr>
<td>{{SpecName('ES5.1', '#sec-15.3.4.5', 'Function.prototype.bind')}}</td>
<td>{{Spec2('ES5.1')}}</td>
<td>Initial definition. Implemented in JavaScript 1.8.5.</td>
</tr>
<tr>
<td>{{SpecName('ES2015', '#sec-function.prototype.bind', 'Function.prototype.bind')}}</td>
<td>{{Spec2('ES2015')}}</td>
<td></td>
</tr>
<tr>
<td>{{SpecName('ESDraft', '#sec-function.prototype.bind', 'Function.prototype.bind')}}</td>
<td>{{Spec2('ESDraft')}}</td>
<td></td>
</tr>
</tbody>
</table>
<h2 id="Browser_compatibility">Browser compatibility</h2>
<div>
<p>{{Compat("javascript.builtins.Function.bind")}}</p>
</div>
<h2 id="See_also">See also</h2>
<ul>
<li>{{jsxref("Function.prototype.apply()")}}</li>
<li>{{jsxref("Function.prototype.call()")}}</li>
<li>{{jsxref("Functions", "Functions", "", 1)}}</li>
</ul>
|