*概述

本文将说明函数相关的几个属性的含义,内容如下

---每个javascript函数有arguments和caller属性,记作F.arguments,F.caller(F表示函数名称);

---arguments有length和callee两个属性;

 

*属性含义

---F.arguments

1)包含传递给函数的参数对象,可以通过'[]运算'获取函数的参数;

2)具有length属性,表示函数参数的个数;

---F.caller

表示当前函数被哪个函数调用;

例如下面的示例中函数fun2中执行函数fun1,那么fun1.caller的值就是fun2;

通过这个属性的值, 可以获取函数的调用栈

---arguments.length

表示传递给arguments的参数个数

---arguments.callee

表示当前函数自身;

例如,下面的函数fun1,fun1.arguments.callee == fun1;

这个属性经常在new对象时, 用于修改对象的constructor属性, 让其值为函数自身.

 

*示例,演示了函数属性的取值

---源码(下载)

t_func.js
 1 function fun1(){
 2     console.log("run " + arguments.callee);
 3     console.log("arguments is array: " +  (arguments instanceof Array)); //false
 4     console.log("arguments.length: " + arguments.length);
 5     if(arguments.length > 0)
 6         console.log("arguments[0]: " + arguments[0]);
 7     console.log("arguments.callee: " + arguments.callee);
 8     console.log("arguments.callee.caller: " + arguments.callee.caller);
 9     console.log("\n");
10 }
11 
12 function fun2(){
13     console.log("run " + arguments.callee);
14     console.log("arguments is array: " +  (arguments instanceof Array)); //false
15     console.log("arguments.length: " + arguments.length);
16     console.log("arguments.callee: " + arguments.callee);
17     console.log("arguments.callee.caller: " + arguments.callee.caller);
18     console.log("\n")
19 
20     fun1(1);
21 }
22 
23 fun1();
24 fun2();
25 
26 console.log("host");
27 if(arguments){
28     console.log("host arguments.length: " + arguments.length);
29     console.log("host arguments.callee: " + arguments.callee);
30     console.log("host arguments.callee.caller: " + arguments.caller); //undefined
31 }

---结果(测试环境为Node)

运行结果
  1 dzh@dzh-laptop:~/lx/js/example$ node t_func.js //开始执行
  2 run function fun1(){  //运行fun1()
  3     console.log("run " + arguments.callee);
  4     console.log("arguments is array: " +  (arguments instanceof Array)); //false
  5     console.log("arguments.length: " + arguments.length);
  6     if(arguments.length > 0)
  7         console.log("arguments[0]: " + arguments[0]);
  8     console.log("arguments.callee: " + arguments.callee);
  9     console.log("arguments.callee.caller: " + arguments.callee.caller);
 10     console.log("\n");
 11 }
 12 arguments is array: false
 13 arguments.length: 0
 14 arguments.callee: function fun1(){
 15     console.log("run " + arguments.callee);
 16     console.log("arguments is array: " +  (arguments instanceof Array)); //false
 17     console.log("arguments.length: " + arguments.length);
 18     if(arguments.length > 0)
 19         console.log("arguments[0]: " + arguments[0]);
 20     console.log("arguments.callee: " + arguments.callee);
 21     console.log("arguments.callee.caller: " + arguments.callee.caller);
 22     console.log("\n");
 23 }
 24 arguments.callee.caller: function (exports, require, module, __filename, __dirname) { function fun1(){
 25     console.log("run " + arguments.callee);
 26     console.log("arguments is array: " +  (arguments instanceof Array)); //false
 27     console.log("arguments.length: " + arguments.length);
 28     if(arguments.length > 0)
 29         console.log("arguments[0]: " + arguments[0]);
 30     console.log("arguments.callee: " + arguments.callee);
 31     console.log("arguments.callee.caller: " + arguments.callee.caller);
 32     console.log("\n");
 33 }
 34 
 35 function fun2(){
 36     console.log("run " + arguments.callee);
 37     console.log("arguments is array: " +  (arguments instanceof Array)); //false
 38     console.log("arguments.length: " + arguments.length);
 39     console.log("arguments.callee: " + arguments.callee);
 40     console.log("arguments.callee.caller: " + arguments.callee.caller);
 41     console.log("\n")
 42 
 43     fun1(1);
 44 }
 45 
 46 fun1();
 47 fun2();
 48 
 49 console.log("host");
 50 if(arguments){
 51     console.log("host arguments.length: " + arguments.length);
 52     console.log("host arguments.callee: " + arguments.callee);
 53     console.log("host arguments.callee.caller: " + arguments.caller); //undefined
 54 }
 55 }
 56 
 57 
 58 run function fun2(){   //运行fun2()
 59     console.log("run " + arguments.callee);
 60     console.log("arguments is array: " +  (arguments instanceof Array)); //false
 61     console.log("arguments.length: " + arguments.length);
 62     console.log("arguments.callee: " + arguments.callee);
 63     console.log("arguments.callee.caller: " + arguments.callee.caller);
 64     console.log("\n")
 65 
 66     fun1(1);
 67 }
 68 arguments is array: false
 69 arguments.length: 0
 70 arguments.callee: function fun2(){
 71     console.log("run " + arguments.callee);
 72     console.log("arguments is array: " +  (arguments instanceof Array)); //false
 73     console.log("arguments.length: " + arguments.length);
 74     console.log("arguments.callee: " + arguments.callee);
 75     console.log("arguments.callee.caller: " + arguments.callee.caller);
 76     console.log("\n")
 77 
 78     fun1(1);
 79 }
 80 arguments.callee.caller: function (exports, require, module, __filename, __dirname) { function fun1(){
 81     console.log("run " + arguments.callee);
 82     console.log("arguments is array: " +  (arguments instanceof Array)); //false
 83     console.log("arguments.length: " + arguments.length);
 84     if(arguments.length > 0)
 85         console.log("arguments[0]: " + arguments[0]);
 86     console.log("arguments.callee: " + arguments.callee);
 87     console.log("arguments.callee.caller: " + arguments.callee.caller);
 88     console.log("\n");
 89 }
 90 
 91 function fun2(){
 92     console.log("run " + arguments.callee);
 93     console.log("arguments is array: " +  (arguments instanceof Array)); //false
 94     console.log("arguments.length: " + arguments.length);
 95     console.log("arguments.callee: " + arguments.callee);
 96     console.log("arguments.callee.caller: " + arguments.callee.caller);
 97     console.log("\n")
 98 
 99     fun1(1);
100 }
101 
102 fun1();
103 fun2();
104 
105 console.log("host");
106 if(arguments){
107     console.log("host arguments.length: " + arguments.length);
108     console.log("host arguments.callee: " + arguments.callee);
109     console.log("host arguments.callee.caller: " + arguments.caller); //undefined
110 }
111 }
112 
113 
114 run function fun1(){  //运行fun2中的fun1()
115     console.log("run " + arguments.callee);
116     console.log("arguments is array: " +  (arguments instanceof Array)); //false
117     console.log("arguments.length: " + arguments.length);
118     if(arguments.length > 0)
119         console.log("arguments[0]: " + arguments[0]);
120     console.log("arguments.callee: " + arguments.callee);
121     console.log("arguments.callee.caller: " + arguments.callee.caller);
122     console.log("\n");
123 }
124 arguments is array: false
125 arguments.length: 1
126 arguments[0]: 1
127 arguments.callee: function fun1(){
128     console.log("run " + arguments.callee);
129     console.log("arguments is array: " +  (arguments instanceof Array)); //false
130     console.log("arguments.length: " + arguments.length);
131     if(arguments.length > 0)
132         console.log("arguments[0]: " + arguments[0]);
133     console.log("arguments.callee: " + arguments.callee);
134     console.log("arguments.callee.caller: " + arguments.callee.caller);
135     console.log("\n");
136 }
137 arguments.callee.caller: function fun2(){
138     console.log("run " + arguments.callee);
139     console.log("arguments is array: " +  (arguments instanceof Array)); //false
140     console.log("arguments.length: " + arguments.length);
141     console.log("arguments.callee: " + arguments.callee);
142     console.log("arguments.callee.caller: " + arguments.callee.caller);
143     console.log("\n")
144 
145     fun1(1);
146 }
147 
148 
149 host  //最后运行宿主函数,使它执行了这个脚本
150 host arguments.length: 5
151 host arguments.callee: function (exports, require, module, __filename, __dirname) { function fun1(){
152     console.log("run " + arguments.callee);
153     console.log("arguments is array: " +  (arguments instanceof Array)); //false
154     console.log("arguments.length: " + arguments.length);
155     if(arguments.length > 0)
156         console.log("arguments[0]: " + arguments[0]);
157     console.log("arguments.callee: " + arguments.callee);
158     console.log("arguments.callee.caller: " + arguments.callee.caller);
159     console.log("\n");
160 }
161 
162 function fun2(){
163     console.log("run " + arguments.callee);
164     console.log("arguments is array: " +  (arguments instanceof Array)); //false
165     console.log("arguments.length: " + arguments.length);
166     console.log("arguments.callee: " + arguments.callee);
167     console.log("arguments.callee.caller: " + arguments.callee.caller);
168     console.log("\n")
169 
170     fun1(1);
171 }
172 
173 fun1();
174 fun2();
175 
176 console.log("host");
177 if(arguments){
178     console.log("host arguments.length: " + arguments.length);
179     console.log("host arguments.callee: " + arguments.callee);
180     console.log("host arguments.callee.caller: " + arguments.caller); //undefined
181 }
182 }
183 host arguments.callee.caller: undefined

 

*结果分析

---如何理解函数的属性(个人目前的想法)

每一个函数(这里指函数的源码脚本), 都对应一个执行上下文(这是运行时维护的对函数的一种描述), 函数的参数也在这个执行上下文中定义;

函数的每次被执行时, 解释器都将同步的去修改这个函数对应的上下文中的相关定义, 包括像arguments等属性的定义.

---脚本函数(宿主函数, 或许这些称呼都不正确)

像示例中的fun1()执行时, 可以发现它也有一个caller; 在示例的最后直接调用arguments(看看最后的host部分), 可以发现整个脚本t_func也同样被定义成了一个函数,

只是arguments.caller的值是undefined.

可以说, 每个js脚本也在运行环境里被定义为一个执行上下文.

---疑问, 为啥测试arguments的类型时, 它不是Array类型呢?

事实就是如此, 它不是一个Array类型但是可以用'[]'来运算.  不知为何要设计成这样.

  

*参考

http://debuggable.com/posts/turning-javascript-s-arguments-object-into-an-array:4ac50ef8-3bd0-4a2d-8c2e-535ccbdd56cb

 

posted on 2012-06-08 02:00  戴忠  阅读(708)  评论(0编辑  收藏  举报