Let's start with the example of a gray egg pain. demo1:
Function Test () {var x = 1; with ({X: 2}) {eval ('function Foo () {console. log (x);} '); EVAL ('var bar = function () {console. log (x);} ');} Foo (); Bar ();} test (); |
Most engines implemented by es5 (except opera12-) results. both are printed. I must emphasize it first. this result is incorrect according to the standard. it should be 1, 2 according to the standard. opera12-two 1 will be printed. we will not discuss this. the error is even more outrageous. start question: why do we say two or two are wrong. this will start with the function declaration of es5 and the function expression. frankly speaking. I resisted writing this article. because we need to clarify the details here. there are too many things involved. if every involved concept is to be put in place. A waste of time for friends who are familiar with es5. I don't think that a friend who is not familiar with es5 can establish a correct understanding through a detailed introduction. so keep everything simple. here, we assume that you know what the concept of function declaration is, the concept of function expressions, and the difference in syntax between the two. and lexical environments, lexicalenvironment, variableenvironmet, and their relationships and environment records
, Declarative environment records, object environment records related concepts. in es5, the function definition section describes two definitions: 1. function Declaration 2. function expressions are not just syntax differences. there are also some detailed differences when creating function objects. we will discuss how to use the current variableenvironmet of the execution environment where the function is located as the scope parameter provided when creating the function object. the function expression uses lexicalenvironment as the scope parameter. this leads to the most direct problem in the above example. we know that in non-strict mode, es5 allows the use of (
Expression )
Statement Syntax. But we need to clarify a few things first. 1.
Statement In Syntax.
Functiondeclaration
.
Block The Syntax is also true. (obviously, all browsers do not implement this specification according to the standard. That is to say, all Javascript Engines I have seen are allowed in the with, catch, or even if
Statement 2. Our example does not conflict with the first one, because the function declaration in the previous example is placed in eval. The eval code is
Program . Function declaration is allowed. 3. with will create a new lexicalenvironment within the scope of its function. set lexicalenvironment associated with the execution environment to the newly created lexicalenvironment. (that is, with changes the lexicalenvironment of the current execution environment) 4. with does not change variableenvironmet. before changing lexicalenvironment, lexicalenvironment and variableenvironmet point to the same reference. (with forces them to play each other) 5. with will also create an object environment record for this lexicalenvironment. the purpose is naturally (
Expression ) In toobject (
Expression Is used as the top of the entire responsibility chain for the identifier search. 6. Code When executed. the eval CALL Environment lexicalenvironment and variableenvironmet will be used as the corresponding lexical environments of the execution environment of the internal code (note that I am the plural here. there are spaces between words. I hope you can understand the meaning here. I will not explain it in detail) now the problem is coming. you should note that according to our known conditions. foo is the function declaration. the next lexical environment searched for its identifier is obviously the original variableenvironmet. bar is the new lexicalenvironment created by. obviously, the result of the entire example should be 1, 2. unfortunately, we have not found a known JavaScript engine, and the Implementation here is in line with the standard .... but knowing this is not the focus of our discussion today. our focus is. why is the standard defined like this. the following is my personal guess. demo2:
Function Test (){ VaR x = 1;
With ({X: 2}) {function Foo (){ Console. Log (X ); } VaR bar = function (){ Console. Log (X ); }; }
Foo (); Bar ();} Test (); |
If my interpretation of the standard is correct. I can conclude that the rule makers here are in chaos. he seems to be considering a situation similar to demo2. the idea is as follows: Foo's function declaration, the defined function object should not be affected by. but he seems to have forgotten two things. 1. function declaration is performed when the Controller enters the execution environment and initializes the variable. the with statement is executed during the interpretation execution period. obviously, the function definition of foo is earlier than. when with is executed, it modifies the lexicalenvironment associated with the current execution environment. all function declarations have long been processed. foo. [[Scope] has long referenced the original lexicalenvironment. it should not be affected by. so this design is totally redundant .. 2. the designer forgot
Statement And
Blok There is no syntax in the two statements.
Functiondeclaration
. What else is it about? So from the standard perspective. maybe we should not split lexical environments into lexicalenvironment and variableenvironmet. we need to deal with the responsible chain nodes inserted before with and catch. you only need to describe the concept. but it may be for accurate description, right? After all, he wants to describe the unique feature of with. In short, this ass is not wiped clean in es5. PS: although all known engines do not comply with the second article, we are discussing standards rather than implementation differences. PS: The Catch clause has the ability to create and tamper with the current execution environment lexicalenvironment. However, it corresponds to a block. The Catch clause does not use the object environment record. PS: earlier versions of spidermoneky include various branches with monkeys in the middle.
Block
Functiondeclaration.This is a special non-standard syntax called statement block function declaration. It causes the results of demo2 to be different. It is not covered in this article. In simple terms:
Typeof FN; // undefined {function FN (){}} |
Last. it seems that the function declaration in draft es6 no longer uses variableenvironmet as its [[Scope. I don't know if someone in the Standards Committee is aware of this problem. and made a correction. I have no energy to continue to ask. my attitude towards es6 is still on the sidelines. when is the release status. follow up again .. okay. that's it. thanks to ash for writing this painful example. thanks to bosn, Kenny, and ABCD for taking the time to discuss it. last. truth. compared with es5, the scope chain concept is removed and replaced by the internal and external layer lexical environment. I prefer ES3 description. because the description is directly a description of the data structure. it is more suitable for coders.
Finally, add something because some friends thought that function declaration could not appear in the block as statment, which is a limitation of es5's strict mode. the following describes the problem.
For issues where the function declaration should occur in blocks or other statement, the end of section 12.0 of es5 is described as follows:
Several widely used implementations of ecmascript are known to support the useFunctiondeclarationAsStatement. However there are significant and irreconcilable variations among the implementations in the semantics applied to suchFunctiondeclarations. Because of these irreconcilable differences, the use ofFunctiondeclarationAsStatementResults In code that is not reliably portable among implementations. It is recommended that ecmascript implementations either disallow this usageFunctiondeclarationOr issue a warning when such a usage is encountered. Future editions of ecmascript may define alternative portable means for declaring functions inStatementContext.
Basically, most elasticsearch engines are known to support the implementation of function declaration as a statement. in fact, this brings about a semantic conflict. es5 recommends that you disable this behavior or issue a warning .. in future elasticsearch versions. as a standard behavior...
That is to say, the es engine should not be used to make function Declaration appear in blocks or other places... So when some engines (such as V8 and monkey) Implement the es5 strict mode, this behavior is also explicitly prohibited (but it should be clear that this strict mode limitation, it does not come from the official restrictions of es5 strict mode. it is implemented by the engine implementer for some consideration )... But I personally think. this constraint is redundant. because we observe the production formula, we will find that. this type of support is not supposed to appear. that is to say, this method of using function declaration should not appear in non-strict mode variants... Why do we emphasize this in the sample mode? ... Oh, of course, out of respect for the fact, if the crude hexadecimal non-strict mode variant Code also throws an exception, the old code may have problems .... So this may be a remedy for some of the engine implementers.
We will wait and see how es6 defines this.Wait for es6 release.
A link to es5 strict mode is provided:Http://www.cnblogs.com/_franky/articles/2184461.html