this series as effective JavaScript 's reading notes.
due to historical reasons, many JavaScript The execution environment provides some way to view the function call stack. In some environments, thearguments object ( about which the object can view Item , There are two additional attributes on it:
Arguments.callee- it references the function that is being called
Arguments.caller- it references the function that called the current function
about the Arguments.callee use, you can refer to the following code:
var factorial = (function (n) {return (n <= 1)? 1: (N * Arguments.callee (n-1));});
visible, in the recursive function, you can use the callee to get the function that is currently being called.
However, it is also convenient to implement recursive invocation of functions by using function declarations, and this is clearer:
function factorial (n) {return (n <= 1)? 1: (N * factorial (n-1));}
and for Arguments.caller , it provides a more powerful feature that preserves a reference to the function that invokes the current function. Because it has security implications, many JavaScript Runtime environments remove this attribute. At the same time, some running environments provide a caller property on a function object to achieve the same effect as Arguments.caller:
function Revealcaller () {return revealcaller.caller;} function Start () {return Revealcaller ();} Start () = = = Start; True
Therefore, you can use this property to get information about the current call stack:
function Getcallstack () {var stack = [];for (var f = getcallstack.caller; f; f = F.caller) {Stack.push (f);} return stack;}
For a simple call relationship, the above can actually get the message of the call stack:
Function F1 () {return getcallstack ();} function F2 () {return f1 ();} var trace = F2 (); trace; [F1, F2]
But when a function occurs more than once in the call stack, a problem occurs, such as the following code produces a dead loop:
function f (n) {return n = = = 0? getcallstack (): F (n-1);} var trace = f (1); Infinite loop
The reason is that when a recursive call occurs, the function itself is assigned a value to its Caller property. Therefore , the terminating condition of the For loop in getcallstack F will never be false :
for (var f = getcallstack.caller; f; f = F.caller) {Stack.push (f);}
as a result of this instability and the resulting security problems, ES5 of the Strict Mode , use Caller or callee properties are forbidden:
function f () {"Use strict"; return F.caller;} f (); Error:caller accessed on strict functions
Summarize:
- Avoid using arguments object on the callee and the Caller property.
- Avoid using function object on the Caller property.
Effective JavaScript Item 29 avoid using non-canonical stack inspection properties