为什么JSHINT抱怨这是一个严格违规?

101

我认为这可能是 Strict Violation using this keyword and revealing module pattern 的重复。

我有这段代码:

function gotoPage(s){
    if(s<=this.d&&s>0){this.g=s; this.page((s-1)*this.p.size);}
}

function pageChange(event, sorter) {
    var dd = event.currentTarget;
    gotoPage.call(sorter, dd[dd.selectedIndex].value);
}

JSHINT(JSLINT)报错了。它在高亮行上显示“Strict violation.”

enter image description here

我使用Function.call()再引用实例,这样做有什么不妥吗?

这是否被认为是不好的样式?


它只显示“Strict violation”而没有任何详细的错误信息吗? - stivlo
我无法重现这个问题,我已经通过 JSHint 和 JSLint 运行了代码,它似乎没有对任何内容提出异议。 - Peter Olson
54
请注意,如果您不试图把它塞进一个荒谬的一行代码中,那么诊断问题会更容易 :P。 - Domenic
1
我在另一个问题中见过类似的内容(现在找不到了)。这与使用“this”有关。我不知道为什么JSLint会称其为“严格违规”,但我知道,如果您不定义函数的“this”值,则在严格模式下它将是“undefined”。显然,您正在定义“this”,所以这不应该是个问题。 - user113716
2
在配置json中使用 "-W040":true,你可以忽略这些可能的严格违规警告,但由于json没有注释,你不能告诉任何人它存在的原因。 - kojiro
或者你可以添加注释 /* jshint -W040 */,当你想要恢复该警告时,则加入 /* jshint +W040 */ - JSmith
4个回答

126

JSHint提示可能会出现严格模式违规,因为您在某些情况下使用了this,但据它所知,这不是一个方法。

在非严格模式下,调用gotoPage(5)会将this绑定到全局对象(在浏览器中是window)。在严格模式下,this将是undefined,您会遇到麻烦。

大概而言,您意图使用绑定的this上下文调用此函数,例如gotoPage.bind(myObj)(5)gotoPage.call(myObj, 5)。如果是这样,您可以忽略JSHint,因为您不会生成任何错误。但是,JSHint提示您的代码对于任何阅读它的人来说都不够清晰,因为在不明显是方法的东西内部使用this相当令人困惑。最好是直接将对象作为参数传递:

function gotoPage(sorter, s) {
    if (s <= sorter.d && s > 0) {
        sorter.g = s;

        sorter.page((s - 1) * sorter.p.size);
    }
}

function pageChange(event, sorter) {
    var dd = event.currentTarget;
    gotoPage(sorter, dd[dd.selectedIndex].value);
}

12
即使如此,我认为他们在描述中有些误导。即使this最终确实变成了undefined,那么实际问题并不仅是一个严格模式违规。他们最好发出警告说,在“严格模式”下,this可能会变成undefined,从而导致TypeError(或类似的错误)。 - user113716
12
确实,这就是为什么我总是使用 event.currentTarget 而不是 this 的原因。 - Domenic
4
我应该在.jshintrc中添加哪个配置指令来禁用此检查? - callum
8
@callum "validthis": true - Brett
19
如果只有几个情况需要这样做,并且你不想针对每个情况都进行更改,请使用/* jshint validthis: true */ - knownasilya
显示剩余5条评论

94

我有一个函数名称的警告,因为它不是以大写字母开头。

"use strict";

// ---> strict violation
function something() {
    this.test = "";
}


// ---> just fine (note the capital S in Something)
function Something() {
    this.test = "";
}

29
注意,jshint 可能会假设由于 Something 首字母大写的惯例,它是一个构造函数,因此应该使用 new 来调用。这样做会定义 this 为基于 Something.prototype 的一个新对象。很可能正是由于这种假设,它不会引发可能的严格模式违规警告。 - Andy
4
我在 AngularJS 的提供者中遇到了这个错误,因此需要使用大驼峰命名法的方法名称,但我使用了小驼峰命名法。已修复。 - Deminetix
我曾遇到类似的问题,当函数名称只有小写时,重命名为大写。 - GibboK
不要使用大写字母作为首字母,因为它也是一个构造函数,你会遇到另一个问题。相反,你可以使用:var fnAbc = function(){this.test = ""} - Hieu Tran AGI
大写字母对函数的内部工作没有任何影响。这只是程序员通常以这种方式传达含义的一种方式。换句话说:这不是技术问题,而是人类之间的沟通问题。 - amenthes

9
如果您将函数声明为变量而不是使用标准函数声明,则jshint不会将其标记为严格违规。因此,您可以执行以下操作 -
var gotoPage = function (s){
    if(s<=this.d&&s>0){this.g=s; this.page((s-1)*this.p.size);}
};


var pageChange = function (event, sorter) {
    var dd = event.currentTarget;
    gotoPage.call(sorter, dd[dd.selectedIndex].value);
};

0
如果你想要实现一个方法,你可能想要将其分配给原型而不是直接赋值:
ExampleClassName.protytpe.gotoPage = function gotoPage(s){
  // code using this
};

JSHint 不会在函数被赋值时发出警告。


还不够好。即使正确绑定了 myMethod,然后在下面定义了该方法,你仍然会收到错误提示。ClassName.prototype.myMethod = myMethod; - Jefftopia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接