Der Inhalt dieses Artikels befasst sich mit der nativen Implementierung von Aufrufen, der Anwendung und der Bindung in js. Freunde in Not können sich darauf beziehen.
Da es sich um das hier angesprochene Problem handelt, kann man die Verwendung von „call“, „apply“ und „bind“ als Klischee bezeichnen. Die Hauptfunktion dieses Artikels besteht darin, die nativen Methoden von js zu verwenden, um die drei Methoden zu implementieren, die Prinzipien zu verstehen und relevante Wissenspunkte besser zu verstehen. Native Implementierung der Github-Adresse call, apply und bind
Eine kurze Einführung: Die Call- und Apply-Methoden rufen beide eine Funktion unter Verwendung eines angegebenen Werts und entsprechender Parameter oder Methoden auf. Der Unterschied besteht darin, dass call mehrere Parameter übergibt, während apply ein Array übergibt.
Zum Beispiel:
var obj = { name: 'linxin' } function func(age, sex) { console.log(this.name,age,sex); } func.call(obj,12,'女'); // linxin 12 女 func.apply(obj, [18, '女']); //linxin 18 女
Idee: Der in JavaScript erwähnte Zeiger: Die Funktion kann auch als Methode eines Objekts aufgerufen werden, dann verweist dies auf dieses übergeordnete Objekt . Das ist es, was wir normalerweise sagen, wer anruft, wird darauf hinweisen. Die Implementierungsmethode besteht also darin, eine solche Methode zum eingehenden Objekt hinzuzufügen und diese Methode dann auszuführen. Um das Objekt persistent zu halten, wird das Objekt nach der Ausführung gelöscht. Ist es nicht ganz einfach^-^?
Erste Erfahrung:
Function.prototype.newCall = function(context) { context.fn = this; // 通过this获取call的函数 context.fn(); delete context.fn; } let foo = { value: 1 } function bar() { console.log(this.value); } bar.newCall (foo); // 1
Damit ist die Implementierung der Basisversion abgeschlossen, aber was ist, wenn Parameter übergeben werden müssen?
Damit wir es optimieren können, da die Anzahl der übergebenen Parameter ungewiss ist, können wir es aus dem Arguments-Objekt abrufen, was relativ einfach ist. Das Problem besteht darin, dass die Parameter unsicher sind. Wie übergeben wir sie an die Funktion, die wir ausführen möchten? Hier haben wir zwei Möglichkeiten: Eine besteht darin, Eval-Spleißen durchzuführen, und die andere besteht darin, es6 zu verwenden.
Erlebnis-Upgrade (Evaluierungsversion):
Function.prototype.newCall = function(context) { context.fn = this; var args = []; for(var i = 1, len = arguments.length; i < len; i++) { args.push('arguments[' + i + ']'); } eval('context.fn(' + args +')'); delete context.fn; } let person = { name: 'Abiel' } function sayHi(age,sex) { console.log(this.name, age, sex); } sayHi.newCall (person, 25, '男'); // Abiel 25 男
Erlebnis-Upgrade (ES6-Version):
Function.prototype.newCall = function(context) { context.fn = this; context.fn(...Array.from(arguments).slice(1)); delete context.fn; } let person = { name: 'Abiel' } function sayHi(age,sex) { console.log(this.name, age, sex); } sayHi.newCall (person, 25, '男'); // Abiel 25 男
Lassen Sie die ES6-Methode weiterhin funktionieren
Die ES6-Version kann ohne Verwendung von Argumenten aktualisiert werden:
Function.prototype.newCall = function(context, ...parameter) { context.fn = this; context.fn(...parameter); delete context.fn; } let person = { name: 'Abiel' } function sayHi(age,sex) { console.log(this.name, age, sex); } sayHi.newCall (person, 25, '男'); // Abiel 25 男
Auf diese Weise realisieren wir grundsätzlich die Aufruffunktion, es gibt jedoch noch einige versteckte Gefahren und Unterschiede.
Wenn das Objekt selbst über die fn-Methode verfügt, gibt es ein großes Problem.
Wenn das vom Aufruf übergebene Objekt null oder ein anderer Typ ist, meldet die Funktion einen Fehler.
Ultimative Erfahrung:
Function.prototype.newCall = function(context, ...parameter) { if (typeof context === 'object') { context = context || window } else { context = Object.create(null) } let fn = Symbol() context[fn] = this context[fn](...parameter); delete context[fn] } let person = { name: 'Abiel' } function sayHi(age,sex) { console.log(this.name, age, sex); } sayHi.newCall (person, 25, '男'); // Abiel 25 男
Nach der Implementierung von Call hat apply die gleiche Idee.
Apply-Implementierung:
Function.prototype.newApply = function(context, parameter) { if (typeof context === 'object') { context = context || window } else { context = Object.create(null) } let fn = Symbol() context[fn] = this context[fn](parameter); delete context[fn] }
bind ist ebenfalls eine Funktionsmethode. Ihre Funktion besteht darin, die Ausführung dieser Methode zu ändern, und sie kann auch mehrere Parameter übergeben . Im Gegensatz zu call und apply wird die Bind-Methode nicht sofort ausgeführt, sondern gibt eine Funktion zurück, die den Kontext ändert, auf den sie verweist. Die ursprüngliche Funktion wurde nicht geändert. Und wenn die Funktion selbst eine an dieses Objekt gebundene Funktion ist, werden „Apply“ und „Call“ nicht wie erwartet ausgeführt.
Erste Erfahrung:
Function.prototype.bind = function (context) { var me = this return function () { // bind之后得到的函数 return me.call(context) // 执行是改变this执行 } }
Hinzugefügte Parameter:
Function.prototype.bind = function (context,...innerArgs) { var me = this return function (...finnalyArgs) { return me.call(context,...innerArgs,...finnalyArgs) } } let person = { name: 'Abiel' } function sayHi(age,sex) { console.log(this.name, age, sex); } let personSayHi = sayHi.bind(person, 25) personSayHi('男')
Verwandte Empfehlungen:
Das obige ist der detaillierte Inhalt vonSo implementieren Sie Aufruf, Anwendung und Bindung nativ in js. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!