web-dev-qa-db-fra.com

Violation stricte en utilisant ce mot-clé et le modèle de module révélateur

Ayant du mal à obtenir ce qui suit pour passer jslint/jshint

/*jshint strict: true */
var myModule = (function() {
    "use strict";

    var privVar = true,
        pubVar = false;

    function privFn() {
        return this.test; // -> Strict violation.
    }

    function pubFn() {
        this.test = 'public'; // -> Strict violation.
        privFn.call(this); // -> Strict violation.
    }

    return {
        pubVar: pubVar,
        pubFn: pubFn
    };

}());

myModule.pubFn();

Je comprends que cela est causé par l'utilisation de this dans une déclaration de fonction, mais j'ai lu quelque chose que Crockford a écrit et il a dit que la violation était destinée à empêcher la pollution des variables globales - mais la seule variable globale ici est celle que je '' m définissant explicitement ... myModule. Tout le reste est contenu dans la portée de la fonction immédiate, et je devrais pouvoir utiliser this pour faire référence au module.

Des idées sur la façon de faire passer ce modèle?

pdate: si j'utilise une expression de fonction au lieu d'une déclaration, cela semble fonctionner, c'est-à-dire

var pubFn = function () { ...

Cependant, je ne suis pas fan de ce format, je préfère que le nom de la fonction et les paramètres nommés soient plus proches et que la déclaration soit plus nette. Honnêtement, je ne vois pas pourquoi cela jette la violation - il n'y a aucune raison à cela dans ce schéma.

53
Matty F

JSHint a un option appelé validthis, qui:

[...] supprime les avertissements concernant d'éventuelles violations strictes lorsque le code s'exécute en mode strict et que vous utilisez this dans une fonction non constructeur [...], lorsque vous êtes certain que votre utilisation de this est valide en mode strict.

Utilisez-le dans la fonction dont se plaint JSHint, qui dans votre cas, ressemblerait à ceci:

function privFn() {
    /*jshint validthis: true */
    return this.test; // -> No Strict violation!
}

function pubFn() {
    /*jshint validthis: true */
    this.test = 'public'; // -> No Strict violation!
    privFn.call(this); // -> No Strict violation!
}

Cela peut sembler pénible de devoir spécifier cela dans chaque fonction où elle s'applique, mais si vous définissez l'option en haut de la fonction de votre module, vous pouvez masquer authentique violations strictes du mode par vous-même.

80
markrian

Le vrai problème ici est que si vous appelez privFn à partir du contexte module (à partir du [[~ # ~ ] iife [~ # ~]), this sera undefined en mode strict; window si ce n'est pas en mode strict. Hélas, la fonction échouerait si elle était appelée depuis l'IIFF.

En effet, les fonctions n'ont pas de propriétaire (objet) lorsqu'elles sont appelées à l'intérieur d'un IIFE, tandis que l'objet module renvoyé est le propriétaire des fonctions lorsqu'elles sont appelées en dehors du contexte IIFE, par exemple this === myModule Lors de l'appel de myModule.pubFn().

Le mode strict et JSHint/JSLint essaient de vous aider et vous ne devez jamais ignorer les erreurs/avertissements générés par eux, mais plutôt comprendre pourquoi ils vous avertissent.

Si vous êtes sûr à 100% que privFn, pubFn, etc. ne sera pas appelé ailleurs qu'en dehors de votre module, insérez simplement le commentaire /*jshint validthis: true */ Dans toutes les fonctions qui génèrent un avertissement. Alternativement, un commentaire dans l'IIFE empêchera JSHint de générer cette erreur sur n'importe quelle fonction à l'intérieur du module.


Une des nombreuses solutions possibles

Stockez la portée de this (dans self dans cet exemple) pour faire référence explicitement au module. Cela montrera et garantira votre intention.

/*jshint strict: true */
var myModule = (function() {
    "use strict";

    var privVar = true,
        pubVar = false,
        self = this;

    function privFn() {
        return self.test;
    }

    function pubFn() {
        self.test = 'public';
        //privFn.call(this); // Will have no effect, as `privFn` does not reference `this`
        privFn();
    }

    return {
        pubVar: pubVar,
        pubFn: pubFn
    };
}());

myModule.pubFn();
25

Malheureusement, il s'agit de l'erreur prévue pour cette configuration car jslint/jshint ne sait pas que la fonction déclarée dans le contexte global doit être utilisée ultérieurement comme méthode d'objet.

4
Matty F