Function.caller、arguments.caller、argument.callee
caller、callee是与javascript函数相关的两个属性,今天来总结下。
Function.caller
caller是javascript函数的一个属性,它指向调用当前函数的函数,如果函数是在全局范围内调用的话,那么caller的值为null。
function outer() {
inner();
}
function inner() {
if(inner.caller==null) { //值为null,在全局作用域下调用
console.log("我是在全局环境下调用的");
} else {
console.log(inner.caller+"调用了我");
}
}
inner();
outer();
arguments.callee
arguments是函数内部中一个特殊的对象,callee是arguments的属性之一, 他指向拥有该arguments的函数对象。在某些不方便暴露函数名的情况下, 可以用arguments.callee代替函数名。但是,在严格模式(“use strict;”)下访问arguments.callee会抛出 TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them 错误
现在我们来仔细看看上面那段代码。如果老板说:“不行,函数名叫inner不好听,给我改!” 改代码容易,但是想改了后不出错误那可就难了。 这时我们就可以使用argument.callee来代替函数名,减少修改代码的地方,从而降低出错率
function outer() {
inner();
}
function inner() { //只需改这个函数名,而不需要改内部代码
if(arguments.callee.caller==null) {
console.log("我是在全局环境下调用的");
} else {
console.log(arguments.callee.caller+"调用了我");
}
}
inner();
outer();
除此之外,当我们写递归函数时,也会在函数里面暴露函数名,此时也会产生问题,如下。
/**
* factorial:阶乘
*/
function factorial(n) {
if(n<=1) {
return 1;
} else {
return n*factorial(n-1);
}
}
console.log(factorial(3)); //
var foo = factorial;
console.log(foo(3)); //
factorial = null;
console.log(foo(3)); //Error:factorial is not a function
factorial置为null,虽然foo指向了factorial使其不会被销毁, 但是原函数内部的函数名任然是factorial,自然应找不到而报错。 此时我们就可以用arguments.callee代替函数名
function factorial(n) {
if(n<=1) {
return 1;
} else {
return n*arguments.callee(n-1);
}
}
那还能不能更强点?毕竟arguments.callee在严格模式下是无法访问的,肯定没法儿用啊!
var factorial = (function foo(n) {
if(n<=1) {
return 1;
} else {
return n*foo(n-1); //内部可访问foo
}
});
foo(6); //ReferenceError: foo is not defined
以上代码利用命名函数表达式的形式创建了一个递归函数。 这有两个好处:第一,严格模式下函数任然能照常运转; 第二,性能优于argument.callee。注意foo仅在其函数体内可访问,在外是访问不到的。
arguments.caller
arguments.caller 这是我们遇到的第二个caller,没啥用,在严格模式下无法访问,非严格模式下值也为undefined,而且貌似被废弃了
总结
1.Function.caller指向调用该函数的函数
2.arguments.callee指向拥有该arguments的函数
3.arguments.caller没啥用
引用
1.《javascript高级程序设计》
2.MDN
2.1 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/caller
2.2 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/caller
2.3 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/arguments/callee
Function.caller、arguments.caller、argument.callee的更多相关文章
- 第4天:function对象(案例:获取当前日期属于当年第几天、arguments对象、函数类型、参数、返回值、自身调用)
获取当前日期输入当年第几天 //输入,年月日,获取这个日期是这一年的第几天 //年-月--日:20171月31日 function getDay(year,month,day){ //定义变量存储对应 ...
- JavaScript学习总结(三、函数声明和表达式、this、闭包和引用、arguments对象、函数间传递参数)
一.函数声明和表达式 函数声明: function test() {}; test(); //运行正常 function test() {}; 函数表达式: var test = functio ...
- (O)JS:执行环境、变量对象、活动对象和作用域链(原创)
var a=1; function b(x){ var c=2; console.log(x); } b(3); ·执行环境(execution context),也称为环境.执行上下文.上下文环境. ...
- 引用类型--Function类型(函数声明与函数表达式、arguments.callee、caller、apply、call、bind)
在ECMAScript中函数实际上是对象.每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法.由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定 ...
- js中函数的 this、arguments 、caller,call(),apply(),bind()
在函数内部有两个特殊的对象,arguments 和 this,还有一个函数对象的属性caller. arguments对象 arguments是一个类似数组的对象,包含着传入函数的所有参数. func ...
- Function.caller, arguments.caller, arguments.callee, arguments.callee.calller
Function.caller指向当前函数的调用者,是arguments.caller的替代者 arguments.caller也是指向当前函数的调用者,已被废弃 arguments.callee是对 ...
- javascript下的arguments,caller,callee,call,apply示例及理解
(参考:http://justcoding.iteye.com/blog/589111) Arguments 该对象代表正在执行的函数和调用它的函数的参数. [function.]arguments ...
- javascript 之Function对象的apply(),call(),bind(),方法和arguments,caller,length属性
注:这篇文章原文:http://www.jb51.net/article/30883.htm 自己作为学习,重新写写. 一.写在前面的话 前端javascript编程还只是略懂皮毛,DOM知道一点,j ...
- Spring8中lambda表达式的学习(Function接口、BiFunction接口、Consumer接口)
代码重构,为了确保功能的等效性,梳理代码时,发现如下代码: public SingleRespTTO fundI(SingleReqTTO request) throws Exception { re ...
随机推荐
- CodeForces 620A Professor GukiZ's Robot
水题 #include<cstdio> #include<cstring> #include<cmath> #include<stack> #inclu ...
- Openlayers修改矢量要素
将以下代码放到demo下examples中即可运行 <!DOCTYPE html><html> <head> <meta http-equiv="C ...
- memcache细节解析
转自:原链接 Memcached内存管理采取预分配.分组管理的方式,分组管理就是划分slab class,按照chunk的大小slab被分为很多种类. slab Slab是一个内存块,它是memc ...
- VS2010下创建的VB.NET项目打包发布安装包的流程
VS2010下创建的VB.NET项目打包发布安装包的流程 参考:http://blog.csdn.net/liuyanlinglanq/article/details/8609675 关于relea ...
- UVa 10041 - Vito's Family
题目大意:给出一些点,找到一个位置使这个位置到所有的点的距离的和最短. 很明显,排序,找中位数.关于中位数:有n个从小到大的数,k=(n+1)/2,若n为奇数,k为中位数,若n为偶数,k为中间那两个数 ...
- Python知识小点(备注)
(1)if __name__ == '__main__': 的作用是让后面的代码只有文件被作为程序执行时才有效,作为库加载时不执行
- IOS web app一些实用的属性设置
IOS对safari私有的属性很多,虽然很多不为人知但是却很实用.掌握好这些属性对web app和混合app的开发会很有帮助. 1.format-detection[telephone=no] 是否自 ...
- php redis 函数手册
Redis::__construct构造函数$redis = new Redis();connect, open 链接redis服务参数host: string,服务地址port: int,端口号ti ...
- CSS3 :target伪类实现Tab切换效果 BY commy
http://www.shejidaren.com/examples/css3-target/css3-target.html#tab1 标签一 标签二 标签三 欢迎加设计达人Q群:50063010设 ...
- angular指令中,require和transclude同时设置为true时的作用
最近在学习angularJS指令的时候,对指令对象中require属性和transclude属性同时设置为true比较疑惑,于是自己动手测试一下具体差异 index.html: <simple& ...