53

无法让以下内容通过 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 写的一些东西,他说违规是为了防止全局变量污染 - 但这里唯一的全局变量是我明确定义的那个...... myModule. 其他所有内容都保存在直接函数范围内,我应该可以this用来引用模块。

有什么想法可以让这种模式通过吗?

更新:如果我使用函数表达式而不是声明,这似乎有效,即

var pubFn = function () { ...

不过,我不喜欢这种格式,更喜欢让函数名和命名参数更接近,并且声明看起来/感觉更干净。老实说,我不明白为什么会引发违规行为——这种模式没有理由这样做。

4

3 回答 3

80

JSHint 有一个名为的选项validthis,它:

this[...] 当代码在严格模式下运行并且您在非构造函数中使用 [...] 时,当您确定您的使用this在严格模式下有效时,会抑制有关可能的严格违规的警告。

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

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

It might seem like a pain to have to specify that in each function where it applies, but if you set the option at the top of your module function, you may hide genuine strict mode violations from yourself.

于 2012-09-11T18:05:39.267 回答
25

The real problem here is that if you call privFn from within the module context (from within the IIFE), this will be undefined when in strict mode; window if not in strict mode. Alas, the function would fail if called from within the IIFE.

This is because the functions have no owner (object) when called from within an IIFE, whereas the returned module object is the owner of the functions when they are called from outside the IIFE context, e.g. this === myModule when calling myModule.pubFn().

Both strict mode and JSHint/JSLint are trying to help you and you should never just ignore the errors/warnings generated by them, but instead figure out why they are warning you.

If you are 100 percent sure that privFn, pubFn, etc. will not be called anywhere but outside your module, just put in the comment /*jshint validthis: true */ in any functions that generate a warning. Alternatively, one comment in the IIFE will prevent JSHint from generating this error on any function inside the module.


One of the many possible solution

Store the scope of this (in self in this example) to refer explicitly to the module. This will show and ensure your intent.

/*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();
于 2014-01-29T07:40:13.203 回答
4

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

于 2011-06-24T01:05:40.983 回答