Heim  >  Artikel  >  Web-Frontend  >  Vertiefendes Verständnis davon in ECMA Javascript (mit Beispielen)

Vertiefendes Verständnis davon in ECMA Javascript (mit Beispielen)

不言
不言nach vorne
2018-11-24 14:05:592240Durchsuche

Dieser Artikel vermittelt Ihnen ein detailliertes Verständnis davon in ECMA-Javascript (mit Beispielen). Ich hoffe, dass er für Freunde in Not hilfreich ist.

Dies ist eigentlich eine Bindung, die auftritt, wenn die Funktion aufgerufen wird, und worauf sie verweist, hängt vollständig davon ab, wo die Funktion aufgerufen wird (d. h. wie die Funktion aufgerufen wird).

Vier Regeln: (JS, das weißt du nicht)

1. Standardbindung

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

Ob es streng ist oder nicht Modus, im globalen Ausführungskontext (außerhalb eines Funktionskörpers) bezieht sich dies auf das globale Objekt. (MDN)
Im strikten Modus behält dies seinen Wert, wenn es in den Ausführungskontext eintritt. Wenn dies nicht durch den Ausführungskontext definiert ist, bleibt es undefiniert. (MDN)

function foo() {
    "use strict";
    console.log( this.a );
}
var a = 2;
foo(); // TypeError: this is undefined

2. Implizite Bindung/Verlust

Wenn Funktionen als Methoden in Objekten aufgerufen werden, ist dies das Objekt, das die Funktion aufruft, und die Bindung wird nur durch den Einfluss beeinflusst der nächstgelegenen Mitgliedsreferenz. (MDN)

//隐式绑定
function foo() {
    console.log( this.a );
}
var obj2 = {
    a: 42,
    foo: foo
};
var obj1 = {
    a: 2,
    obj2: obj2
};
obj1.obj2.foo(); // 42
//隐式丢失
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"

3. Anzeigebindung

Wenn Sie den Wert davon von einem Kontext an einen anderen übergeben möchten, müssen Sie die Methode call oder apply verwenden. (MDN)
Durch den Aufruf von f.bind(someObject) wird eine Funktion mit demselben Funktionskörper und Umfang wie f erstellt, aber in dieser neuen Funktion wird diese dauerhaft an den ersten Parameter von bind gebunden, egal wie diese Funktion ist heißt.

var obj = {
    count: 0,
    cool: function coolFn() {
    if (this.count < 1) {
        setTimeout( function timer(){
            this.count++; // this 是安全的
                            // 因为 bind(..)
            console.log( "more awesome" );
            }.bind( this ), 100 ); // look, bind()!
        }
    }
};
obj.cool(); // 更酷了。

Harte Bindung

Erstellt eine Wrapper-Funktion, die alle Parameter übergibt und alle empfangenen Werte zurückgibt.
Eine harte Bindung verringert die Flexibilität der Funktion erheblich. Nach der Verwendung einer harten Bindung können Sie diese nicht mehr mit impliziter Bindung oder expliziter Bindung ändern.

// 简单的辅助绑定函数
function bind(fn, obj) {
    return function() {
        return fn.apply( obj, arguments );
    };
}

Weiche Bindung

Geben Sie ein globales Objekt und einen anderen Wert als undefiniert für die Standardbindung an. Dann können Sie den gleichen Effekt wie eine harte Bindung erzielen und gleichzeitig die implizite Bindung oder explizite Bindung beibehalten Ich bin verpflichtet, dies zu ändern.

Function.prototype.softBind = function(obj) {
    var fn = this;
    var curried = [].slice.call( arguments, 1 );// 捕获所有 curried 参数
    var bound = function() {
        return fn.apply(
            (!this || this === (window || global))?obj : this
            curried.concat.apply( curried, arguments )
        );
    };
    bound.prototype = Object.create( fn.prototype );
    return bound;
};

4. Neue Bindung

Wenn eine Funktion als Konstruktor verwendet wird (mit dem Schlüsselwort new), wird this an das neue Objekt gebunden, das erstellt wird. (MDN)
Verwenden Sie new, um eine Funktion aufzurufen, oder wenn ein Konstruktoraufruf auftritt, werden die folgenden Vorgänge automatisch ausgeführt (JS, das Sie nicht kennen)

  1. Erstellen (oder konstruieren ) ein völlig neues Objekt.

  2. Dieses neue Objekt wird durch [[ Prototyp ]] verbunden.

  3. Dieses neue Objekt wird an das This des Funktionsaufrufs gebunden.

  4. Wenn die Funktion kein anderes Objekt zurückgibt, dann gibt der Funktionsaufruf im neuen Ausdruck automatisch dieses neue Objekt zurück.

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

Vier Regelprioritäten

Neue Bindung> implizite Bindung> >Wird die Funktion neu aufgerufen (neue Bindung)? Wenn ja, wird dies an das neu erstellte Objekt gebunden.

 var bar = new foo()
  1. Wird die Funktion über call , apply (explizite Bindung) oder harte Bindung aufgerufen? Wenn ja, wird dies an das angegebene Objekt gebunden.

  2. Zusätzlich:
  3. Wenn die Bindung null oder undefiniert ist, werden tatsächlich die Standardbindungsregeln angewendet.

     var bar = foo.call(obj2)

    Wird die Funktion in einem Kontextobjekt aufgerufen (implizit gebunden)? Wenn ja, ist dies an dieses Kontextobjekt gebunden.
     var bar = obj1.foo()
  4. Wenn beides nicht der Fall ist, verwenden Sie die Standardbindung. Im strikten Modus ist es an undefiniert gebunden, andernfalls ist es an das globale Objekt gebunden.

     var bar = foo()
  5. wobei:

    Indirekte Referenzfunktionen wenden die Standardbindungsregeln an

    function foo() {
        console.log( this.a );
    }
    var a = 2;
    var o = { a: 3, foo: foo };
    var p = { a: 4 };
    o.foo(); // 3
    (p.foo = o.foo)(); // 2

    Ausnahmen

1. Pfeilfunktion

Die Pfeilfunktion verwendet nicht die vier Standardregeln, sondern bestimmt dies anhand des äußeren (Funktions- oder globalen) Geltungsbereichs. In Pfeilfunktionen stimmt dies mit dem Dies des umschließenden lexikalischen Kontexts überein. (MDN)Pfeilfunktionen erben die This-Bindung des äußeren Funktionsaufrufs (unabhängig davon, woran diese gebunden ist). Dies ist tatsächlich der gleiche Mechanismus wie self = this.

Pfeilfunktionsbindungen können nicht geändert werden.



2. nodejs

setTimeout(function() { 
    console.log(this) 
    //浏览器中:window 
    //nodejs中:Timeout实例
}, 0)

Weitere Erklärungen

https://www.zhihu.com/questio... func(p1, p2) ist äquivalent zu func.call(undefiniert, p1, p2)

obj.child.method(p1, p2) ist äquivalent zu
obj.child .method.call(obj.child, p1, p2)

Wenn der von Ihnen übergebene Kontext null oder undefiniert ist, dann ist das Fensterobjekt der Standardkontext (der Standardkontext im strikten Modus ist undefiniert)


Beispiel

    var number = 50;
    var obj = {
        number: 60,
        getNum: function () {
        var number = 70;
        return this.number;
    }
    }; 

    alert(obj.getNum());
    alert(obj.getNum.call());
    alert(obj.getNum.call({number:20}));

Das obige ist der detaillierte Inhalt vonVertiefendes Verständnis davon in ECMA Javascript (mit Beispielen). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen