严格违反使用此关键字和揭示模块模式

遇到麻烦得到以下通过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(); 

我知道这是由于在函数声明中使用this引起的,但是我读了Crockford写的东西,他说违规是为了防止全局variables污染 – 但是这里唯一的全局variables就是我明确定义的variables。 myModule 。 其他的一切都在直接的function范围内,我应该可以用this来指代这个模块。

任何想法如何我可以通过这种模式?

更新:如果我使用函数expression式而不是声明,这似乎工作,即

 var pubFn = function () { ... 

我不是这种格式的粉丝,更喜欢让函数名和命名参数更接近,声明看起来更清晰。 我真的不明白为什么这是抛出违规 – 这种模式没有理由。

validthis有一个叫validthis的选项 ,它:

当代码以严格模式运行时,可以禁止警告严重的违规行为,并且在非构造函数中使用this警告,当你肯定你在严格模式下使用this函数。

在JSHint所抱怨的function中使用它,在你的情况下,看起来像这样:

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

看起来很痛苦,不得不在每个函数中指定它,但是如果你在模块函数的顶部设置了这个选项,你可能会隐藏真正严格的模式违规。

这里真正的问题是,如果从模块上下文 (从IIFE内 )调用privFn ,在严格模式下this将是undefined ; window如果不是在严格的模式。 唉,如果从IIFE内部调用函数将失败。

这是因为函数在从IIFE内部调用时没有所有者 (对象),而返回的模块对象是从IIFE上下文外部调用的函数的所有者,例如调用myModule.pubFn()时的this === myModule myModule.pubFn()

严格模式和JSHint / JSLint都试图帮助你,你永远不应该忽略他们产生的错误/警告,而是找出他们为什么警告你。

如果您100%确定privFnpubFn等将不会在您的模块之外的任何地方被调用,只需在任何生成警告的函数中添加comment /*jshint validthis: true */ 。 或者,在IIFE中的一个注释将阻止JSHint在模块内部的任何函数上产生这个错误。


许多可能的解决scheme之一

存储这个范围(在这个例子中是self )来明确地指向模块。 这将显示并确保您的意图。

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

不幸的是,这是这个设置的预期错误,因为jslint / jshint不知道在全局上下文中声明的函数将被用作对象方法。