javascript中callee与caller的用法和接收场景_javascript技能_脚本之家

最近学习javascript,碰到caller和callee的问题,去网上百度了很多。搜到的内容大同小益,整理总结了一下与大家分享。

callee

caller : functionName.caller 返回调用者。
看看下面的函数,大家可以复制到VS中执行下 复制代码 代码如下: function caller() { if {
alert(caller.caller.toString; } else { alert; } } function handleCaller;
} handleCaller;
大家会发现第一个alert会弹出调用caller函数的调用者handleCaller,而第二个alert由于没有在其他函数体内调用,所以caller为null,就执行了
alert; callee: 返回正被执行的 Function 对象,也就是所指定的 Function
对象的正文. callee是arguments
的一个属性成员,它表示对函数对象本身的引用,这有利于匿名
函数的递归或者保证函数的封装性。
下面一段代码先说明callee的用法,实例代码摘自网上 复制代码 代码如下: function calleeLengthDemo {
alert(arguments.callee.toString; if (arguments.length ==
arguments.callee.length) { window.alert; return; } else {
alert(“实参长度:” + arguments.length); alert(“形参长度: ” +
arguments.callee.length); } } calleeLengthDemo;
第一个消息框弹出calleeLengthDemo函数本身,这说明callee就是函数本身对象的引用。callee还有个非常有用的应用就是用来判断实际参数跟行参是否一致。上面的代码第一个消息框会弹出实际参数的长度为1,形式参数也就是函数本身的参数长度为2.
应用场景: callee的应用场景一般用于匿名函数 大家看下下面一段代码
摘自网络 复制代码 代码如下: var
fn=function return n+fn; return 0; } alert
函数内部包含了对自身的引用,函数名仅仅是一个变量名,在函数内部调用即相当于调用
一个全局变量,不能很好的体现出是调用自身,这时使用callee会是一个比较好的方法
复制代码 代码如下: var fn= return
n+arguments.callee 这样就让代码更加简练。又防止了全局变量的污染。
caller的应用场景 主要用于察看函数本身被哪个函数调用。

arguments是什么?

在提到上述的概念之前,首先想说说javascript中函数的隐含参数:arguments
Arguments 该对象代表正在执行的函数和调用它的函数的参数。
[function.]arguments[奥门威尼斯网址,n] 参数function :选项。当前正在执行的 Function
对象的名字。 n :选项。要传递给 Function 对象的从0开始的参数值索引。
说明
Arguments是进行函数调用时,除了指定的参数外,还另外创建的一个隐藏对象。Arguments是一个类似数组但不是数组的对象,说它类似数组是因为其具有数组一样的访问性质及方式,可以由arguments[n]来访问对应的单个参数的值,并拥有数组长度属性length。还有就是arguments对象存储的是实际传递给函数的参数,而不局限于函数声明所定义的参数列表,而且不能显式创建
arguments 对象。arguments
对象只有函数开始时才可用。下边例子详细说明了这些性质: 复制代码 代码如下: //arguments 对象的用法。
function ArgTest{ var i, s = “The ArgTest function expected “; var
numargs = arguments.length; // 获取被传递参数的数值。 var expargs =
ArgTest.length; // 获取期望参数的数值。 if s += expargs + ” argument. “;
else s += expargs + ” arguments. “; if s += numargs + ” was passed.”;
else s += numargs + ” were passed.”; s += “\n\n” for (i =0 ; i <
numargs; i++){ // 获取参数内容。 s += ” Arg ” + i + ” = ” +
arguments[i] + “\n”; } return; // 返回参数列表。 }
在此添加了一个说明arguments不是数组的代码: 复制代码 代码如下: Array.prototype.selfvalue =
1; alert.selfvalue); function testAguments(){ alert; }
运行代码你会发现第一个alert显示1,这表示数组对象拥有selfvalue属性,值为1,而当你调用函数testAguments时,你会发现显示的是“undefined”,说明了不是arguments的属性,即arguments并不是一个数组对象。
在此附加上大家推荐的一个简单方法: 复制代码 代码如下: alert(arguments instanceof
Array); alert(arguments instanceof Object); caller
返回一个对函数的引用,该函数调用了当前函数。 functionName.caller
functionName 对象是所执行函数的名称。 说明 对于函数来说,caller
属性只有在函数执行时才有定义。如果函数是由顶层调用的,那么 caller
包含的就是 null 。如果在字符串上下文中使用 caller 属性,那么结果和
functionName.toString 一样,也就是说,显示的是函数的反编译文本。
下面的例子说明了 caller 属性的用法: 复制代码 代码如下: // caller demo { function
callerDemo() { if { var a= callerDemo.caller.toString; } else {
alert(“this is a top function”); } } function handleCaller; } callee
返回正被执行的 Function 对象,也就是所指定的 Function 对象的正文。
[function.]arguments.callee 可选项 function 参数是当前正在执行的
Function 对象的名称。 说明 callee 属性的初始值就是正被执行的 Function
对象。 callee 属性是 arguments
对象的一个成员,它表示对函数对象本身的引用,这有利于匿名
函数的递归或者保证函数的封装性,例如下边示例的递归计算1到n的自然数之和。而该属性
仅当相关函数正在执行时才可用。还有需要注意的是callee拥有length属性,这个属性有时候
用于验证还是比较好的。arguments.length是实参长度,arguments.callee.length是
形参长度,由此可以判断调用时形参长度是否和实参长度一致。 示例 复制代码 代码如下: //callee可以打印其本身
function calleeDemo() { alert; } //用于验证参数 function
calleeLengthDemo { if (arguments.length==arguments.callee.length) {
window.alert; return; } else { alert(“实参长度:” +arguments.length);
alert(“形参长度: ” +arguments.callee.length); } } //递归计算 var sum =
function return 1; else return n +arguments.callee }
比较一般的递归函数: 复制代码 代码如下:
var sum = function return 1; else return n + sum ; 调用时:alert;
其中函数内部包含了对sum自身的引用,函数名仅仅是一个变量名,在函数内部调用sum即相当于调用
一个全局变量,不能很好的体现出是调用自身,这时使用callee会是一个比较好的方法。
apply and call
它们的作用都是将函数绑定到另外一个对象上去运行,两者仅在定义参数方式有所区别:
apply; call(thisArg[,arg1,arg2…] ]);
即所有函数内部的this指针都会被赋值为thisArg,这可实现将函数作为另外一个对象的方法运行的目的
apply的说明 如果 argArray 不是一个有效的数组或者不是 arguments
对象,那么将导致一个 TypeError。 如果没有提供 argArray 和
thisArg任何一个参数,那么 Global 对象将被用作 thisArg,
并且无法被传递任何参数。 call的说明 call
方法可将一个函数的对象上下文从初始的上下文改变为由 thisArg指定的新对象。
如果没有提供 thisArg参数,那么 Global 对象被用作 thisArg 相关技巧:
应用call和apply还有一个技巧在里面,就是用call和apply应用另一个函数就具备了另一个函数的方法或者是属性,这也可以称之为“继承”。看下面示例:
复制代码 代码如下: // 继承的演示 function
base() { this.member = ” dnnsun_Member”; this.method = function() {
window.alert; } } function extend; window.alert; window.alert; }
上面的例子可以看出,通过call之后,extend可以继承到base的方法和属性。
顺便提一下,在javascript框架prototype里就使用apply来创建一个定义类的模式,
其实现代码如下: 复制代码 代码如下: var
Class = { create: function { this.initialize.apply; } } }
解析:从代码看,该对象仅包含一个方法:Create,其返回一个函数,即类。但这也同时是类的
构造函数,其中调用initialize,而这个方法是在类创建时定义的初始化函数。通过如此途径,
就可以实现prototype中的类创建模式 示例: 复制代码 代码如下: var vehicle=Class.create();
vehicle.prototype={ initialize:function{ this.type=type; }
showSelf:function(){ alert(“this vehicle is “+ this.type); } } var
moto=new vehicle; moto.showSelf();
更详细的关于prototype信息请到其官方网站查看。
评论还有更精彩对此的理解,在这我就不再添加了,大家可以看看加深理解。
看完了上面的代码,就可以,下面的代码是给一些比较想立即看到效果的人看的。多测试。复制代码 代码如下:

caller:返回一个对调用function函数的函数的引用

callee是对象的一个属性,该属性是一个指针,指向参数arguments对象的函数首先我们来写个阶成函数:

arguments是函数调用时,创建的一个类似的数组但又不是数组的对象,并且它存储的是实际传递给函数的参数,并不局限于函数声明的参数列表哦。

说明:对于函数来说,caller属性只有在函数执行时才有定义。如果函数由顶层调用,caller则为null。

function chen {return 1;} else{return x*chen;};};

写个demo看看,代码见下

var time = 3 //控制次数,去掉会一直在caller与handleCaller交替不断执行function caller//返回调用caller函数的函数引用}function handleCaller{ time-- alert//返回调用handleCaller函数的函数引用 alert//返回调用caller函数的函数引用 caller

从这个函数中可以看出来,用到了递归函数,要是改变了函数名,里面的函数名也要随着改变,这样很不方便所以我们用callee来试试

  arguments    function obj(){ //&#21033;&#29992;instanceof&#21028;&#26029;arguments console.log( 'arguments instanceof Array&amp;#63; ' + (arguments instanceof Array) ); console.log( 'arguments instanceof Object&amp;#63; ' + (arguments instanceof Object) ); console.log;  

例子分析:第一次handleCaller运行的时候,两个alert返回的都是null,alert返回null是因为它是由顶层调用,
alert返回null是因为caller的默认值是null。接下去caller()函数被调用,caller.caller返回的是调用它的函数的引用,通过caller.caller()可以再次调用handleCaller函数。第二次handleCaller运行的时候,alert返回的是caller代码,alert返回的是handleCaller代码。因为函数之间的调用关系是handleCaller->caller->handleCaller。之后就不断在2个函数之间交替执行。

function chen {return 1;}else{return x*arguments.callee;};};

caller指向调用当前函数的函数,但是有一点,如果是在全局作用域内被调用,则返回null。代码走起

我们来分析一下为什么这样写:根据callee的定义,可以看出来callee是arguments对象的一个属性,指向arguments对象的函数,这个函数就是chen(chen=arguments.callee),这样解释应该可以理解了吧。

====================function testCaller(){if(testCaller.caller == null){console.log;}else{console.log('accessed at ' + testCaller.caller);}}

testCaller(); // accessed at global

function a; // accessed at function a;} 

caller

此时,testCaller.caller指向就是 function a

caller是函数对象的一个属性,该属性保存着调用当前函数的函数的引用

callee:返回相对应的arguments的函数引用。

function a{alert; //结果就是弹出函数a和内容

说明:也许你在网上看到最多的是callee返回正在执行的函数引用。我是这么理解,每个函数都有一个自己的arguments,通常是用来存放参数的。arguments有一个callee
属性,初始值就是对应自身的函数引用。当你函数执行到该语句时,arguments是默认对应的是你现在执行的函数,那么arguments.callee为当前正在执行的函数的引用。当然如果你有标记过其他函数的arguments,自然可以用args.callee()去再次调用那个函数。

我们来解释一下吧,首先函数b的属性caller调用当前函数b的函数引用a,所以结果就是弹出
function a;};

function a(){ alert var args = arguments function c(){ alert args.callee

那么了解了caller和callee,那么可以不可以将二者结合在一起来使用呢

例子分析:例子中的arguments.callee都是默认返回当前正在执行的函数的引用(a中返回a自身函数引用,c中返回c自身函数引用),而通过用args存放a函数的arguments,在内置函数c中使用args.callee()再次调用a函数。

function b;};
====================function areturn x;elsereturn x + a // 78

从这个代码可以看出b函数中调用了b函数名,这样当函数名改变时就很不方便,我们需要替换里面的那个b前面我们知道用什么方法可以指向当前对象,下面我们就来修改一下:

这是一个极简的递归,运行结果正常。

;function b(){alert(arguments.callee.caller);};
var b = a;a = null; // 将a回收b; // erro : 'a' is not a function

从代码中可以看出我们用arguments.callee代替了b函数,所以解决了一下麻烦。。。。。

原因也简单,b=a,b=function a(){};在b调用之前,我们用了a=null。所以在
function a 运行的时候,其中的return x + a;中的a,指向的就是null,而不是
function a。所以就报错了,如何解决这样的问题。我们将a换一种写法

以上所述就是本文的全部内容了,希望大家能够喜欢。

function areturn x;elsereturn arguments.callee; // 这句是改变的地方}

var b = a;a = null;b; // 78

原因:虽然我们将a=null了,但是函数a中并没有用到a,而是通过arguments.callee指向当前函数。因为arguments.callee的定义就是:返回正在执行的函数。

发表评论

电子邮件地址不会被公开。 必填项已用*标注