【问题标题】:Why is this illegal in strict mode?为什么这在严格模式下是非法的?
【发布时间】:2011-05-18 10:25:09
【问题描述】:

是的,是的,我知道,严格模式还没有出现,但实际上,我正在为未来做计划......

那么,为什么会这样:

$('#'+ $(this).attr('id').replace('control-', 'legend-')).fadeIn();

...在 ES5 严格模式下不允许?

还是我误解了? JSLint:

第 516 行字符 18 处的问题:严格违反。

能不能再详细一点,我想知道...?

编辑:

为避免混淆,这里有更多的原始代码:

function displayLegend() {
    $('#'+ $(this).attr('id').replace('control-', 'legend-')).fadeIn();
}

【问题讨论】:

  • 只是好奇,$('#'+ this.id.replace('control-', 'legend-')).fadeIn(); 是做什么的?
  • 哇,一个 100k 的人……以前从未见过这样的人。脱离上下文有点复杂......这是一个用户脚本,Manga ChapterReader,你可以在那里找到它。基本上,我有匹配的 HTML 元素,它们具有相同的 id 和不同的前缀。当您将鼠标悬停在控件上时,描述(图例)会淡出。我发现能够使用预定义的模式添加控件非常漂亮。
  • 我不太了解严格模式,无法给出连贯的答案,但它似乎与在看起来像方法之外使用 this 有关。如果我将代码更改为'use strict';var foo = {};foo.bar = function () {$('#'+ $(this).attr('id').replace('control-', 'legend-')).fadeIn();},那么它将通过 JSLint 的严格测试。
  • 它可能与 developer.mozilla.org/en/JavaScript/… 相关(也可能是 JSLint 中的一个错误,只有在 window 的上下文中调用该函数时它可能才会失败,并且作为你将它用作事件处理程序——这永远不会发生。不过,这一切都是我的猜测。
  • @David:这是否与我在回答中引用的规范部分有关,无论它的真正含义是什么?

标签: javascript ecmascript-5 strict use-strict


【解决方案1】:

此代码在JSLint 中的一些试验和错误

"use strict";
var that="dd";
function $(x){return x;}

$('#'+ $(this).attr('id').replace('control-', 'legend-')).fadeIn();
$(this);

告诉我出了什么问题:您使用this 作为参数。将thises 都更改为thats 不会触发错误。

正如the specification 所说:

如果在严格模式代码中评估 this,则不会将 this 值强制为对象。 nullundefinedthis 值不会转换为全局对象,原始值也不会转换为包装器对象。 this 值通过函数调用(包括使用 Function.prototype.applyFunction.prototype.call 进行的调用)传递不要将传递的 this 值强制为对象10.4.311.1.115.3.4.315.3.4.4)。 [我的重点]

作为约翰·雷西格writes

最后,一个长期存在(而且非常 烦人的)错误已解决:案例 其中 null 或 undefined 被强制 成为全局对象。 严格模式现在可以防止这种情况 发生并抛出异常 而是。

(function(){ ... }).call( null ); // Exception

正如您所展示的,在函数声明中使用您的代码行会在 JSLint 中引发错误,而在函数表达式中使用它不会。看起来 JSLint 错误地解析了函数声明,看到了 this,此时仍然未定义,并引发异常。

此时,我想我不得不引用Juriy Zaytsev (‘kangax’)

真的很重要吗?

很高兴了解 严格模式不是必需的,而是 只是一种选择。它在那里 为那些谁提供更严格的规则 需要它,并愿意应付 (并享受)后果。


更新:我终于找到了解释。如果您阅读 this thread,尤其是从消息 #1512 开始,您就会阅读到该内容

ES5/strict 的重点是禁止 泄漏全局对象, ES3 混杂地做的事情。 ES5/strict 做了一些工作 动态的,以及它的一些工作 静态的。 JSLint 完成所有 静态工作,所以它必须是均匀的 更严格的,以提供最好的帮助 你得到你的程序正确。 [#1553 中的道格拉斯·克罗克福德]

我不得不承认他有一个正确的观点:如果你的目标是避免全局命名空间污染,那么无论如何你不应该使用函数声明,而应该使用私有命名空间内的函数表达式。但我同意上述线程中的其他人的观点,即错误消息应该更明确(并且可能在遇到函数声明时发出警告)。

【讨论】:

  • 什么???但我需要this,而不是that!该行在函数内部,由事件触发!我应该如何在没有this 的情况下点击元素?
  • 真的很重要吗?是的,对我来说确实如此。我就是这样:)
  • @passcod – 是的,我明白,我也一样。 ;)
  • 经过进一步询问,这是 JSLint 的正常行为……我猜这与指南或约定有关。很好的答案!
【解决方案2】:

按照 David Dorward 的说法,我找到了通过 JSLint 测试的东西。这对于它为什么这样做是非常奇怪的。

之前:(见问题)

之后:

var displayLegend = function () {
    $('#'+ $(this).attr('id').replace('control-', 'legend-')).fadeIn();
};

编辑:

我问道格拉斯·克罗克福德:

JSLint 只允许在严格模式下这样做 在显然是 旨在被称为方法。所以 写

object.property = function () {
    ... this ...
};

这证实了它在规范中所说的内容,但它更清晰!

【讨论】:

  • 啊,现在你使用的是函数表达式,而不是函数声明;前者在运行时解析,后者在脚本执行之前解析(在 JSLint 看来,this 可能仍未设置)。
  • @MarcelKorpel,感谢您的评论。它更加澄清了整个问题。
猜你喜欢
  • 2011-03-09
  • 2019-11-14
  • 1970-01-01
  • 1970-01-01
  • 2015-01-04
  • 2013-05-15
  • 2015-02-04
  • 2014-11-02
  • 1970-01-01
相关资源
最近更新 更多