javascript - diseño - Violación estricta usando esta palabra clave y revelando un patrón de módulo
patron de diseño iterator (3)
Tener problemas para obtener lo siguiente para pasar 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 causado por el uso de this
en una declaración de función, pero leí algo que escribió Crockford y dijo que la violación está destinada a prevenir la contaminación de variables globales, pero la única variable global aquí es la que estoy definiendo explícitamente ... mi 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 conseguir que este patrón pase?
Actualización: si uso una expresión de función en lugar de una declaración, esto parece funcionar, es decir,
var pubFn = function () { ...
Sin embargo, no soy un fan de este formato, prefiero tener el nombre de la función y los parámetros nombrados más cerca y la declaración se ve / se siente más limpia. Sinceramente, no veo por qué esto está provocando la violación: no hay razón para ello en este patrón.
Desafortunadamente, este es el error previsto para esta configuración, ya que jslint / jshint no sabe que la función declarada en el contexto global se usará más adelante como un método de objeto.
El problema real aquí es que si llama a privFn
desde el contexto del módulo (desde dentro del IIFE ), this
quedará undefined
cuando esté en modo estricto; window
si no está en modo estricto. Por desgracia, la función fallaría si fuera llamada desde el IIFE.
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 de IIFE, por ejemplo, this === myModule
al llamar a myModule.pubFn()
.
Tanto el modo estricto como JSHint / JSLint intentan ayudarte y nunca debes ignorar los errores / advertencias generados por ellos, sino descubrir por qué te advierten.
Si está 100 por ciento seguro de que no se privFn
, pubFn
, etc. en ningún lugar que no sea su módulo, simplemente /*jshint validthis: true */
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.
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();
JSHint tiene una option llamada validthis
, que:
[...] suprime las advertencias sobre posibles infracciones estrictas cuando el código se ejecuta en modo estricto y usted usa
this
en una función no constructora [...] cuando está seguro de que su uso dethis
es válido en modo estricto.
Úselo en la función de la que se queja JSHint, 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 una molestia tener que especificar eso en cada función donde se aplique, pero si configura la opción en la parte superior de su función de módulo, puede ocultar violaciones auténticas de modo estricto de usted mismo.