JSLint 错误:意外的“这个”

Posted

技术标签:

【中文标题】JSLint 错误:意外的“这个”【英文标题】:JSLint Error: Unexpected 'this' 【发布时间】:2015-07-30 15:37:02 【问题描述】:

无法理解为什么 JSLint 对我在以下代码中使用 this 感到惊讶:

function testConstr (x) 
    'use strict';
    this.joker = "Whyyy sooo seriousss?";
    this.x = x;

对于这两个属性分配,JSLint 都说:意外的“this”。如何更正我的代码?

【问题讨论】:

您的this 不一定是坏事。 testConstr 是否用作构造函数?你是用call 还是apply 调用它? 如果你发现 JSLint 有太多的任意警告,你想看看 JSHint。 如果你把它大写成TestConstr会发生什么?警告是否仍然存在? @apsillers 是的,这也是我的第一步。还是被打了。新的 JSLint 希望鼓励您完全停止使用 this。我的意思是,诚然,对于新的(和旧的!)javascript 编码人员来说,范围确实是最令人困惑的话题之一,尽管我不知道这是否足以在默认情况下禁止使用它。他的rationale 是“在语言中使用this 会使谈论该语言变得更加困难”。我猜这并没有。可能值得尝试一段时间。 JSLint 现在提供了抑制此投诉的选项。请参阅my answer。 【参考方案1】:

在严格模式下,this 引用设置为 undefined

所以你的两个语句都会导致读取undefined对象的属性,这会导致异常。

如何更正我的代码?

删除这两行。

UPD:我上面所说的是 JSLint 如何处理您的代码,而不是我如何处理。

【讨论】:

或者:因为在非严格模式下,this 指的是 windowwindow.jokerwindow.x 也是可能的……除非 this 指的是事件目标或其他东西… 您假设testConstr 被称为testConstr()。鉴于它的名字,情况可能并非如此。 @Oriol 我不假设任何事情——它是 JSLint。我个人认为 JSLint 的破坏性大于实用性。 Re: 破坏性的:值得指出的是 this 选项是 JSLint 测试版的新选项,它只有几周的历史。我也有点失望。我的意思是,Crockford's comment,“[使用this] 就像与 Abbott 和 Costello 的结对编程”对于指出什么是 最佳实践并没有真正的帮助正是这种情况。我暂时给测试版提供了怀疑的好处,但请注意,所写的原始代码在 old.jslint.com 中进行 lints,只是将“混乱的空白”指令设置为 true。 所以上个月不那么邪恶了。【参考方案2】:

您的代码可能完全正确(也可能有问题,具体取决于您如何调用testConstr)。

我的建议是:让 JSLint 闭嘴

或者根本不使用 JSLint。

【讨论】:

我会使用 new 关键字来调用它(即将它用作对象构造函数)。抱歉,如果不清楚。所以换句话说,JSLint 不会自动期望我使用构造函数模式?对像我这样的人没有帮助。 . . @jdw 如果你使用new 应该没问题。 JSLint 不仅仅是偏执狂。 是的,这也是一种选择,但如果我不想通过使用此 JSLint 指令来抑制此警告怎么办。【参考方案3】:

So in other words, JSLint doesn't automatically expect me to use a constructor pattern?

你知道,我认为你是对的。你的问题困扰着我,我注册了Crockford's JSLint discussion group 和asked。他回答了,但忽略了我将在下面介绍的解决方案,我认为这意味着没关系,就像 JSLint 不会抱怨通过集合时一样。

(不过,我仍在等待更新的Good Parts。)

除此之外,我建议对通过 Beta JSLint 的 OO JavaScript 执行以下操作(无论如何,从今天开始)。

我将重写 MDN 页面“Introduction to Object Oriented Programming”中的一个示例,该页面本身大量使用this

this

这是上面链接部分中原始的、unlinted MDN 示例:

var Person = function (firstName) 
  this.firstName = firstName;
;

Person.prototype.sayHello = function() 
  console.log("Hello, I'm " + this.firstName);
;

var person1 = new Person("Alice");
var person2 = new Person("Bob");

// call the Person sayHello method.
person1.sayHello(); // logs "Hello, I'm Alice"
person2.sayHello(); // logs "Hello, I'm Bob"

这遵循我们熟悉和喜爱的惯例。

没有this

很容易弄清楚如何制作不遵循该模式的“构造函数”,但如果我没有遗漏任何内容,我们将不再使用prototype,并且必须将所有对象的方法包含在我们希望所有我们的Peeps 共享的构造函数。

/*jslint white:true, devel:true */
var Peep = function(firstName) 
    "use strict";
    var peep = ;
    peep.firstName = firstName;

    peep.innerSayHello = function() 
        console.log("Hello, I'm " + peep.firstName + ".");
    ;

    return peep;
;

var peep1 = new Peep("Bob");
var peep2 = new Peep("Doug");

peep1.innerSayHello();
peep2.innerSayHello();

所以有一个 lintable 替代方案。除了return peep; 和方法的内部定义之外,这确实使 JavaScript 的行为类似于您可能遇到的许多面向对象优先的语言。至少没有

无法访问prototype 并不可怕;在构造函数旁边不正确的地方更改prototype 确实是个坏消息,因为您的代码会变成意大利面条。 “有些Persons 有sayGoodbye(),有些没有,这取决于我们是否在构造它们时修改了原型。” 这太糟糕了。因此,这种替代约定有其优势。

当然,稍后您仍然可以将函数添加到 Peep 的单个实例化中,但我不确定您如何在不使用 this 的情况下访问 firstName,所以也许他希望我们停止修改构建后的对象。

person1.sayGoodbye = function (other)  
    console.log("Goodbye, " + other + "."); 
;

(我的意思是,我们仍然可以给 Peep 打猴子补丁以在进程中更改它,但那是可怕的、愚蠢的编程。通常。

继承(不带this

我认为继承很容易。

var PeepWithGoodbye = function (firstName) 
    "use strict";
    var peepWithGoodbye = new Peep(firstName);

    peepWithGoodbye.innerSayGoodbye = function (otherPeep) 
        if (undefined === otherPeep) 
            otherPeep =  firstName: "you" ;
        
        console.log("This is " + firstName 
            + " saying goodbye to " + otherPeep.firstName + ".");
    ;

    return peepWithGoodbye;
;

var pwg1 = new PeepWithGoodbye("Fred");
pwg1.innerSayHello();           // Hello, I'm Fred.
pwg1.innerSayGoodbye(peep1);    // This is Fred saying goodbye to Bob.
pwg1.innerSayGoodbye();         // This is Fred saying goodbye to you.

编辑: 另请参阅this answer,提问者后来发现 Crockford 建议的创建 OO javascript 的方法。我试图说服那个人删除 Q&A 并将 A 移到这里。如果他没有,我可能会在此处添加他的资料和社区 wiki。


编辑:请参阅 this from MDN 了解其工作原理:

(通常构造函数不返回值,但他们可以选择这样做 所以如果他们想覆盖正常的对象创建过程。)

【讨论】:

【参考方案4】:

JSLint 说:意外的“这个”。如何更正我的代码?

无需更正您的代码。

在help page for JSLint 的/*jslint*/ 指令部分中,已将“Tolerate this”选项添加到可用选项表中:

+---------------+------+---------------------------------+
| Tolerate this | this | true if this should be allowed. |
+---------------+------+---------------------------------+

因此,为了抑制对使用 this 的投诉,请将以下指令放入源文件中的第一条语句之前:

/*jslint
    this
*/

(请注意,其他 /*jslint*/ 选项可以在 this 之后通过在选项之间插入逗号。请参阅 JSLint 帮助页面。)

另请参阅the answer by @Oriol 以在 JSLint 的用户界面中启用 "Tolerate this" 选项。

【讨论】:

【参考方案5】:
'use strict';

var SudoConstructor = (function () 

    /* We need bind, < IE9 needs a (tiny) polyfill */

    function protoEsqDeclare(sudoThis) 
        return sudoThis;
    

    function protoEsqSet(sudoThis, newValA, newValB) 
        sudoThis.valA = newValA;
        sudoThis.valB = newValB;
    

    function instanceCreator(valA, valB) 
        var sudoThis = 
            valA: valA,
            valB: valB
        ;

        return 
            declare: protoEsqDeclare.bind(null, sudoThis),
            set: protoEsqSet.bind(null, sudoThis)
        ;

    

    return instanceCreator;

());

【讨论】:

【参考方案6】:

我知道一个老问题,但如果它对任何人有帮助,我正在观看 Douglas Crockford 的 talk,他说(大约 23 分钟)他把它拿出来,因为攻击者可以将方法作为函数运行并使用“this”关键字访问全局范围。

他说这也意味着不再使用 Object.create ——他帮助引入了该语言的一个功能!

【讨论】:

以上是关于JSLint 错误:意外的“这个”的主要内容,如果未能解决你的问题,请参考以下文章

jslint 中出现意外的“++”[重复]

JSLint:意外的“为”。意外的'var'

JSLint 的“语句位置出现意外的表达式‘i’”是啥意思?

无法在 React.js 中读取 json,出现意外的令牌错误

反应:解析错误:意外的令牌,预期的“(”

为啥这个解析错误在这里解析错误:语法错误,意外标识符“编辑”,期待“,”或“;”? [复制]