2011-06-10 7 views
52

teniendo problemas para conseguir lo siguiente para pasar JSLint/jshintViolación estricto usando esta palabra clave y revelando el diseño del módulo

/*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 causado por el uso de this en una declaración de la función, pero leí algo 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 alcance de la función inmediata, y debería poder usar this para referirme al módulo.

Alguna idea de cómo puedo obtener este patrón para pasar?

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

var pubFn = function() { ... 

No soy un fan de este formato, sin embargo, prefieren tener el nombre de la función y nombraron a los params más cerca y la declaración parece/se siente más limpia. Honestamente, no veo por qué esto está arrojando la violación, no hay ninguna razón para ello en este patrón.

+1

Suena como uno de esos casos en los que simplemente puede ignorar las quejas de jslint. Como un aparte, ¿cómo funciona 'pubVar' cuando se accede como' myModule.pubVar'? Realmente no da código fuera del acceso al modelo a la variable en el módulo ¿verdad? Pensaría que si realmente quieres obtener/establecer el valor actual de la variable del módulo, necesitarías funciones getter y setter. – nnnnnn

+0

tienes razón, pensé que se veía un poco gracioso. Si intentabas 'myModule.pubVar = true', simplemente volverías a escribir la propiedad en el objeto. El 'pubVar' interno se mantendría como' falso' –

+2

Respecto a la actualización: prefiero 'var foo = function() {}' a 'función foo() {}' porque ayuda a evitar problemas de alojamiento. Además, me gusta que * does * haga que las funciones se parezcan más a otras variables, ya que en JS no hay diferencia entre una función o cualquier otro valor; son de primera clase. Preferencia personal, lo sé, pero pensé en arrojar algunos pensamientos. – JAAulde

Respuesta

79

JSHint tiene una llamada optionvalidthis, que:

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

Se usa en la función que JSHint se queja de 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! 
} 

Podría parecer como un dolor a 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 genuinas infracciones de modo estricto.

4

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 utilizará más tarde como método de objeto.

+1

Pero esas funciones no están declaradas en el código global. Están anidados dentro de su expresión de función (que usted usa para ajustar el código de su módulo). –

23

El verdadero problema aquí es que si usted llama privFn desde dentro del contexto módulo (desde dentro del IIFE), this habrá undefined cuando se encuentra en modo estricto; window si no está en modo estricto. Desgraciadamente, la función fallaría si se llama desde el IIFE.

Esto es porque las funciones no tienen propietario (objeto) cuando se llama desde dentro de una IIFE, mientras que el objeto de módulo devuelto es el propietario de las funciones cuando son llamados desde fuera del contexto IIFE, por ejemplo this === myModule al llamar al myModule.pubFn().

Tanto el modo estricto como JSHint/JSLint están tratando de ayudarlo y nunca debería simplemente 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 serán llamados a ningún lado pero fuera de su módulo, simplemente ponga el comentario /*jshint validthis: true */ en cualquier función que genere una advertencia. Alternativamente, un comentario en el IIFE evitará que JSHint genere este error en cualquier función dentro del módulo.


Uno de los muchos solución posible

tienda del alcance de this (en self en este ejemplo) para referirse explícitamente al módulo. Esto mostrará y asegurará tu intento.

/*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(); 
+1

Totalmente de acuerdo con su respuesta, solo quiero agregar una cosa más. Si usa 'this' dentro de una función, comience con mayúscula y no le dará ninguna advertencia. Porque la función de inicio con mayúscula significa que vas a usarlo como un constructor con una nueva palabra clave. Usted permitió usar esto en el constructor incluso en el modo estricto :) – Tarun

+0

Tengo el mismo problema para una devolución de llamada del mapa de la matriz (devolución de llamada, contexto) que se utiliza en diferentes lugares. "esto" tiene en este caso un uso perfectamente válido tal como lo proporciona el segundo argumento de map(). Por cierto, también es cierto para otros métodos de matriz, como algunos(), every(), reduce(), reduceRight(). Creo que JSHint & JSLint podría comprobar que dicha función siempre se usa como una devolución de llamada de método de matriz con un contexto proporcionado –

Cuestiones relacionadas