Heim  >  Artikel  >  Web-Frontend  >  So implementieren Sie Aufruf, Anwendung und Bindung nativ in js

So implementieren Sie Aufruf, Anwendung und Bindung nativ in js

不言
不言Original
2018-07-23 11:26:582117Durchsuche

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

call and apply

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 女

Simulationsimplementierung

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

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:

JS-Modulanalyse (Namespace)

Detaillierte Einführung in die JS-Vererbung (Prototypkette, Konstruktor, Kombination, Prototyp, parasitär, parasitäre Kombination, Klassenerweiterungen)

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn