最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why is this illegal in strict mode? - Stack Overflow

programmeradmin2浏览0评论

Yeah, yeah, I know, strict mode ain't around yet, but really, I'm planning for the future...

So, why is this:

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

... not allowed in ES5 Strict mode?

Or am I misinterpreting? JSLint:

Problem at line 516 character 18: Strict violation.

Could it be a little more verbose, I wonder...?

EDIT:

To avoid confusion, here's more of the original code:

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

Yeah, yeah, I know, strict mode ain't around yet, but really, I'm planning for the future...

So, why is this:

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

... not allowed in ES5 Strict mode?

Or am I misinterpreting? JSLint:

Problem at line 516 character 18: Strict violation.

Could it be a little more verbose, I wonder...?

EDIT:

To avoid confusion, here's more of the original code:

function displayLegend() {
    $('#'+ $(this).attr('id').replace('control-', 'legend-')).fadeIn();
}
Share Improve this question edited Jan 19, 2013 at 10:31 hippietrail 17k21 gold badges109 silver badges179 bronze badges asked Dec 1, 2010 at 10:48 Félix SaparelliFélix Saparelli 8,7496 gold badges55 silver badges68 bronze badges 6
  • Just curious, what does $('#'+ this.id.replace('control-', 'legend-')).fadeIn(); do? – Nick Craver Commented Dec 1, 2010 at 10:50
  • Wow, a 100k person... never seen one of these before. It's a bit plicated out of context... This is for a userscript, Manga ChapterReader, you can find it out there. Basically, I have matching HTML elements which have the same id with different prefixes. When you hover a control, the description (legend) fades in. I found it's pretty nifty to be able to add a control using predefined patterns. – Félix Saparelli Commented Dec 1, 2010 at 11:04
  • I don't know strict mode well enough to give a coherent answer, but it appears to have something to do with using this outside of what looks like a method. If I change the code to 'use strict';var foo = {};foo.bar = function () {$('#'+ $(this).attr('id').replace('control-', 'legend-')).fadeIn();} then it passes the strict test on JSLint. – Quentin Commented Dec 1, 2010 at 11:16
  • It could be related to developer.mozilla/en/JavaScript/… (and it could also be a bug in JSLint, it is possible that it would only fail if the function was called in the context of window and that as you are using it as an event handler — that will never happen. All this is speculation on my part though. – Quentin Commented Dec 1, 2010 at 11:20
  • @David: Doesn't it have something to do with the part of the spec I quoted in my answer, whatever it really means? – Marcel Korpel Commented Dec 1, 2010 at 11:29
 |  Show 1 more ment

2 Answers 2

Reset to default 6

Some trial-and-error of this code in JSLint

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

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

shows me what's wrong: you're using this as a parameter. Changing both thises to thats doesn't trigger the error.

As the specification says:

If this is evaluated within strict mode code, then the this value is not coerced to an object. A this value of null or undefined is not converted to the global object and primitive values are not converted to wrapper objects. The this value passed via a function call (including calls made using Function.prototype.apply and Function.prototype.call) do not coerce the passed this value to an object (10.4.3, 11.1.1, 15.3.4.3, 15.3.4.4). [my emphasis]

As John Resig writes,

Finally, a long-standing (and very annoying) bug has been resolved: Cases where null or undefined is coerced into being the global object. Strict mode now prevents this from happening and throws an exception instead.

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

As you showed, using your line of code inside a function declaration throws an error in JSLint, whereas using it inside a function expression doesn't. It looks like JSLint erroneously parses the function declaration, sees this, that's still undefined at that moment, and throws an exception.

At this point, I think I have to quote Juriy Zaytsev (‘kangax’):

Does it really matter?

It’s good to understand that strict mode is not a requirement, but is merely an option. It is there to provide stricter rules for those who need it, and are willing to cope with (and enjoy) consequences.


Update: At last I found an explanation. If you read this thread, especially from message #1512 onwards, you'll read that

The point of ES5/strict is to prohibit leaking of the global object, something that ES3 does promiscuously. ES5/strict does some of its work dynamically, and some of its work statically. JSLint does all of its work statically, so it must be even more restrictive in order to best help you get your program right. [Douglas Crockford in #1553]

I have to admit that he has a valid point here: if your goal is to avoid global namespace pollution, you shouldn't use function declarations, but function expressions inside a private namespace, anyway. But I agree with others in the mentioned thread that the error message should be more explicit (and probably throw a warning on encountering a function declaration).

Following what David Dorward said, I found something that passes JSLint's test. This is downright strange as to why it's doing that.

Before: (see question)

After:

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

EDIT:

I asked Douglas Crockford:

JSLint only allows this in strict mode in functions that are obviously intended to be called as methods. So write

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

This confirms what it says in the spec, except it's much clearer!

发布评论

评论列表(0)

  1. 暂无评论