3

The specification states:

It is a SyntaxError to use within strict mode code the identifiers eval or arguments as the Identifier of a FunctionDeclaration or FunctionExpression or as a formal parameter name (13.1). Attempting to dynamically define such a strict mode function using the Function constructor (15.3.2) will throw a SyntaxError exception.

Source: http://es5.github.com/C.html#C (last bullet)

Therefore, this throws a syntax error (in Firefox, Chrome, and Opera):

(function () {
    'use strict';

    var f = function ( eval ) {};
})();

Live demo: http://jsfiddle.net/v8Ff4/

However, this doesn't throw a syntax error:

(function () {
    'use strict';

    var f = new Function( 'eval', '' );
})();

Live demo: http://jsfiddle.net/v8Ff4/1/

It is my understanding that this second code-block should throw a syntax error. Should it? And if yes, why doesn't it?

Šime Vidas
  • 182,163
  • 62
  • 281
  • 385
  • Wait a minute, it could be that since the `new Function(...)` function executes in global code (its scope is the global scope), that the "use strict" rule doesn't apply to it. Is it that? – Šime Vidas Dec 10 '11 at 18:51
  • I don't know. Seems odd to me since "strict mode" is lexically scoped, if you add `'use strict'` at the global level, creating the function like that should inherit strict mode. Since the `eval` formal parameter is within the new environment of the function *(it isn't global)*, it seems that you should get the error. – RightSaidFred Dec 10 '11 at 21:30
  • With this: `var f = new Function( 'eval', '"use strict";' );` you get the error. But not with this: `"use strict"; var f = new Function( 'eval', ';' );` Doesn't seem right. – RightSaidFred Dec 10 '11 at 21:31
  • This run globally: `eval( 'var f = function( eval ) { ; }' );` also gives you the error. – RightSaidFred Dec 10 '11 at 21:40
  • @RightSaidFred I've figured it out. This behavior is proper and it conforms to the standard. I'll post a detailed answer later... (I can notify you if you want to) – Šime Vidas Dec 10 '11 at 21:40
  • @RightSaidFred I've posted my answer. – Šime Vidas Dec 11 '11 at 22:51
  • @gsnedders It turned out, that wasn't the reason... – Šime Vidas Dec 11 '11 at 22:52

1 Answers1

2

So, I'm going to answer my own question here (since I've figured it out).

My initial premise was that both code blocks are equivalent. So that this

var f = function ( eval ) {};

is equivalent to

var f = new Function( 'eval', '' );

This is however not true. There are differences. The creation of a function object from a function declaration / expression notation is defined in Chapter 13.2 Creating Function Objects. On the other hand, the creation of a function object from a new Function constructor invocation is defined in Chapter 15.3.2.1 new Function (p1, p2, … , pn, body). So there are different algorithms at work here.

The specific part which is relevant to this question is the part which defines the strictness of the created function object.

Function expressions

The strictness of a function object created via a function expression is defined in the semantics of the production FunctionExpression at the beginning of chapter 13:

Pass in true as the Strict flag if the FunctionExpression is contained in strict code or if its FunctionBody is strict code.

So the function object will be strict if either one of these conditions is met:

  • the function expression is contained in strict code
  • the function body of the function expression is strict code

so for instance, the function f is strict in both examples below.

Example 1:

(function () {    
    var f = function () {
        'use strict';
        return 'I am strict!';
    }    
})();

Example 2:

(function () {
    'use strict';    
    var f = function () {
        return 'I am strict!';
    }    
})();

Function constructor invocation

The strictness of a function object created via a Function constructor invocation is defined in step 9 of the algorithm from Chapter 15.3.2.1 (already linked above):

If body is strict mode code (see 10.1.1) then let strict be true, else let strict be false.

So, whether or not the new Function invocation is contained in strict code is irrelevant. To create a strict function via this pattern, one has to explicitly define the strictness in the function body (which is the last argument supplied to the constructor.

new Function ( 'a, b', 'return a + b;' ); // not strict
new Function ( 'a, b', '"use strict"; return a + b;' ); // strict
Šime Vidas
  • 182,163
  • 62
  • 281
  • 385
  • Yep, you got it. 10.1.1 *"Function code that is supplied as the last argument to the built-in Function constructor is strict function code if the last argument... begins with a Directive Prologue that contains a Use Strict Directive."* It says nothing of it being *contained in* strict mode code. – RightSaidFred Dec 11 '11 at 23:44