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 ...
随机推荐
- Python正则表达式学习笔记
[] 字符类,只要匹配里面的任意字符,都算匹配 . 元字符,可以匹配除换行符之外的所有字符 大小写敏感,但是可以关闭 \d 可以匹配0-9中的任意数字 {3}大括号里面的数字,边上前面一个字符匹配的 ...
- 数据降维技术(2)—奇异值分解(SVD)
上一篇文章讲了PCA的数据原理,明白了PCA主要的思想及使用PCA做数据降维的步骤,本文我们详细探讨下另一种数据降维技术—奇异值分解(SVD). 在介绍奇异值分解前,先谈谈这个比较奇怪的名字:奇异值分 ...
- Lumen 配置、重写、404错误等
1.权限是否有设置为777: 2.app key是否有设置: 3.apache下是否有开启重写,a2enmod: 4.nginx下server的location是否配置正确,重写规则有没添加,rout ...
- Java 的Object类
1.toString()是Objectde的方法,如果不重写,直接输出对象或者用对象调用toString()输出是会输出包名.类名@对象哈希码的无符号十六进制表示 子类如果重写了这个方法,可以隐式调用 ...
- Linux下mysql数据库的命令
连接数据库命令:mysql -u 用户名 -p 密码 要求你输入要连接数据库的用户名和密码.用户名默认root密码不方便输入时,可以只输入:mysql -u 用户名 -p 然后回车,此时提示你输入密码 ...
- 学习c++语言应该牢记的50条准则,同样学习其他语言也一样
1.把C++当成一门新的语言学习(和C没啥关系!真的.): 2.看<Thinking In C++>,不要看<C++变成死相>: 3.看<The C++ Programm ...
- php 三大特点:封装,继承,多态
一.封装 目的:让类更安全 做法:成员变量变为私有的,通过方法间接操作成员变量,在方法里面加限制条件 二.继承 概念:子类可以继承父类的一切 方法重写:在子类里面对父类进行方法重写 特点:单继承:一个 ...
- css(二) block,inline和inline-block概念和区别
转: http://www.cnblogs.com/KeithWang/p/3139517.html 总体概念 block和inline这两个概念是简略的说法,完整确切的说应该是 block-leve ...
- IOS开发-ObjC-对象、封装
C语言是基于过程的一种编程语言,而OC语言是基于对象的一种语言. C是和其他的面向对象的语言的区别在于C语言更注重地层操作,思维方式相比面向对象的语言而言更接近机器的思维方式,而面向对象的语言更接近于 ...
- C++ 句柄类
一.容器与继承 在容器中保存有继承关系的对象时,如果定义成保存基类对象,则派生类将被切割,如果定义成保存派生类对象,则保存基类对象又成问题(基类对象将被强制转换成派生类对象,而派生类中定义的成员未被初 ...