Heim  >  Artikel  >  Web-Frontend  >  Umfassende Analyse hierzu in JavaScript

Umfassende Analyse hierzu in JavaScript

韦小宝
韦小宝Original
2017-11-30 10:41:301241Durchsuche

JavaScript enthält Objekte, natürlich ist es unverzichtbar, das Schlüsselwort this! Mit dem Schlüsselwort this wird der Code von JavaScript reduziert. Heute analysieren wir dies in JavaScript!

Implizite Bindung

Im Allgemeinen zeigt jeder, der eine Methode aufruft, auf wen diese Methode verweist, wie zum Beispiel:

function foo(){
    console.log(this.a)
}
var a = 3;
var obj = {
    a: 2,
    foo: foo
};
obj.foo(); // 输出2,因为是obj调用的foo,所以foo的this指向了obj,而obj.a = 2

Wenn es mehrere Aufrufe gibt, funktioniert nur die obere oder letzte Ebene der Objekt--Attribut--Referenzkette am aufrufenden Ort, wie zum Beispiel:

function foo() {
    console.log( this.a )
}
var obj2 = { 
    a: 42,
    foo: foo
}
var obj1 = {
    a: 2,
    obj2: obj2
}
obj1.obj2.foo(); // 42

Impliziter Verlust


Eines der häufigsten Bindungsprobleme besteht darin, dass implizit gebundene Funktionen verloren gehen. Binden Sie das Objekt, das bedeutet, dass die Standardbindung angewendet werden soll und diese somit an das globale Objekt oder undefiniert gebunden wird, je nachdem, ob es sich im strikten Modus befindet.

function foo() {
    console.log( this.a )
}
var obj1 = {
    a: 2,
    foo: foo
}
var bar = obj1.foo; // 函数别名!
var a = "oops, global"; // a是全局对象的属性
bar(); // "oops, global"

Obwohl bar ein Verweis auf obj.foo ist, bezieht es sich tatsächlich auf die foo-Funktion selbst, sodass bar() zu diesem Zeitpunkt tatsächlich ein Funktionsaufruf ohne Änderungen ist, sodass die Standardbindung angewendet wird

Eine subtilere, häufigere und unerwartetere Situation tritt auf, wenn eine Rückruffunktion übergeben wird:

function foo() {
    console.log( this.a )
}
function doFoo( fn ){
    // fn 其实引用的是 foo
    fn(); // <-- 调用位置!
}
var obj = {
    a: 2,
    foo: foo
}
var a = "oops, global"; // a是全局对象的属性
doFoo( obj.foo ); // "oops, global"

Parameterübergabe tatsächlich Es handelt sich um eine implizite Zuweisung, also wenn wir übergeben Eine Funktion wird ebenfalls implizit zugewiesen, sodass das Ergebnis das gleiche ist wie im vorherigen Beispiel. Wenn die Funktion an die integrierte Funktion der Sprache übergeben wird, anstatt an die von Ihnen deklarierte Funktion (z. B. setTimeout usw.). , das Ergebnis ist das gleiche

Explizite Bindung

Um es einfach auszudrücken: Geben Sie dies an, z. B.: Aufrufen, Anwenden, Binden, Neu Bindung usw.

Feste Bindung

function foo( something ) {
    console.log( this.a, something)
    return this.a + something
}
var obj = {
    a: 2
}
var bar = function() {
    return foo.apply( obj, arguments)
}
var b = bar(3); // 2 3
console.log(b); // 5

Hier eine kurze Erklärung: In der Bar-Funktion verwendet foo die Apply-Funktion, um obj zu binden, also an Sagen Sie, dass dies in foo auf obj zeigt. Gleichzeitig werden Argumente (keine Begrenzung der Anzahl der übergebenen Parameter) als Parameter verwendet und an die foo-Funktion übergeben. Wenn also bar(3) ausgeführt wird, steht obj.a an erster Stelle Die Ausgabe, die 2 und 3 ist, wird übergeben, und dann gibt foo die Summe der beiden zurück, sodass der Wert von b 5 ist


In ähnlicher Weise kann dieses Beispiel auch verwendet werden bind:

function foo( something ) {
    console.log( this.a, something)
    return this.a + something
}
var obj = {
    a: 2
}
var bar = foo.bind(obj)
var b = bar(3); // 2 3
console.log(b); // 5

neue Bindung

In traditionellen klassenorientierten Sprachen wird bei Verwendung von new zum Initialisieren einer Klasse das verwendet Der Konstruktor in der Klasse wird aufgerufen, aber der neue Mechanismus in JS unterscheidet sich tatsächlich völlig von klassenorientiert und sprachorientiert.

Verwenden Sie new, um eine Funktion aufzurufen, oder wenn ein Konstruktoraufruf erfolgt, werden die folgenden Vorgänge automatisch ausgeführt:

Erstellen (oder konstruieren) Sie ein brandneues Objekt

Dies Das neue Objekt wird ausgeführt [[Prototyp]] Verbindung

Dieses neue Objekt wird an diesen

des Funktionsaufrufs gebunden. Wenn die Funktion keine anderen Objekte zurückgibt, dann das neueAusdruckDie Funktion in gibt automatisch dieses neue Objekt zurück, z. B.:

function foo(a){
    this.a = a
}
var bar = new foo(2);
console.log(bar.a); // 2

Wenn wir new verwenden, um foo(…) aufzurufen, erstellen wir ein neues Objekt und binden es an den Aufruf foo( …) dazu. new ist die letzte Methode, die das Verhalten dieser Bindung beeinflussen kann, wenn eine Funktion aufgerufen wird. Wir nennen sie neue Bindung.

Das ist Priorität

Es besteht kein Zweifel, dass die Priorität der Standardbindung die niedrigste unter den vier Regeln ist , also können wir es zunächst ignorieren.


Welches hat die höhere Priorität, implizite Bindung oder explizite Bindung? Testen wir es:

function foo(a){
    console.log(this.a)
}
var obj1 = {
    a: 2,
    foo: foo
}
var obj2 = {
    a: 3,
    foo: foo
}
obj1.foo(); // 2
obj2.foo(); // 3
obj1.foo.call(obj2); // 3
obj2.foo.call(obj1); // 2

Wie Sie sehen, hat die explizite Bindung eine höhere Priorität, was bedeutet, dass bei der Beurteilung zunächst berücksichtigt werden sollte, ob eine explizite Bindung vorliegen kann.

Jetzt müssen wir herausfinden, wer zwischen neuer Bindung und impliziter Bindung eine höhere Priorität und wer eine niedrigere Priorität hat:

function foo(something){
    this.a = something
}
var obj1 = {
    foo: foo
}
var obj2 = {}
obj1.foo(2); 
console.log(obj1.a); // 2
obj1.foo.call(obj2,3);
console.log(obj2.a); // 3
var bar = new obj1.foo(4)
console.log(obj1.a); // 2
console.log(bar.a); // 4

Sie können sehen, dass neue Bindung eine höhere Priorität hat als implizite Bindung. Aber welche hat die höhere Priorität, neue Bindung oder explizite Bindung?

function foo(something){
    this.a = something
}
var obj1 = {}
var bar = foo.bind(obj1);
bar(2);
console.log(obj1.a); // 2
var baz = new bar(3);
console.log(obj1.a); // 2
console.log(baz.a); // 3

Wie Sie sehen können, ändert die neue Bindung dies in der harten Bindung, sodass die neue Bindung eine höhere Priorität hat als die explizite Bindung.


Der Hauptzweck der Verwendung fest gebundener Funktionen in new besteht darin, einige Parameter der Funktion vorab festzulegen, sodass bei der Initialisierung mit new nur der Rest übergeben werden kann Parameter. Eine der Funktionen von bind(...) besteht darin, dass alle Parameter außer dem ersten Parameter (der erste Parameter wird zum Binden verwendet) an die zugrunde liegende Funktion übergeben werden können (diese Technik wird als „Teilanwendung“ bezeichnet und ist eine Art von „Curry“). Zum Beispiel:

function foo(p1,p2){
    this.val = p1 + p2;
}
// 之所以使用null是因为在本例中我们并不关心硬绑定的this是什么
// 反正使用new时this会被修改
var bar = foo.bind(null,&#39;p1&#39;);
var baz = new bar(&#39;p2&#39;);
baz.val; // p1p2
}

Currying: Intuitiv besagt Currying, dass „wenn Sie einige Parameter festlegen, erhalten Sie eine Funktion, die die verbleibenden Parameter akzeptiert“. Wenn also für die Funktion yx mit zwei Variablen y = 2 fest ist, erhalten wir die Funktion 2x mit einer Variablen

Diese Anwendung in Pfeilfunktionen

Die Pfeilfunktion verwendet nicht die vier Standardregeln davon, sondern bestimmt dies anhand des äußeren (Funktions- oder globalen) Geltungsbereichs.

我们来看一下箭头函数的词法作用域:

function foo() {
    // 返回一个箭头函数
    return (a) => {
        // this继承自foo()
        console.log(this.a)
    };
}
var obj1 = {
    a: 2
};
var obj2 = {
    a: 3
};
var bar = foo.call(obj1);
bar.call(obj2); // 2, 不是3!

foo()内部创建的箭头函数会捕获调用时foo()的this。由于foo()的this绑定到obj1,bar(引用箭头函数)的this也会绑定到obj1,箭头函数的绑定无法被修改。(new也不行!)

总结

如果要判断一个运行中的函数的this绑定,就需要找到这个函数的直接调用位置。找到之后就可以顺序应用下面这四条规则来判断this的绑定对象。

由new调用?绑定到新创建的对象。

由call或者apply(或者bind)调用?绑定到指定的对象。

由上下文对象调用?绑定到那个上下文对象。

默认:在严格模式下绑定到undefined,否则绑定到全局对象。

相关推荐:

JavaScript学习笔记之基础语法

JavaScript 是真正的 OOP 语言吗?

如何用JavaScript修改伪类样式

Das obige ist der detaillierte Inhalt vonUmfassende Analyse hierzu in JavaScript. 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