Movatterモバイル変換


[0]ホーム

URL:


MDN Web Docs

Experiment: Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten.

Function.prototype.bind()

BaselineWidely available

Diebind()-Methode vonFunction-Instanzen erstellt eine neue Funktion, die, wenn sie aufgerufen wird, diese Funktion mit ihremthis-Schlüsselwort auf den angegebenen Wert gesetzt aufruft, und eine gegebene Sequenz von Argumenten vor denjenigen bereitstellt, die beim Aufruf der neuen Funktion bereitgestellt werden.

Probieren Sie es aus

const module = {  x: 42,  getX() {    return this.x;  },};const unboundGetX = module.getX;console.log(unboundGetX()); // The function gets invoked at the global scope// Expected output: undefinedconst boundGetX = unboundGetX.bind(module);console.log(boundGetX());// Expected output: 42

Syntax

js
bind(thisArg)bind(thisArg, arg1)bind(thisArg, arg1, arg2)bind(thisArg, arg1, arg2, /* …, */ argN)

Parameter

thisArg

Der Wert, der alsthis-Parameter an die Ziel-Funktionfunc übergeben wird, wenn die gebundene Funktion aufgerufen wird. Wenn die Funktion nicht imstrict mode ist, werdennull undundefined durch das globale Objekt ersetzt, und primitive Werte werden in Objekte umgewandelt. Der Wert wird ignoriert, wenn die gebundene Funktion mit demnew-Operator konstruiert wird.

arg1, …,argNOptional

Argumente, die den Argumenten vorangestellt werden, die bei der Ausführung vonfunc an die gebundene Funktion übergeben werden.

Rückgabewert

Eine Kopie der angegebenen Funktion mit dem spezifiziertenthis-Wert und anfänglichen Argumenten (falls vorhanden).

Beschreibung

Diebind()-Funktion erstellt eine neuegebundene Funktion. Der Aufruf der gebundenen Funktion führt im Allgemeinen zur Ausführung der Funktion, die sie umschließt, welche auch dieZiel-Funktion genannt wird. Die gebundene Funktion speichert die übergebenen Parameter – die den Wert vonthis und die ersten Argumente enthalten – als ihren internen Zustand. Diese Werte werden im Voraus gespeichert, anstatt zur Aufrufzeit übergeben zu werden. Sie können im Allgemeinenconst boundFn = fn.bind(thisArg, arg1, arg2) als äquivalent zuconst boundFn = (...restArgs) => fn.call(thisArg, arg1, arg2, ...restArgs) für die Wirkung beim Aufruf sehen (aber nicht beim Konstruieren vonboundFn).

Eine gebundene Funktion kann durch Aufruf vonboundFn.bind(thisArg, /* weitere args */) weiter gebunden werden, was eine weitere gebundene FunktionboundFn2 erstellt. Der neu gebundenethisArg-Wert wird ignoriert, da die Ziel-Funktion vonboundFn2, dieboundFn ist, bereits ein gebundenesthis hat. WennboundFn2 aufgerufen wird, ruft esboundFn auf, was wiederumfn aufruft. Die Argumente, diefn letztendlich erhält, sind in der Reihenfolge: die vonboundFn gebundenen Argumente, die vonboundFn2 gebundenen Argumente und die vonboundFn2 empfangenen Argumente.

js
"use strict"; // prevent `this` from being boxed into the wrapper objectfunction log(...args) {  console.log(this, ...args);}const boundLog = log.bind("this value", 1, 2);const boundLog2 = boundLog.bind("new this value", 3, 4);boundLog2(5, 6); // "this value", 1, 2, 3, 4, 5, 6

Eine gebundene Funktion kann auch mit demnew-Operator konstruiert werden, wenn ihre Ziel-Funktion konstruierbar ist. Dies wirkt so, als ob die Ziel-Funktion stattdessen konstruiert worden wäre. Die vorangestellten Argumente werden wie üblich an die Ziel-Funktion übergeben, während der bereitgestelltethis-Wert ignoriert wird (da Konstruktion ihr eigenesthis vorbereitet, wie bei den Parametern vonReflect.construct sichtbar). Wenn die gebundene Funktion direkt konstruiert wird, wirdnew.target die Ziel-Funktion anstatt. (Das heißt, die gebundene Funktion ist fürnew.target transparent.)

js
class Base {  constructor(...args) {    console.log(new.target === Base);    console.log(args);  }}const BoundBase = Base.bind(null, 1, 2);new BoundBase(3, 4); // true, [1, 2, 3, 4]

Da eine gebundene Funktion jedoch nicht dieprototype-Eigenschaft hat, kann sie nicht als Basisklasse fürextends verwendet werden.

js
class Derived extends class {}.bind(null) {}// TypeError: Class extends value does not have valid prototype property undefined

Wenn eine gebundene Funktion als rechte Seite voninstanceof verwendet wird, würdeinstanceof nach der Ziel-Funktion (die intern in der gebundenen Funktion gespeichert ist) greifen und ihrenprototype lesen.

js
class Base {}const BoundBase = Base.bind(null, 1, 2);console.log(new Base() instanceof BoundBase); // true

Die gebundene Funktion hat die folgenden Eigenschaften:

length

Derlength der Ziel-Funktion minus die Anzahl der gebundenen Argumente (ohne denthisArg-Parameter zu zählen), wobei 0 der Mindestwert ist.

name

Dername der Ziel-Funktion plus ein"bound "-Präfix.

Die gebundene Funktion erbt auch diePrototype-Kette der Ziel-Funktion. Sie hat jedoch keine anderen eigenen Eigenschaften der Ziel-Funktion (wiestatische Eigenschaften, wenn die Ziel-Funktion eine Klasse ist).

Beispiele

Eine gebundene Funktion erstellen

Die häufigste Verwendung vonbind() besteht darin, eine Funktion zu erstellen, die, egal wie sie aufgerufen wird, mit einem bestimmtenthis-Wert aufgerufen wird.

Ein häufiger Fehler für neue JavaScript-Programmierer ist es, eine Methode aus einem Objekt zu extrahieren, dann diese Funktion später aufzurufen und zu erwarten, dass sie das ursprüngliche Objekt als ihrthis verwendet (z.B. durch Verwendung der Methode in rückrufbasierter Code).

Ohne besondere Vorsichtsmaßnahmen geht jedoch das ursprüngliche Objekt normalerweise verloren. Durch das Erstellen einer gebundenen Funktion aus der Funktion unter Verwendung des ursprünglichen Objekts kann dieses Problem elegant gelöst werden:

js
// Top-level 'this' is bound to 'globalThis' in scripts.this.x = 9;const module = {  x: 81,  getX() {    return this.x;  },};// The 'this' parameter of 'getX' is bound to 'module'.console.log(module.getX()); // 81const retrieveX = module.getX;// The 'this' parameter of 'retrieveX' is bound to 'globalThis' in non-strict mode.console.log(retrieveX()); // 9// Create a new function 'boundGetX' with the 'this' parameter bound to 'module'.const boundGetX = retrieveX.bind(module);console.log(boundGetX()); // 81

Hinweis:Wenn Sie dieses Beispiel imstrict mode ausführen, wird derthis-Parameter vonretrieveX aufundefined gebunden anstatt aufglobalThis, was dazu führt, dass der Aufruf vonretrieveX() fehlschlägt.

Wenn Sie dieses Beispiel in einem ECMAScript-Modul ausführen, wird das oberstethis aufundefined gebunden anstatt aufglobalThis, was dazu führt, dass die Zuweisungthis.x = 9 fehlschlägt.

Wenn Sie dieses Beispiel in einem Node CommonJS-Modul ausführen, wird das oberstethis aufmodule.exports gebunden anstatt aufglobalThis. Derthis-Parameter vonretrieveX wird jedoch in non-strict mode noch aufglobalThis gebunden und in strict mode aufundefined. Daher wird in non-strict mode (der Voreinstellung) der Aufruf vonretrieveX()undefined zurückgeben, weilthis.x = 9 auf ein anderes Objekt (module.exports) schreibt als von demgetX liest (globalThis).

Tatsächlich sind einige eingebauten "Methoden" auch Getter, die gebundene Funktionen zurückgeben — ein bemerkenswertes Beispiel istIntl.NumberFormat.prototype.format(), die bei Zugriff eine gebundene Funktion zurückgibt, die Sie direkt als Rückruf weitergeben können.

Partiell angewendete Funktionen

Eine weitere Verwendung vonbind() besteht darin, eine Funktion mit vordefinierten Anfangsargumenten zu erstellen.

Diese Argumente (falls vorhanden) folgen dem bereitgestelltenthis-Wert und werden dann am Anfang der Argumente eingefügt, die an die Ziel-Funktion weitergegeben werden, gefolgt von allen Argumenten, die zur Zeitpunkt des Aufrufs an die gebundene Funktion übergeben werden.

js
function list(...args) {  return args;}function addArguments(arg1, arg2) {  return arg1 + arg2;}console.log(list(1, 2, 3)); // [1, 2, 3]console.log(addArguments(1, 2)); // 3// Create a function with a preset leading argumentconst leadingThirtySevenList = list.bind(null, 37);// Create a function with a preset first argument.const addThirtySeven = addArguments.bind(null, 37);console.log(leadingThirtySevenList()); // [37]console.log(leadingThirtySevenList(1, 2, 3)); // [37, 1, 2, 3]console.log(addThirtySeven(5)); // 42console.log(addThirtySeven(5, 10)); // 42// (the last argument 10 is ignored)

Mit setTimeout()

Standardmäßig wird innerhalb vonsetTimeout() dasthis-Schlüsselwort aufglobalThis gesetzt, das in Browsernwindow ist. Wenn Sie mit Klassenmethoden arbeiten, die erfordern, dassthis auf Klasseninstanzen verweist, können Siethis explizit an die Rückruffunktion binden, um die Instanz beizubehalten.

js
class LateBloomer {  constructor() {    this.petalCount = Math.floor(Math.random() * 12) + 1;  }  bloom() {    // Declare bloom after a delay of 1 second    setTimeout(this.declare.bind(this), 1000);  }  declare() {    console.log(`I am a beautiful flower with ${this.petalCount} petals!`);  }}const flower = new LateBloomer();flower.bloom();// After 1 second, calls 'flower.declare()'

Sie können hierfür auchPfeilfunktionen verwenden.

js
class LateBloomer {  bloom() {    // Declare bloom after a delay of 1 second    setTimeout(() => this.declare(), 1000);  }}

Gebundene Funktionen, die als Konstruktoren verwendet werden

Gebundene Funktionen sind automatisch für die Verwendung mit demnew-Operator geeignet, um neue Instanzen zu konstruieren, die von der Ziel-Funktion erstellt werden. Wenn eine gebundene Funktion verwendet wird, um einen Wert zu konstruieren, wird das bereitgestelltethis ignoriert. Es werden jedoch weiterhin bereitgestellte Argumente vor dem Konstruktorruf eingefügt.

js
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'// The thisArg's value doesn't matter because it's ignoredconst YAxisPoint = Point.bind(null, 0 /* x */);const axisPoint = new YAxisPoint(5);axisPoint.toString(); // '0,5'axisPoint instanceof Point; // trueaxisPoint instanceof YAxisPoint; // truenew YAxisPoint(17, 42) instanceof Point; // true

Beachten Sie, dass Sie nichts Besonderes tun müssen, um eine gebundene Funktion zur Verwendung mitnew zu erstellen.new.target,instanceof,this usw. funktionieren alle wie erwartet, als ob der Konstruktor nie gebunden wäre. Der einzige Unterschied ist, dass er nicht mehr fürextends verwendet werden kann.

Die Folge davon ist, dass Sie nichts Besonderes tun müssen, um eine gebundene Funktion zu erstellen, die einfach aufgerufen werden kann, selbst wenn Sie lieber verlangen würden, dass die gebundene Funktion nur unter Verwendung vonnew aufgerufen wird. Wenn Sie sie ohnenew aufrufen, wird das gebundenethis plötzlich nicht ignoriert.

js
const emptyObj = {};const YAxisPoint = Point.bind(emptyObj, 0 /* x */);// Can still be called as a normal function// (although usually this is undesirable)YAxisPoint(13);// The modifications to `this` is now observable from the outsideconsole.log(emptyObj); // { x: 0, y: 13 }

Wenn Sie eine gebundene Funktion nur mitnew aufrufbar oder nur ohnenew aufrufbar machen möchten, muss die Ziel-Funktion diese Einschränkung durchsetzen, z.B. durch Überprüfung vonnew.target !== undefined oder Verwendung einerKlasse.

Binden von Klassen

Die Verwendung vonbind() bei Klassen erhält die meisten Semantiken der Klasse, wobei jedoch alle statischen eigenen Eigenschaften der aktuellen Klasse verloren gehen. Da jedoch die Prototype-Kette erhalten bleibt, können Sie dennoch auf statische Eigenschaften der übergeordneten Klasse zugreifen.

js
class Base {  static baseProp = "base";}class Derived extends Base {  static derivedProp = "derived";}const BoundDerived = Derived.bind(null);console.log(BoundDerived.baseProp); // "base"console.log(BoundDerived.derivedProp); // undefinedconsole.log(new BoundDerived() instanceof Derived); // true

Methoden in Utility-Funktionen umwandeln

bind() ist auch in Fällen hilfreich, bei denen Sie eine Methode, die einen spezifischenthis-Wert erfordert, in eine einfache Utility-Funktion umwandeln möchten, die den vorherigenthis-Parameter als normalen Parameter akzeptiert. Dies ist ähnlich wie allgemeine Utility-Funktionen: anstattarray.map(callback) aufzurufen, verwenden Siemap(array, callback), wodurch Siemap mit array-ähnlichen Objekten verwenden können, die keine Arrays sind (z.B.arguments), ohneObject.prototype zu ändern.

Nehmen SieArray.prototype.slice(), zum Beispiel, das Sie verwenden möchten, um ein array-ähnliches Objekt in ein echtes Array zu konvertieren. Sie könnten eine Abkürzung erstellen wie diese:

js
const slice = Array.prototype.slice;// …slice.call(arguments);

Beachten Sie, dass Sieslice.call nicht speichern und als einfache Funktion aufrufen können, weil diecall()-Methode auch ihrenthis-Wert liest, was die Funktion ist, die sie aufrufen soll. In diesem Fall können Siebind() verwenden, um den Wert vonthis fürcall() zu binden. Im folgenden Code istslice() eine gebundene Version vonFunction.prototype.call(), wobei derthis-Wert anArray.prototype.slice() gebunden ist. Dies bedeutet, dass zusätzlichecall()-Aufrufe eliminiert werden können:

js
// Same as "slice" in the previous exampleconst unboundSlice = Array.prototype.slice;const slice = Function.prototype.call.bind(unboundSlice);// …slice(arguments);

Spezifikationen

Specification
ECMAScript® 2026 Language Specification
# sec-function.prototype.bind

Browser-Kompatibilität

Siehe auch

MDN-Feedback-Box

Diese Seite wurde automatisch aus dem Englischen übersetzt.


[8]ページ先頭

©2009-2025 Movatter.jp