Introduction:
Today, I saw a question from someone else:
Copy codeThe Code is as follows: function fn (x ){
X = 10;
Arguments [0] = 20;
Console. log (x, arguments [0])
}
Fn ()
I feel like I have no idea about this. I can try it myself, so I will analyze it specially.
I wanted to analyze it from the perspective of language, but I had to give it a rough try, so I looked at it and hoped that I could correct it.
This was written yesterday. I thought about it again when I was eating today. I thought about some problems, but I was not reliable. So I tried to modify it again.
Every js getting-started book will mention that a JS function contains an Arguments object, arguments, which is used to actually input function parameters when calling a function. fn. length stores the length of the parameter.
These are helpful for analysis, but I want to get more information about the parameters. I don't know who has a better solution. I have no solutions for the moment.
So we can only simulate it.
Ignore the simulation and start with the actual problem:Copy codeThe Code is as follows: <! DOCTYPE html PUBLIC "-// W3C // dtd xhtml 1.0 Transitional // EN"
Http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd>
<Html>
<Head>
<Meta http-equiv = "Content-Type" content = "text/html; charset = UTF-8"/>
<Title> </title>
</Head>
<Body>
<Script type = "text/javascript">
// The parameter contains an invisible declaration var x = undefined
Function fn (x ){
Console. log (x, arguments [0]);
Arguments [0] = 2;
Console. log (x, arguments [0]);
}
Console. log ('fn ():');
Fn ();
// Undefined, undefined
// Undefined, 2
Console. log ('fn (1 ):');
Fn (1 );
// 1, 1
// 2, 2
Focus on the execution of the next two functions (fn_1, fn_2). Here, we directly re-declare the x corresponding to the form parameter. Some people on the Internet say this is a declared local variable x.
Yes, but this local variable is not a common local variable. x is directly associated with the corresponding arguments. In the above example, x is associated with arguments [0];
So I guess the assignment process should be
1. When defining a function, the parameter is declared. If the function contains a local variable with the same name, the Declaration is ignored. At the same time, the function body also has an object arguments;
(Into a mess: I think arguments could not be defined as an array at the beginning. Is it because the number of actual parameters cannot be determined in the Function Definition [dynamic confirmation during runtime]? so either this array is infinitely large, or the array value is out of range ).
Back to the topic:
For fn_2, the initialization parameter is equivalent to var x. (in this case, x is not assigned a value. The default value is undefined. The value is assigned when the statement is executed)
Therefore, fn_2 should be like this:Copy codeThe Code is as follows: function fn_2 (var x ){
X = 3;
Console. log (x, arguments [0]);
Arguments [0] = 2;
Console. log (x, arguments [0]);
}
2. The function syntax check is passed. During execution, the arguments object inside the function gets a value at the beginning. After the value assignment is complete, the statements in the function are executed.
The following statement is my own, and I do not know whether it is correct or not (especially the related statement ):Copy codeThe Code is as follows: Once a parameter (corresponding variable) is assigned a value, the corresponding item of arguments will be searched. If the corresponding item of arguments is found, then the configuration form participates in the association of the corresponding arguments items. If the corresponding items (undefined) in arguments are not found, the form parameters and arguments remain independent. Here we are looking for a snapshot of arguments at the beginning of function running. In turn, the same is true for arguments values.
The delete part above is from yesterday, and the red part is written in half and found a problem was added. Today, why did you think of snapshots yesterday? This is not just a direct response when the function starts to run.
Judge Association? So I changed the statement:Copy codeThe Code is as follows: when the function starts to execute, set the association information that participates in arguments. If the corresponding items (undefined) can be found in the corresponding arguments, the two are associated. No matter how it is processed, the association information of the entire function body is not changed.
As a result, the description of the following examples should also be changed:
Back to the example, the syntax of the fn_2 function is checked and executed from Step 2:
Without ParametersCopy codeThe Code is as follows: fn_2 ();
Function fn_2 (x) {// The arguments value is assigned. The arguments parameter list is empty because no real parameter exists. The association information is determined at the same time. Obviously, the parameters are empty. The two are independent of each other and will not be associated in the future.
Var x = 3; // The value of x is 3. x and arguments [0] are mutually independent. arguments [0] is still undefined.
Console. log (x, arguments [0]); // print x = 3, arguments [0] is undefined
Arguments [0] = 2; // arguments is assigned, and x and arguments [0] are independent of each other. Therefore, x = 3 does not change.
Console. log (x, arguments [0]); // print x = 3, arguments [0] = 2
}
Conditions with ParametersCopy codeThe Code is as follows: fn_2 (1) with parameters );
Function fn_2 (x) {// arguments is assigned with a value. arguments [0] = 1. At the same time, the parameter x has a value, which is associated with each other and is always the same.
Var x = 3; // The value of x is 3. x is associated with arguments [0], so arguments [0] is assigned 3 ,.
Console. log (x, arguments [0]); // print x = 3, arguments [0] = 3
Arguments [0] = 2; // arguments [0] is assigned a value of 2. Since x and arguments [0] have been associated, x changes at the same time.
Console. log (x, arguments [0]); // print x = 2, arguments [0] = 2
}
In turn, it should be the same:
Without ParametersCopy codeThe Code is as follows: fn_2 ();
Function fn_2 (x) {// not associated
Arguments [0] = 2; // cannot find the corresponding x (undefined), independent of each other
Console. log (x, arguments [0]); // undefined, 2
X = 3; // independent of each other and snapshots. Although arguments is added dynamically, it still fails.
Console. log (x, arguments [0]); // 3, 2
}
With ParametersCopy codeThe Code is as follows: fn_2 (1 );
Function fn_2 (x ){
Arguments [0] = 2; // associate
Console. log (x, arguments [0]); // 2,2
X = 3; // join
Console. log (x, arguments [0]); // 3
}
Since we only have one form parameter, it may not be convincing enough. Now we have increased it to two.
There is only one real parameter:Copy codeThe Code is as follows: fn_2 (1 );
Function fn_2 (x, y) {// arguments is assigned successfully. arguments [0] = 1, arguments [1] = undefined. Therefore, only x is associated with arguments [0, y and arguments [1]
Console. log (x, y, arguments [0], arguments [1]); // 1, undefined, 1, undefined
Var x = 3; // The value of x is 3, and x is associated with arguments [0], so arguments [0] is assigned 3.
Console. log (x, y, arguments [0], arguments [1]); // 3, undefined, 3, undefined
Var y = 4; // The value of y is 3. y and arguments [1] are independent of each other. arguments [1] is still undefined.
Console. log (x, y, arguments [0], arguments [1]); // 3,4, 3, undefined
Arguments [0] = 2; // arguments [0] is assigned a value of 2. Since x and arguments [0] have been associated, x changes at the same time.
Console. log (x, y, arguments [0], arguments [1]); // 2, 2, undefined
Arguments [1] = 5; // arguments [1] is assigned a value of 5, and y and arguments [1] are independent of each other, so y remains 4
Console. log (x, y, arguments [0], arguments [1]); // x = 2, y = 4, arguments [0] = 2, arguments [1] = 5
}
There are two real parameters:Copy codeThe Code is as follows: fn_3 (1, 6 );
Function fn_3 (x, y) {// arguments is assigned, arguments [0] = 1, arguments [1] = 6, x and arguments [0], y and arguments [1] are correlated
Console. log (x, y, arguments [0], arguments [1 ]); //,
Var x = 3; // The value of x is 3, and x is associated with arguments [0], so arguments [0] is assigned 3.
Console. log (x, y, arguments [0], arguments [1]); // 3,6, 3,6
Var y = 4; // The value of y is 3, and y is associated with arguments [1], so arguments [1] is assigned 4.
Console. log (x, y, arguments [0], arguments [1]); // 3,4, 3,4
Arguments [0] = 2; // arguments [0] is assigned a value of 2. Since x and arguments [0] have been associated, x changes at the same time.
Console. log (x, y, arguments [0], arguments [1]); // 2, 4, 4
Arguments [1] = 5; // arguments [1] is assigned 5 values. Because y and arguments [1] have been associated, y changes at the same time.
Console. log (x, y, arguments [0], arguments [1]); // x = 2, y = 5, arguments [0] = 2, arguments [1] = 5
}
All of the above are speculative, because there is no way to form the parameter information, so I wrote a small test based on speculation:
The following is also changed:Copy codeThe Code is as follows: function _ Function () {// The list of parameters is an array: _ args
Var _ args = [];
For (var I = 0; I <arguments. length-1; I ++ ){
Var obj = {};
Obj ['key'] = arguments [I];
Obj [arguments [I] = undefined;
_ Args. push (obj );
}
// This. _ argu = _ args;
Var fn_body = arguments [arguments. length-1];
// The following method gets the real parameter _ arguments. Here _ arguments is implemented as an array instead of an arguments object.
This.exe c = function (){
// When the function is running, the real parameter _ arguments is assigned a value.
Var _ arguments = [];
For (var I = 0; I <arguments. length; I ++ ){
_ Arguments [I] = arguments [I];
}
// Execute the function body below
Eval (fn_body );
}
}
Replace:Copy codeThe Code is as follows: function _ Function () {// The list of parameters is an array: _ args
Var _ args = [];
For (var I = 0; I <arguments. length-1; I ++ ){
Var obj = {};
Obj ['key'] = arguments [I];
Obj [arguments [I] = undefined;
_ Args. push (obj );
}
// This. _ argu = _ args;
Var fn_body = arguments [arguments. length-1];
// The following method gets the real parameter _ arguments. Here _ arguments is implemented as an array instead of an arguments object.
This.exe c = function (){
// When the function is running, the real parameter _ arguments is assigned a value.
Var _ arguments = [];
For (var I = 0; I <arguments. length; I ++ ){
_ Arguments [I] = arguments [I];
}
// Determine the associated information at the start of the operation
For (var j = 0; j <Math. min (_ arguments. length, _ args. length); j ++ ){
_ Args [j] ["link"] = true;
}
// Execute the function body below
Eval (fn_body );
}
}
As mentioned above, the association should point the two to the same object, but I only need to analyze the example and do not intend to do so precisely, so it is determined by the if statement in the function body.
Replace fn_2 In the example with the following format:Copy codeThe Code is as follows: // function fn_2 (x ){
// Var x = 3;
// Console. log (x, arguments [0]);
// Arguments [0] = 2;
// Console. log (x, arguments [0]);
//}
// Fn_2 (1)
// In fn_2body, _ args [I] ["link"] = true; is used to indicate that the form participates in the real parameter Association.
Var fn_2body = ''+
'_ Args [0] [_ args [0] ["key"] = 3;' +
'If (_ args [0] ["link"]) {_ arguments [0] = _ args [0] [_ args [0] ["key"];} '+
'Console. log (_ args [0] [_ args [0] ["key"], _ arguments [0]); '+
'_ Arguments [0] = 2;' +
'If (_ args [0] ["link"]) {_ args [0] [_ args [0] ["key"] = _ arguments [0]} '+
'Console. log (_ args [0] [_ args [0] ["key"], _ arguments [0]); ';
Var fn_2 = new _ Function ('x', fn_2body );
Fn_2.exec (1 );
I drew a figure to show the relationship between the instance and the rewrite function. By the way, I also changed it:
Return to the example at the beginning of the article:Copy codeThe Code is as follows: function fn (x ){
X = 10;
Arguments [0] = 20;
Console. log (x, arguments [0])
}
Fn ()
Obviously, the two are independent of each other:
X = 10, arguments [0] = 20;
Let's guess:Copy codeThe Code is as follows: function fn (x ){
X = 10;
Arguments [0] = 20;
Console. log (x, arguments [0])
}
Fn (1)
Both outputs 20 and 20Copy codeThe Code is as follows: function fn (x ){
Arguments [0] = 20;
Console. log (x, arguments [0])
}
Fn (1)
Both outputs 20 and 20Copy codeThe Code is as follows: function fn (x ){
Arguments [0] = 20;
Console. log (x, arguments [0])
}
Fn ()
It should be undefined and 20
Source: cnblogs xiaoxishanzi