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
指的是 window
和 window.joker
和 window.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
,并且必须将所有对象的方法包含在我们希望所有我们的Peep
s 共享的构造函数。
/*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
确实是个坏消息,因为您的代码会变成意大利面条。 “有些Person
s 有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 的“语句位置出现意外的表达式‘i’”是啥意思?