Heim  >  Artikel  >  Web-Frontend  >  Tipps, Arbeitsprinzipien und Vorsichtsmaßnahmen für die Verwendung dieses Schlüsselworts in JavaScript_Javascript-Tipps

Tipps, Arbeitsprinzipien und Vorsichtsmaßnahmen für die Verwendung dieses Schlüsselworts in JavaScript_Javascript-Tipps

WBOY
WBOYOriginal
2016-05-16 16:47:301472Durchsuche

Um dies je nach Standort zu verstehen, kann die Situation grob in drei Typen unterteilt werden:

1. In Funktionen: Dies ist normalerweise ein impliziter Parameter.

2. Außerhalb der Funktion (im Top-Level-Bereich): Im Browser bezieht sich dies auf das globale Objekt in Node.js, es bezieht sich auf die Exporte des Moduls.

 3. Die an eval() übergebene Zeichenfolge: Wenn eval() direkt aufgerufen wird, bezieht sich dies auf das aktuelle Objekt; wenn eval() indirekt aufgerufen wird, bezieht sich dies auf das globale Objekt.

Für diese Kategorien haben wir entsprechende Tests durchgeführt:
1. Dies in der Funktion

Funktionen können grundsätzlich alle aufrufbaren Strukturen in JS darstellen, daher ist dies das häufigste Szenario für die Verwendung, und Funktionen können in die folgenden drei Rollen unterteilt werden:

Echte Funktion
Konstruktor
Methode

 1.1 dies

in realen Funktionen

In realen Funktionen ist der Wert davon ein Muster, das vom Kontext abhängt, in dem es gefunden wird.

Sloppy-Modus: Dies bezieht sich auf das globale Objekt (Fenster im Browser).

Code kopieren Der Code lautet wie folgt:

Funktion sloppyFunc() {
Konsole .log( this === window); // true
}
sloppyFunc();

Strikter Modus: Der Wert ist undefiniert.

Code kopieren Der Code lautet wie folgt:

function strictFunc() {
' use strict' ;
console.log(this === undefiniert); // true
}
strictFunc();

Dies ist ein impliziter Parameter der Funktion, daher ist sein Wert immer derselbe. Sie können den Wert jedoch explizit definieren, indem Sie die Methoden call() oder apply() verwenden.

Code kopieren Der Code lautet wie folgt:

Funktion func(arg1, arg2) {
console .log(this); // 1
console.log(arg1); // 2
console.log(arg2); // 3
}
func.call(1 , 2, 3); // (this, arg1, arg2)
func.apply(1, [2, 3]); // (this, arrayWithArgs)

1.2 this

im Konstruktor

Sie können new verwenden, um eine Funktion als Konstruktor zu verwenden. Die neue Operation erstellt ein neues Objekt und übergibt dieses Objekt über diesen an den Konstruktor.

Code kopieren Der Code lautet wie folgt:

var savingThis;
function Constr( ) {
savingThis = this;
}
var inst = new Constr();
console.log(savedThis === inst); // true

Das Implementierungsprinzip neuer Operationen in JS ist ungefähr wie im folgenden Code dargestellt (eine genauere Implementierung finden Sie hier, diese Implementierung ist auch komplizierter):

Code kopieren Der Code lautet wie folgt:

function newOperator(Constr, arrayWithArgs) {
var thisValue = Object.create(Constr.prototype);
Constr.apply(thisValue, arrayWithArgs);
return thisValue;
}

1.3 dies

in der Methode

Die Verwendung davon in Methoden ähnelt eher traditionellen objektorientierten Sprachen: Der Empfänger, auf den hiermit verwiesen wird, ist das Objekt, das diese Methode enthält.

Code kopieren Der Code lautet wie folgt:

var obj = {
Methode: function () {
console.log(this === obj); // true
}
}
obj.method();

2. Dies im Umfang

Im Browser ist der Bereich der globale Bereich, und dieser bezieht sich auf das globale Objekt (genau wie Fenster):

Code kopieren Der Code lautet wie folgt:

<script><br> Konsole. log(this === window); // true<br></script>

In Node.js führen Sie Funktionen normalerweise in Modulen aus. Daher ist der Top-Level-Bereich ein ganz besonderer Modulbereich:

Code kopieren Der Code lautet wie folgt:

// `global` (nicht `window `) bezieht sich auf das globale Objekt:
console.log(Math === global.Math); // true

// `this` bezieht sich nicht auf das globale Objekt:
console .log( this !== global); // true
// `this` bezieht sich auf die Exporte eines Moduls:
console.log(this === module.exports); // true

3. dies in eval()

eval() kann direkt (durch Aufruf des Funktionsnamens „eval“) oder indirekt (auf andere Weise aufgerufen, z. B. call()) aufgerufen werden. Weitere Einzelheiten finden Sie hier.

Code kopieren Der Code lautet wie folgt:

// Echte Funktionen
Funktion sloppyFunc () {
console.log(eval('this') === window); // true
}
sloppyFunc();

function strictFunc() {
'use strict ';
console.log(eval('this') === undefiniert); // true
}
strictFunc();

// Konstruktoren
var savedThis;
function Constr() {
savedThis = eval('this');
}
var inst = new Constr();
console.log(savedThis === inst ); / / true

// Methoden
var obj = {
method: function () {
console.log(eval('this') === obj); / true
}
}
obj.method();

4. Fallen im Zusammenhang damit

Sie sollten sich vor den drei damit verbundenen Fallen in Acht nehmen, die im Folgenden vorgestellt werden. Es ist zu beachten, dass in den folgenden Beispielen die Verwendung des strengen Modus die Sicherheit des Codes verbessern kann. Da dieser Wert in realen Funktionen undefiniert ist, erhalten Sie eine Warnung, wenn etwas schief geht.

 4.1 Ich habe vergessen, „Neu“ zu verwenden

Wenn Sie zum Aufrufen des Konstruktors nicht new verwenden, verwenden Sie tatsächlich eine echte Funktion. Daher wird dies nicht der von Ihnen erwartete Wert sein. Im Sloppy-Modus zeigt dies auf das Fenster und Sie erstellen globale Variablen:

Code kopieren Der Code lautet wie folgt:

Funktion Point(x, y) {
this .x = x;
this.y = y;
}
var p = Point(7, 5); // wir haben new vergessen!
console.log(p == = undefiniert) ; // wahr

// Globale Variablen wurden erstellt:
console.log(x); // 7
console.log(y); // 5

Wenn Sie jedoch den strikten Modus verwenden, erhalten Sie weiterhin eine Warnung (dies===undefiniert):

Code kopieren Der Code lautet wie folgt:

Funktion Point(x, y) {
' use strict';
this.x = x;
this.y = y;
}
var p = Point(7, 5);
// TypeError: Cannot setze Eigenschaft 'x' von undefiniert

4.2 Unsachgemäßer Einsatz von Methoden

Wenn Sie den Wert einer Methode direkt abrufen (nicht aufrufen), verwenden Sie die Methode als Funktion. Sie werden dies wahrscheinlich tun, wenn Sie eine Methode als Parameter an eine Funktion oder eine aufrufende Methode übergeben möchten. Dies ist bei setTimeout() und registrierten Event-Handlern der Fall. Ich werde die Methode callIt() verwenden, um dieses Szenario zu simulieren:

Code kopieren Der Code lautet wie folgt:

/**Ähnlich wie setTimeout() und setImmediate()*/
function callIt(func) {
func();
}

Wenn Sie eine Methode im Sloppy-Modus als Funktion aufrufen, zeigt *this* auf das globale Objekt, sodass alle nachfolgenden Erstellungen globale Variablen sind.

Code kopieren Der Code lautet wie folgt:

var counter = {
count: 0,
// Sloppy-mode method
inc: function () {
this.count ;
}
}
callIt(counter.inc);

// Hat nicht funktioniert:
console.log(counter.count); // 0

// Stattdessen ein globaler Variable wurde erstellt
// (NaN ist Ergebnis der Anwendung auf undefiniert):
console.log(count); // NaN

Wenn Sie dies im strengen Modus tun, ist dies undefiniert und Sie erhalten immer noch nicht das gewünschte Ergebnis, aber zumindest erhalten Sie eine Warnung:

Code kopieren Der Code lautet wie folgt:

var counter = {
count: 0,
// Methode im strikten Modus
inc: function () {
'use strict';
this.count ;
}
}
callIt(counter. inc);

// TypeError: Eigenschaft „count“ von undefiniert kann nicht gelesen werden
console.log(counter.count);

Um die erwarteten Ergebnisse zu erhalten, können Sie bind() verwenden:

Code kopieren Der Code lautet wie folgt:

var counter = {
count: 0,
inc: function () {
this.count ;
}
}
callIt(counter.inc.bind(counter));
// Es hat funktioniert!
console .log(counter.count); // 1

bind() erstellt eine weitere Funktion, die den Wert dieser immer auf counter setzt.

 4.3 Dies ausblenden

Wenn Sie eine Funktion in einer Methode verwenden, vergessen Sie oft, dass die Funktion ihr eigenes this hat. Dies unterscheidet sich von den Methoden, daher können Sie die beiden nicht miteinander kombinieren. Einzelheiten finden Sie im folgenden Code:

Code kopieren Der Code lautet wie folgt:

var obj = {
name: 'Jane' ,
friends: [ 'Tarzan', 'Cheeta' ],
Schleife: function () {
'use strict';
this.friends.forEach(
function ( Freund) {
            console.log(this.name ' kennt ' Freund);
                            ; Eigenschaft 'Name' von undefiniert kann nicht gelesen werden



Im obigen Beispiel kann this.name in der Funktion nicht verwendet werden, da der Wert von this in der Funktion undefiniert ist, was sich von diesem in der Methode loop() unterscheidet. Nachfolgend finden Sie drei Ideen zur Lösung dieses Problems:

1. that=this, weisen Sie dies einer Variablen zu, damit dies explizit angezeigt wird (außerdem ist self auch ein sehr häufiger Variablenname, der zum Speichern dieses verwendet wird), und verwenden Sie dann diese Variable:

Code kopieren

Der Code lautet wie folgt:Schleife: Funktion () { 'use strict '; var that = this;
this.friends.forEach(function (friend) {
console.log(that.name ' know ' friend);
});
}



2. bind(). Verwenden Sie bind(), um eine Funktion zu erstellen, deren This immer den Wert enthält, den Sie übergeben möchten (im Beispiel unten das This der Methode):

Code kopieren

Der Code lautet wie folgt:Schleife: Funktion () { 'use strict '; this.friends.forEach(function (friend) {
console.log(this.name ' know ' friend);
}.bind(this));
}

3. Verwenden Sie den zweiten Parameter von forEach. Der zweite Parameter von forEach wird an die Callback-Funktion übergeben und als dieser der Callback-Funktion verwendet.

Code kopieren Der Code lautet wie folgt:

Schleife: Funktion () {
'use strict ';
this.friends.forEach(function (friend) {
console.log(this.name ' know ' friend);
}, this);
}

5. Best Practices

Theoretisch denke ich, dass echte Funktionen keine eigene Funktion haben, und die obige Lösung basiert auch auf dieser Idee. ECMAScript 6 verwendet Pfeilfunktionen, um diesen Effekt zu erzielen. Pfeilfunktionen sind Funktionen, die kein eigenes This haben. In einer solchen Funktion können Sie dies beiläufig verwenden und müssen sich keine Gedanken darüber machen, ob es implizit vorhanden ist.

Code kopieren Der Code lautet wie folgt:

Schleife: Funktion () {
'use strict ';
// Der Parameter von forEach() ist eine Pfeilfunktion
this.friends.forEach(friend => {
// `this` ist `this` der Schleife
console.log (this.name ' kennt ' Freund);
});
}

Mir gefällt nicht, dass einige APIs dies als zusätzlichen Parameter der eigentlichen Funktion behandeln:

Code kopieren Der Code lautet wie folgt:

beforeEach(function () {
this.addMatchers ({
toBeInRange: function (start, end) {
...
} }
});

Schreiben Sie einen impliziten Parameter als explizit und übergeben Sie ihn. Der Code ist dann leichter zu verstehen und entspricht den Anforderungen der Pfeilfunktion:

Code kopieren Der Code lautet wie folgt:
beforeEach(api => {
api. addMatchers({
             toBeInRange(start, end) {                                                                    
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