disabling "use strict"; everywhere
Le 30 janv. 2013 à 06:12, Andrea Giammarchi <andrea.giammarchi at gmail.com> a écrit :
I have a blog post about it called
Resurrecting The With Statement
and before I post the link, there the long story short:
putting
with(this){
before any build process/inlined library and}
at the end of all concatenated files nobody is strict anymore ^_^
For what I understand of ES5, putting some random stuff (other than string literals or comments) before a "use strict" directive at the beginning of a file will disable it. This is a known fact, orthogonal to the "Function + with" dirty/creative hack of your blog post.
To enable strict mode, the "use strict" expression must come as the first non-statement of a script or function body. That means function x(){} "use strict";
Will enable strict mode, but
(function x(){});
"use strict";
won't. To make your example strict, you'd have to do
with (ob) {
(function(){
"use strict'";
/* concatenated stuff */
})();
}
Correction, the use strict directive needs to appear as the first statement (ExpressionStatement) that's not an EmptyStatement and not a FunctionDeclaration. Anything else will cause the directive to be ignored.
let me rephrase ...
putting with(this){
before any build process/inlined library and }
at
the end of all concatenated files nothing is strict anymore ^_^
function isStrict() {"use strict"; return this; }
isStrict(); // undefined
now, wraping the whole thing inside a with statement
with(this){ function isStrict() {"use strict"; return this; } alert(isStrict()); // global object }
forget the Function hack, there is no library able to ensure itself to be executed in strict mode. Using the width statement around any code makes it not strict.
Thoughts ?
actually, interesting enough, function expressions do not suffer this problem ... this is getting weirder and weirder ...
with(this){ alert(function isStrict() {"use strict"; return this; }()); // undefined }
br
The behavior of a FunctionDeclaration that's not directly in the body of a Program or function is not defined in ES5 and this is likely fallout from that.
so the directive is about expressions only ? interesting
The behavior you showed is very odd indeed, I suspect it's actually a bug. But I would guess the reason the bug exists is because of it being a FunctionDeclaration.
On 30 January 2013 18:00, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:
let me rephrase ...
putting
with(this){
before any build process/inlined library and}
at the end of all concatenated files nothing is strict anymore ^_^function isStrict() {"use strict"; return this; }
isStrict(); // undefined
now, wraping the whole thing inside a with statement
with(this){ function isStrict() {"use strict"; return this; } alert(isStrict()); // global object }
forget the Function hack, there is no library able to ensure itself to be executed in strict mode. Using the width statement around any code makes it not strict.
That is, er, balls, of course. All that happens here is that inside the 'with', a call to a toplevel function like 'isStrict()' becomes 'this.isStrict()', and so receives the global object. That does not otherwise change strictness, however. Try:
with(this) { function isStrict() { "use strict"; var x; delete x; } alert(isStrict()); }
for example. Moreover, calls to functions not resolving to global definitions are completely unaffected, so are calls using 'call' or 'apply':
with(this) { function isStrict() { "use strict"; return this; }; function call(f) { f() }; alert(call(isStrict)); // undefined alert(isStrict.call()); // undefined }
Both calls would return window in sloppy mode.
On 30 January 2013 17:19, Brandon Benvie <brandon at brandonbenvie.com> wrote:
Correction, the use strict directive needs to appear as the first statement (ExpressionStatement) that's not an EmptyStatement and not a FunctionDeclaration. Anything else will cause the directive to be ignored.
Any statement/declaration before the use directive renders it inoperational, empty, function, or otherwise. Actually, any token before the magic string does.
thanks, that makes sense. I have tried this too:
with({}){ function isStrict() {"use strict"; return this; } alert(isStrict()); // global object }
still global though, but I believe that a side effect of the with statement.
Weird that expressions behave outside that implicit context.
Libraries wrapped in inline expressions seem to be safe then, hooooray I guess :-)
last examples, for archive reasons:
function isStrict() {"use strict"; return this; }
with(false){ alert(isStrict()); // global object alert((0, isStrict)()); // undefined }
mystery solved, still something to be aware for library authors. I'll explain in a tiny counter post later on.
br
Le 30 janv. 2013 à 18:00, Andrea Giammarchi <andrea.giammarchi at gmail.com> a écrit :
let me rephrase ...
putting
with(this){
before any build process/inlined library and}
at the end of all concatenated files nothing is strict anymore ^_^function isStrict() {"use strict"; return this; }
isStrict(); // undefined
now, wraping the whole thing inside a with statement
with(this){ function isStrict() {"use strict"; return this; } alert(isStrict()); // global object }
Presumably some weirdness between "with" statement mixed with function declaration. You should test specifically the strictness, not the this-binding:
with(this){ function test() { "use strict" return (function() { return this === void 0 })() } alert(test()); // true }
The test function is manifestly in strict mode regardless of its this-binding.
...
!! But wait, I think I understand what's happening:
var obj = { returnThis: function() { "use strict"; return this } , toString: function() { return 'I am "obj"' } } var otherReturnThis = function() { "use strict"; return this }
with(obj){ alert(returnThis()); // 'I am "obj"' alert(otherReturnThis()); // undefined }
Here, "returnThis()" is strictly equivalent to "obj.returnThis()", including the this-binding, while "otherReturnThis()" use "undefined" as target object
In your example, when you say "isStrict()", it is interpreted as "this.isStrict()", since "isStrict" is a property of "this" and "this" is the argument of the "with" statement. (You're still with me?) Nothing to do with strict mode
Ok, you convinced me that the semantic of the "with" statement is really weird, but not that you can disable strict mode.
I have a blog post about it called
Resurrecting The With Statement
and before I post the link, there the long story short:
putting
with(this){
before any build process/inlined library and}
at the end of all concatenated files nobody is strict anymore ^_^webreflection.blogspot.com/2013/01/resurrecting-with-statement.html
I actually like this possibility, but I'd like to know what you think about it
br