Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this illegal in strict mode?

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();
}
like image 476
Félix Saparelli Avatar asked Dec 01 '10 10:12

Félix Saparelli


1 Answers

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 becoming 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).

like image 150
Marcel Korpel Avatar answered Sep 24 '22 02:09

Marcel Korpel