aboutsummaryrefslogtreecommitdiff
path: root/files/pl/web/javascript/reference/global_objects/function/bind/index.html
blob: 028db6b6d4cebd021e3091ee617880e5a413183f (plain)
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
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
---
title: Function.prototype.bind()
slug: Web/JavaScript/Referencje/Obiekty/Function/bind
translation_of: Web/JavaScript/Reference/Global_Objects/Function/bind
---
<div>{{JSRef}}<br>
Metoda <span class="seoSummary"><code><strong>bind()</strong></code> </span> tworzy nową funkcję, której wywołanie powoduje ustawienie <strong>this</strong> na podaną wartość, z podaną sekwencją argumentów poprzedzającą dowolną podaną podczas wywołania nowej funkcji.<br>
 </div>

<div>{{EmbedInteractiveExample („pages / js / function-bind.html”, „taller”)}}<br>
Źródło tego interaktywnego przykładu jest przechowywane w repozytorium GitHub. Jeśli chcesz przyczynić się do projektu interaktywnych przykładów, sklonuj https://github.com/mdn/interactive-examples i wyślij nam prośbę o pobranie.</div>

<h2 id="Syntax">Syntax</h2>

<pre class="syntaxbox notranslate">let boundFunc = <var>func</var>.bind(thisAtr[, <var>arg1</var>[, <var>arg2</var>[, ...<var>argN</var>]]])
</pre>

<h3 id="Parametry">Parametry</h3>

<dl>
 <dt><code><var>thisAtr</var></code></dt>
 <dd>Wartość, która ma być przekazana jako <strong>this</strong> do funkcji docelowej func po wywołaniu funkcji powiązanej. Wartość jest ignorowana, jeśli funkcja powiązana jest konstruowana przy użyciu operatora {{jsxref („Operators / new”, „new”)}}. Podczas używania funkcji <strong>bind</strong> do utworzenia funkcji (dostarczonej jako wywołanie zwrotne) wewnątrz setTimeout, każda prymitywna wartość przekazywana, gdy <strong>thisAtr</strong> jest konwertowany na obiekt. Jeśli nie podano żadnych argumentów, aby powiązać (bind), lub jeśli thisArg jest <strong>null</strong> lub <strong>undefined</strong>, <strong>this</strong> z zakresu wykonania jest traktowany jako <strong>thisAtr</strong> dla nowej funkcji.</dd>
 <dt><code><var>arg1</var>, <var>arg2</var>, ...<var>argN</var></code> {{optional_inline}}</dt>
 <dd>Argumenty poprzedzające argumenty dostarczone funkcji powiązanej podczas wywoływania func.</dd>
</dl>

<h3 id="Zwracana_wartość">Zwracana wartość</h3>

<p>Kopia podanej funkcji z podaną tą wartością i początkowymi argumentami (jeśli podano).</p>

<h2 id="Opis">Opis</h2>

<p>Funkcja <strong>bind</strong>() tworzy nową funkcję wiązania (bound function), która jest exotic function object (termin z ECMAScript 2015), który zawija oryginalny obiekt funkcji. Wywołanie funkcji powiązanej zazwyczaj skutkuje wykonaniem jej owrapowanej funkcji.</p>

<p>Funckja wiązania <strong>(bound function)</strong> ma następujące właściwości wewnętrzne:</p>

<dl>
 <dt><strong><code>[[BoundTargetFunction]]</code> </strong></dt>
 <dd>The wrapped function object</dd>
 <dt><code><strong>[[BoundThis]]</strong></code></dt>
 <dd>The value that is always passed as <code>this</code> value when calling the wrapped function.</dd>
 <dt><code><strong>[[BoundArguments]]</strong></code></dt>
 <dd>A list of values whose elements are used as the first arguments to any call to the wrapped function.</dd>
 <dt><code><strong>[[Call]]</strong></code></dt>
 <dd>Executes code associated with this object. Invoked via a function call expression. The arguments to the internal method are a <code>this</code> value and a list containing the arguments passed to the function by a call expression.</dd>
</dl>

<p>When a bound function is called, it calls internal method <code>[[Call]]</code> on <code>[[BoundTargetFunction]]</code>, with following arguments <code>Call(<var>boundThis</var>, ...<var>args</var>)</code>. Where <code><var>boundThis</var></code> is <code>[[BoundThis]]</code>, <code><var>args</var></code> is <code>[[BoundArguments]]</code>, followed by the arguments passed by the function call.</p>

<p>A bound function may also be constructed using the {{jsxref("Operators/new", "new")}} operator. Doing so acts as though the target function had instead been constructed. The provided <code>this</code> value is ignored, while prepended arguments are provided to the emulated function.</p>

<h2 id="Examples">Examples</h2>

<h3 id="Creating_a_bound_function">Creating a bound function</h3>

<p>The simplest use of <code>bind()</code> is to make a function that, no matter how it is called, is called with a particular <code>this</code> value.</p>

<p>A common mistake for new JavaScript programmers is to extract a method from an object, then to later call that function and expect it to use the original object as its <code>this</code> (e.g., by using the method in callback-based code).</p>

<p>Without special care, however, the original object is usually lost. Creating a bound function from the function, using the original object, neatly solves this problem:</p>

<pre class="brush: js notranslate">this.x = 9;    // 'this' refers to global 'window' object here in a browser
const module = {
  x: 81,
  getX: function() { return this.x; }
};

module.getX();
//  returns 81

const retrieveX = module.getX;
retrieveX();
//  returns 9; the function gets invoked at the global scope

//  Create a new function with 'this' bound to module
//  New programmers might confuse the
//  global variable 'x' with module's property 'x'
const boundGetX = retrieveX.bind(module);
boundGetX();
//  returns 81
</pre>

<p><strong>Funkcje częściowo zastosowane</strong><br>
 Kolejnym najprostszym zastosowaniem bind () jest utworzenie funkcji z wcześniej określonymi argumentami początkowymi.</p>

<p>Argumenty te (jeśli występują) są zgodne z podaną wartością, a następnie są wstawiane na początku argumentów przekazywanych do funkcji docelowej, a następnie wszelkie argumenty przekazywane funkcja powiązana w momencie jej wywołania.</p>

<pre class="brush: js notranslate">function list() {
  return Array.prototype.slice.call(arguments);
}

function addArguments(arg1, arg2) {
  return arg1 + arg2
}

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

const result1 = addArguments(1, 2);
//  3

// Create a function with a preset leading argument
const leadingThirtysevenList = list.bind(null, 37);

// Create a function with a preset first argument.
const addThirtySeven = addArguments.bind(null, 37);

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

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

const result2 = addThirtySeven(5);
//  37 + 5 = 42

const result3 = addThirtySeven(5, 10);
//  37 + 5 = 42
//  (the second argument is ignored)


</pre>

<h3 id="With_setTimeout">With <code>setTimeout()</code></h3>

<p>By default within <a href="/en-US/docs/Web/API/Window/setTimeout" title="REDIRECT WindowTimers.setTimeout"><code>window.setTimeout()</code></a>, the <code>this</code> keyword will be set to the <a href="/en-US/docs/Web/API/Window" title="The Window interface represents a window containing a DOM document; the document property points to the DOM document loaded in that window."><code>window</code></a> (or <code>global</code>) object. When working with class methods that require <code>this</code> to refer to class instances, you may explicitly bind <code>this</code> to the callback function, in order to maintain the instance.</p>

<pre class="brush: js notranslate">function LateBloomer() {
  this.petalCount = Math.floor(Math.random() * 12) + 1;
}

// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
  window.setTimeout(this.declare.bind(this), 1000);
};

LateBloomer.prototype.declare = function() {
  console.log(`I am a beautiful flower with ${this.petalCount} petals!`);
};

const flower = new LateBloomer();
flower.bloom();
//  after 1 second, calls 'flower.declare()'
</pre>

<h3 id="Funkcje_powiązane_używane_jako_kostruktory">Funkcje powiązane używane jako kostruktory</h3>

<div class="warning">
<p>Ostrzeżenie: ta sekcja pokazuje możliwości JavaScript i dokumentuje niektóre przypadki krawędzi metody bind ().</p>

<p>Metody przedstawione poniżej nie są najlepszym sposobem na robienie rzeczy i prawdopodobnie nie powinny być stosowane w żadnym środowisku produkcyjnym.</p>
</div>

<p>Funkcje powiązane są automatycznie odpowiednie do użycia z operatorem {{jsxref („Operators / new”, „new”)}} do tworzenia nowych instancji utworzonych przez funkcję docelową. Gdy do utworzenia wartości używana jest funkcja powiązana, pod warunkiem, że jest to ignorowane.</p>

<p>Jednak pod warunkiem, że argumenty są nadal dołączane do wywołania konstruktora:</p>

<pre class="brush: js notranslate">function Point(x, y) {
  this.x = x;
  this.y = y;
}

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

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


//  not supported in the polyfill below,

//  works fine with native bind:

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


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

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

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

<p>Zauważ, że nie musisz robić nic specjalnego, aby utworzyć powiązaną funkcję do użycia z {{jsxref („Operators / new”, „new”)}}.</p>

<p>Następstwem jest to, że nie musisz robić nic specjalnego, aby utworzyć funkcję powiązaną, która będzie wywoływana w sposób jawny, nawet jeśli wolisz, aby funkcja powiązana była wywoływana tylko za pomocą {{jsxref („Operators / new”, „new”)}} .</p>

<pre class="brush: js notranslate">//  Example can be run directly in your JavaScript console
//  ...continued from above

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

`${emptyObj.x},${emptyObj.y}`;
// &gt;  '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="Tworzenie_skrótów">Tworzenie skrótów</h3>

<p>bind () jest również pomocny w przypadkach, w których chcesz utworzyć skrót do funkcji, która wymaga podania tej wartości.</p>

<p>Weźmy na przykład {{jsxref ("Array.prototype.slice ()")}}, którego chcesz użyć do konwersji obiektu podobnego do tablicy na prawdziwą tablicę. Możesz utworzyć taki skrót:</p>

<pre class="brush: js notranslate">const slice = Array.prototype.slice;

// ...

slice.apply(arguments);
</pre>

<p>Za pomocą bind () można to uprościć.</p>

<p>W poniższym fragmencie kodu slice () jest funkcją powiązaną z funkcją {{jsxref („Function.prototype.apply ()”, „Apply ()”)}} z {{jsxref („Function.prototype”) }}, z tą wartością ustawioną na {{jsxref („Array.prototype.slice ()”, „slice ()”)}} funkcji {{jsxref („Array.prototype”)}}. Oznacza to, że dodatkowe wywołania apply () można wyeliminować:</p>

<pre class="brush: js notranslate">//  same as "slice" in the previous example
const unboundSlice = Array.prototype.slice;
const slice = Function.prototype.apply.bind(unboundSlice);

// ...

slice(arguments);
</pre>

<p>Polyfill<br>
 Ponieważ starsze przeglądarki są na ogół również wolniejszymi przeglądarkami, jest to o wiele bardziej krytyczne niż większość ludzi rozpoznaje tworzenie polifillów wydajności, aby przeglądanie w przestarzałych przeglądarkach było nieco mniej straszne.</p>

<p>W związku z tym poniżej przedstawiono dwie opcje dla funkcji wypełniania funkcji Function.prototype.bind ():</p>

<p>Pierwszy jest znacznie mniejszy i bardziej wydajny, ale nie działa, gdy używasz nowego operatora.<br>
 Drugi jest większy i mniej wydajny, ale pozwala na pewne użycie nowego operatora na powiązanych funkcjach.<br>
 Zasadniczo w większości kodów bardzo rzadko widuje się nowe używane w funkcji powiązanej, więc najlepiej jest wybrać pierwszą opcję.</p>

<pre class="brush: js notranslate">//  Does not work with `new funcA.bind(thisArg, args)`
if (!Function.prototype.bind) (function(){
  var slice = Array.prototype.slice;
  Function.prototype.bind = function() {
    var thatFunc = this, thatArg = arguments[0];
    var args = slice.call(arguments, 1);
    if (typeof thatFunc !== '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');
    }
    return function(){
      var funcArgs = args.concat(slice.call(arguments))
      return thatFunc.apply(thatArg, funcArgs);
    };
  };
})();</pre>

<p>Możesz częściowo obejść ten problem, wstawiając następujący kod na początku skryptów, umożliwiając korzystanie z większości funkcji bind () w implementacjach, które nie obsługują go natywnie.</p>

<pre class="brush: js notranslate">//  Yes, it does work with `new funcA.bind(thisArg, args)`
if (!Function.prototype.bind) (function(){
  var ArrayPrototypeSlice = Array.prototype.slice;
  Function.prototype.bind = function(otherThis) {
    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 baseArgs= ArrayPrototypeSlice .call(arguments, 1),
        baseArgsLength = baseArgs.length,
        fToBind = this,
        fNOP    = function() {},
        fBound  = function() {
          baseArgs.length = baseArgsLength; // reset to default base arguments
          baseArgs.push.apply(baseArgs, arguments);
          return fToBind.apply(
                 fNOP.prototype.isPrototypeOf(this) ? this : otherThis, baseArgs
          );
        };

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

    return fBound;
  };
})();
</pre>

<p>Niektóre z wielu różnic (mogą być też inne, ponieważ ta lista nie próbuje być wyczerpująca) między tym algorytmem a określonym algorytmem to:</p>

<p>Częściowa implementacja opiera się na {{jsxref ("Array.prototype.slice ()")}}, {{jsxref ("Array.prototype.concat ()")}}, {{jsxref ("Function.prototype.call ( ) ")}} i {{jsxref (" Function.prototype.apply () ")}}, wbudowane metody mające swoje oryginalne wartości.<br>
 Częściowa implementacja tworzy funkcje, które nie mają niezmiennej „pigułki trucizny” {{jsxref („Function.caller”, „caller”)}} i właściwości argumentów, które wyrzucają {{jsxref („Global_Objects / TypeError”, „TypeError”) }} przy pobieraniu, ustawianiu lub usuwaniu. (Można to dodać, jeśli implementacja obsługuje {{jsxref („Object.defineProperty”)}} lub częściowo zaimplementowana [bez zachowania polegającego na rzucaniu przy usuwaniu], jeśli implementacja obsługuje {{jsxref („Object .__ zdefiniujGetter__”, „ __defineGetter__ ”)}} i {{jsxref („ Object .__ definiSetter__ ”,„ __defineSetter__ ”)}}).<br>
 Częściowa implementacja tworzy funkcje, które mają właściwość prototypu. (Właściwie powiązane funkcje nie mają żadnych.)<br>
 Częściowa implementacja tworzy powiązane funkcje, których właściwość {{jsxref („Function.length”, „length”)}}} nie zgadza się z właściwością nakazaną przez ECMA-262: tworzy funkcje o długości 0. Pełna implementacja - w zależności od długość funkcji docelowej i liczba wcześniej określonych argumentów - może zwrócić niezerową długość.<br>
 Częściowa implementacja tworzy powiązane funkcje, których właściwość {{jsxref („Function.name”, „name”)}} nie jest pochodną oryginalnej nazwy funkcji. Według ECMA-262 nazwa zwróconej funkcji powiązanej powinna być „związana” + nazwa funkcji docelowej.<br>
 Jeśli zdecydujesz się użyć tej częściowej implementacji, nie możesz polegać na przypadkach, w których zachowanie odbiega od ECMA-262, wydanie 5! Na szczęście te odchylenia od specyfikacji rzadko (jeśli w ogóle) pojawiają się w większości sytuacji kodowania. Jeśli nie rozumiesz żadnego z odchyleń od powyższej specyfikacji, w tym konkretnym przypadku można bezpiecznie nie martwić się o te niezgodne szczegóły odchylenia.</p>

<p>Jeśli jest to absolutnie konieczne, a wydajność nie stanowi problemu, znacznie wolniejsze (ale bardziej zgodne ze specyfikacją rozwiązanie) można znaleźć na stronie https://github.com/Raynos/function-bind.</p>

<h2 id="Dane_techniczne">Dane techniczne</h2>

<table class="standard-table">
 <thead>
  <tr>
   <th scope="col">Specyfikacja</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-function.prototype.bind', 'Function.prototype.bind')}}</td>
  </tr>
 </tbody>
</table>

<h5 id="Kompatybilność_z_przeglądarkami_Tabela_zgodności_na_tej_stronie_jest_generowana_z_danych_strukturalnych._Jeśli_chcesz_przyczynić_się_do_danych_sprawdź_httpsgithub.commdnbrowser-compat-data_i_wyślij_nam_żądanie_ściągnięcia._Compat_javascript.builtins.Function.bind">Kompatybilność z przeglądarkami<br>
 Tabela zgodności na tej stronie jest generowana z danych strukturalnych. Jeśli chcesz przyczynić się do danych, sprawdź https://github.com/mdn/browser-compat-data i wyślij nam żądanie ściągnięcia.<br>
 {{Compat ("javascript.builtins.Function.bind")}}</h5>

<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>