Warum beschwert sich JSHINT darüber, dass dies ein strikter Verstoß ist?

98

Ich denke, dies könnte ein Duplikat von Strict Violation sein, das dieses Schlüsselwort verwendet und das Modulmuster enthüllt

Ich habe diesen Code:

function gotoPage(s){
    if(s<=this.d&&s>0){this.g=s; this.page((s-1)*this.p.size);}
}

function pageChange(event, sorter) {
    var dd = event.currentTarget;
    gotoPage.call(sorter, dd[dd.selectedIndex].value);
}

Und JSHINT (JSLINT) beschwert sich. Es heißt "Strikte Verletzung". für die hervorgehobene Zeile:

Geben Sie hier die Bildbeschreibung ein

Ist es Function.call()irgendwie unangemessen, die Instanz zu verwenden und dann darauf zu verweisen?

Wird dies als schlechter Stil angesehen?

Cheeso
quelle
Sagt es nur "Strikte Verletzung" ohne detaillierte Fehlermeldung?
Stivlo
Ich kann das Problem nicht reproduzieren, ich habe den Code über JSHint und JSLint ausgeführt und es scheint sich über nichts zu beschweren.
Peter Olson
54
Beachten Sie, dass dies viel einfacher zu diagnostizieren wäre, wenn Sie nicht versuchen würden, es in einen lächerlichen Einzeiler zu stopfen: P.
Domenic
1
Ich habe dies in einer anderen Frage gesehen (kann es momentan nicht finden). Es hat mit der Verwendung von zu tun this. Ich habe keine Ahnung, warum JSLint es als strikte Verletzung bezeichnen würde, aber ich weiß, dass thises sich undefinedim strengen Modus befindet , wenn Sie den Wert einer Funktion nicht definieren . Klar definieren Sie this, also sollte es kein Problem sein.
user113716
2
Sie können diese möglichen strengen Verstöße mit "-W040":truein der Konfiguration json ignorieren , aber da json keine Kommentare hat, können Sie niemandem sagen, warum es dort ist.
Kojiro

Antworten:

124

JSHint sagt "Mögliche strikte Verletzung", weil Sie verwenden this in etwas verwenden, das, soweit es das kann, keine Methode ist.

In nicht-striktem Modus Berufung gotoPage(5)binden würde thisauf das globale Objekt ( windowim Browser). Im strengen Modusthis wäre undefined, und Sie würden in Schwierigkeiten geraten.

Vermutlich wollen Sie diese Funktion mit einem gebundenen thisKontext aufrufen , z . B. gotoPage.bind(myObj)(5)oder gotoPage.call(myObj, 5). In diesem Fall können Sie JSHint ignorieren, da Sie keine Fehler generieren. Es sagt Ihnen jedoch, dass Ihr Code für jeden, der ihn liest, unklar ist, da die Verwendung thisin etwas, das offensichtlich keine Methode ist, ziemlich verwirrend ist. Es wäre besser, das Objekt einfach als Parameter zu übergeben:

function gotoPage(sorter, s) {
    if (s <= sorter.d && s > 0) {
        sorter.g = s;

        sorter.page((s - 1) * sorter.p.size);
    }
}

function pageChange(event, sorter) {
    var dd = event.currentTarget;
    gotoPage(sorter, dd[dd.selectedIndex].value);
}
Domenic
quelle
12
Trotzdem denke ich, dass sie in der Beschreibung etwas irreführend sind. Selbst wenn dies der thisFall ist undefined, ist das eigentliche Problem nicht nur ein strikte Verletzung des Modus . Sie sollten besser eine Warnung geben, die besagt, dass sie sich thismöglicherweise undefinedim "strengen Modus" befinden und zu einem TypeError(oder etwas) führen.
user113716
11
@ ripper234 in der Tat, deshalb benutze ich immer event.currentTargetstatt this.
Domenic
4
Zu welcher Konfigurationsanweisung kann ich hinzufügen .jshintrc, um diese Prüfung zu deaktivieren?
Callum
7
@ Callum "validthis": wahr
Brett
18
Verwenden /* jshint validthis: true */Sie diese Option, wenn Sie nur ein Paar haben und nicht für jeden Fall ändern möchten.
bekanntasilya
93

Ich habe diese Nachricht für eine Funktion erhalten, die nicht mit einem Großbuchstaben begann.

"use strict";

// ---> strict violation
function something() {
    this.test = "";
}


// ---> just fine (note the capital S in Something)
function Something() {
    this.test = "";
}
Amenthes
quelle
28
Ich würde bemerken, dass jshint aufgrund der Konvention wahrscheinlich davon ausgeht, dass Somethinges sich aufgrund des Kapitals S um einen Konstruktor handelt, und daher mit using bezeichnet werden sollte new. Dies definiert this, dass es sich um ein neues Objekt handelt, das auf "Something.prototype" basiert. Es ist höchstwahrscheinlich auf diese Annahme zurückzuführen, dass die mögliche Warnung vor strengen Verstößen nicht ausgelöst wird.
Andy Merts
4
Ich hatte diesen Fehler bei einem AngularJS-Anbieter, daher werden Methodennamen in Großbuchstaben erwartet und ich hatte Kleinbuchstaben. Fest.
Deminetix
Ich hatte das ähnliche Problem, wenn ich einen Funktionsnamen nur in Kleinbuchstaben hatte und ihn mit einem Großbuchstaben umbenannte.
GibboK
Verwenden Sie keinen Großbuchstaben, da es sich auch um einen Konstruktor handelt. Sie werden vor einem anderen Problem stehen. stattdessen können Sie verwenden: var fnAbc = function () {this.test = ""}
Hieu Tran AGI
Der Großbuchstabe ändert nichts am Innenleben der Funktion. Es ist nur etwas, was Programmierer normalerweise auf diese Weise tun, um Bedeutung zu vermitteln. Mit anderen Worten: Dies ist kein technologisches Problem, sondern ein Problem der Kommunikation zwischen Homans.
Amenthes
9

Wenn Sie die Funktion als Variable deklarieren, anstatt die Standardfunktionsdeklaration zu verwenden, kennzeichnet jshint dies nicht als strikte Verletzung. Sie können also Folgendes tun:

var gotoPage = function (s){
    if(s<=this.d&&s>0){this.g=s; this.page((s-1)*this.p.size);}
};


var pageChange = function (event, sorter) {
    var dd = event.currentTarget;
    gotoPage.call(sorter, dd[dd.selectedIndex].value);
};
Asulaiman
quelle
0

Wenn Sie versuchen, eine Methode zu implementieren, möchten Sie möglicherweise stattdessen den Prototyp zuweisen:

ExampleClassName.protytpe.gotoPage = function gotoPage(s){
  // code using this
};

JSHint warnt nicht, wenn die Funktion zugewiesen wird.

Flimm
quelle
Immer noch nicht gut genug. ClassName.prototype.myMethod = myMethod;, dann definiert die Methode unten. Sie erhalten immer noch eine Fehlermeldung, obwohl myMethod korrekt gebunden ist.
Jefftopia