Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

The following code prints 1 in Safari 13.0.4 on OSX.

let set = new Set

for(let x = 0; x < 2; x++) {
    function f() {}
    set.add(f)
}

console.log(set.size) // 1 in Safari non-strict mode
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
429 views
Welcome To Ask or Share your Answers For Others

1 Answer

To my understanding, code that has a function declaration placed within a block, should follow the specification of 13.2.14 (I put in bold):

When a Block or CaseBlock is evaluated a new declarative Environment Record is created and bindings for each block scoped variable, constant, function, or class declared in the block are instantiated in the Environment Record.

One of the steps deals with function declarations explicitly, which depends on InstantiateFunctionObject, which in turn depends on OrdinaryFunctionCreate, OrdinaryObjectCreate, MakeBasicObject ... which creates a new object.

All this happens at the evaluation. Your quote from the specifications dictate that the evaluation happens for each iteration, and so the function object should be newly created in each iteration.

Differences in implementation

The specification has a section on implementation differences related to block-level function declarations. It says:

Prior to ECMAScript 2015, the ECMAScript specification did not define the occurrence of a FunctionDeclaration as an element of a Block statement's StatementList. However, support for that form of FunctionDeclaration was an allowable extension and most browser-hosted ECMAScript implementations permitted them. Unfortunately, the semantics of such declarations differ among those implementations. Because of these semantic differences, existing web ECMAScript code that uses Block level function declarations is only portable among browser implementation if the usage only depends upon the semantic intersection of all of the browser implementations for such declarations. The following are the use cases that fall within that intersection semantics:

  1. A function is declared and only referenced within a single block

    • One or more FunctionDeclarations whose BindingIdentifier is the name f occur within the function code of an enclosing function g and that declaration is nested within a Block.
    • No other declaration of f that is not a var declaration occurs within the function code of g
    • All occurrences of f as an IdentifierReference are within the StatementList of the Block containing the declaration of f.

Now the case in your question behaves according to specification (print 2) when the code is not a top-level script, but placed in a function body. In that case we are in situation 1 (in the above quote). But this point is not applicable when the script is global. And so, we see indeed deviating behaviour...


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...