-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathitem_29.js
More file actions
75 lines (61 loc) · 1.96 KB
/
item_29.js
File metadata and controls
75 lines (61 loc) · 1.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Avoid nonstandard stack inspection properties
//
// many Js envs have historically provided some capabilities to inspect the
// 'call stack'
//
// in some older host envs, the 'arguments' object came with two additional
// properties:
// arguments.callee - the function that was called with arguments
// arguments.caller - function that called it
//
// 'arguments.callee' is still supported, but only useful to anonymous
// functions to refer to themeselves recursively
var factorial = (function(n) {
return (n <= 1) ? 1 : (n * arguments.callee(n - 1));
});
// better just have a function refer to itself by its name
function factorial(n) {
return (n <= 1) ? 1 : (n * factorial(n - 1));
}
// arguments.caller refers to the function that made the call with the given
// arguments object
// WARNING: Has been removed from most environments for security
//
// Caveat Emptor: some envs have a 'caller' property which refers to the
// functions most recent caller
function revealCaller(){
return revealCaller.caller;
}
function start() {
return revealCaller()
}
start() === start; // true
// it is tempting to try to use this property to extract a 'stack trace'
function getCallStack() {
var stack = [];
for (var f = getCallStack.caller; f; f = f.caller) {
stack.push(f);
}
return stack;
}
// for simple call stacks, 'getCallStack' appears to work fine
function f1() {
return getCallStack();
}
function f2() {
return f1();
}
var trace = f2()
trace; // [f1, f2]
// 'getCallStack' can easily be broken: if the function shows up more than once
// in the call stack, the stack inspection logic gets stuck in a loop
function f(n) {
return n === 0 ? getCallStack() : f(n - 1);
}
var trace = f(1); // infinite loop, because of recursive calls to f
// ES5 strict functions does not allow accesses to 'caller' or 'callee'
function f() {
"use strict";
return f.caller;
}
f(); // error: caller may not be accessed on strict functions