A function is a convenient way to store code as a data structure that can be executed after the code. This makes it possible to abstract expressive higher-order functions such as map and foreach. It is also the core of the JS asynchronous I/O method. At the same time, you can pass the code as a string to the Eval function to achieve the same functionality.
Programmers face a choice: Should the code be represented as a function or a string?
There is no doubt that code should be represented as a function. One important reason for the lack of flexibility in string notation is that they are not closures.
Closure review
Look at the picture below.
The function values of JS contain more information than the code needed to execute when invoking them. and the JS function values are also stored internally that they may reference variables defined in their enclosing scopes. Functions that track variables within the scope they cover are called closures.
Detailed information to the previous "[Effective JavaScript note] 11th: Master closure" view
String Encapsulation Code
Suppose there is a simple function that repeats the user-supplied action multiple times.
function repeat (n,action) {for (var i=0;i<n;i++) { eval (action);} }
This function does not work well in global scope because the Eval function interprets all the variable references in the string that appear as global variables. For example, a script that tests the benchmark execution speed of a function might use the global start and end variables to store the time exactly.
var start=[],end=[],timings=[];repeat ("Start.push" (Date.now ()); F (); End.push (Date.now ()) "); for (Var i=0,n= start.length;i<n;i++) { timings[i]=end[i]-start[i];}
But the script is fragile. If we simply move the code into a function, then the start and end variables will no longer be global variables.
Function Benchmark () { var start=[],end=[],timings=[]; Repeat (Start.push (Date.now ()); F (); End.push (Date.now ()) "); for (Var i=0,n=start.length;i<n;i++) { timings[i]=end[i]-start[i]; } return timings;}
This time the repeat function does not have access to the internal variable start,end of the benchmark function. Or in the global space to find the start,end variable, if it is not a good situation, you can follow the error prompt to complete the error location. If there is a start,end variable in the global at this time, the global variable will be modified and the resulting behavior cannot be predicted.
Closure Package Code
Or use the example above, but some of these we use the closed package to handle the code.
Overwrite repeat function, parameter action is a function, not a string
function repeat (n,action) {for (var i=0;i<n;i++) { action ();} }
Overwriting the benchmark function, the script can safely refer to the local variable start,end in the closure, which is passed in with the callback function of the repeat function.
Function Benchmark () { var start=[],end=[],timings=[]; Repeat (1000,function () { Start.push (Date.now ()); f (); End.push (Date.now ()); }); for (Var i=0,n=start.length;i<n;i++) { timings[i]=end[i]-start[i]; } return timings;}
Another problem with the Eval function is that some high-performance engines are often difficult to optimize for code in strings because the compiler is not able to get the source code as early as possible to optimize the code in a timely manner. function expressions can be compiled at the same time that their code appears, making it more suitable for standardized compilation.
Other Eval related content can be viewed:
[Effective JavaScript note] 16th: Avoid using eval to create local variables
[Effective JavaScript note] 17th: Indirect call to eval function is better than direct call
Tips
Never include a local variable reference in a string when passing a string to the Eval function to execute their API
An API that accepts function calls is better than an API that uses the Eval function to execute strings
Appendix: Code full version
Tidy up the code above to generate a code that can test the execution time of any function
function repeat (n,action) {for (var i=0;i<n;i++) { action ();} } Function Benchmark (N,FN) { var start=[],end=[],timings=[]; Repeat (N,function () { Start.push (Date.now ()); fn (); End.push (Date.now ()); }); for (Var i=0,n=start.length;i<n;i++) { timings[i]=end[i]-start[i]; } return timings;} Test code function concatstring (A, b) { return a+b;} Benchmark (10000,function () {concatstring (' 1 ', ' 2 ');}); /General Call Benchmark (10000,concatstring.bind (null, ' 1 ', ' 2 ');//favor Bind method to generate new function
[Effective JavaScript note] 27th: encapsulate code using closures instead of strings