Violación estricta usando esta palabra clave y revelando el patrón del módulo


Tener problemas para conseguir que lo siguiente pase 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();

Entiendo que está siendo causada por el uso de this en una declaración de función, pero leí algo que Crockford escribió y dijo que la violación está destinada a prevenir la contaminación variable global, pero la única variable global aquí es la que estoy definiendo explícitamente... myModule. Todo lo demás se mantiene en el ámbito de la función inmediata, y debería ser capaz de usar this para hacer referencia al módulo.

Cualquier idea de cómo ¿puede pasar este patrón?

Update: si utilizo una expresión de función en lugar de una declaración, esto parece funcionar, es decir

var pubFn = function () { ...

Aunque no soy fan de este formato, prefiero tener el nombre de la función y los parámetros con nombre más cerca y la declaración se ve/se siente más limpia. Honestamente no veo por qué esto está lanzando la violación-no hay razón para ello en este patrón.

Author: Matty F, 2011-06-10

3 answers

JSHint tiene una opción llamada validthis, que:

[...] suprime las advertencias sobre posibles violaciones estrictas cuando el código se ejecuta en modo estricto y se utiliza this en una función no constructora [...], cuando esté seguro de que su uso de this es válido en modo estricto.

Úselo en la función de la que JSHint se queja, que en su caso, se vería así:

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!
}

Puede parecer un dolor tener que especificar que en cada función donde se aplica, pero si configura la opción en la parte superior de su función de módulo, puede ocultar violaciones de modo estricto auténticas de usted mismo.

 79
Author: markrian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-11 18:05:39

El verdadero problema aquí es que si llamas privFn desde dentro del contexto del módulo (desde dentro del IIFE), this será undefined cuando esté en modo estricto; window si no está en modo estricto. Por desgracia, la función fallaría si se llama desde dentro de la VIDA.

Esto se debe a que las funciones no tienen propietario (objeto) cuando se llaman desde dentro de un IIFE, mientras que el objeto de módulo devuelto es el propietario de las funciones cuando se llaman desde fuera del contexto IIFE, por ejemplo this === myModule cuando se llama myModule.pubFn().

Tanto strict mode como JSHint/JSLint están tratando de ayudarlo y nunca debe ignorar los errores/advertencias generados por ellos, sino averiguar por qué lo están advirtiendo.

Si está 100 por ciento seguro de que privFn, pubFn, etc. no se llamará en ningún lugar, pero fuera de su módulo, simplemente coloque el comentario /*jshint validthis: true */ en cualquier función que genere una advertencia. Alternativamente, un comentario en el IIFE evitará JSHint de generar este error en cualquier función dentro del módulo.


Una de las muchas soluciones posibles

Almacene el alcance de this (en self en este ejemplo) para referirse explícitamente al módulo. Esto mostrará y asegurará su intención.

/*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();
 23
Author: Lars Gyrup Brink Nielsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-06 07:43:51

Desafortunadamente, este es el error previsto para esta configuración ya que jslint/jshint no sabe que la función declarada en contexto global se va a usar más tarde como un método objeto.

 4
Author: Matty F,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-24 01:05:40