使用js callee 递归的作用有什么作用

js&callee实现递归
//递归计算
var sum = function(n) {
&&& else {
return n + arguments.callee(n - 1);
alert(sum(3));
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。JS arguments.callee一些用途
  argument代表当前函数的参数数组
  arguments.callee表示引用当前正在执行的函数,或者说是调用arguments.callee的函数对象的引用,它给匿名函数提供了一种自我引用的方式。通过如下例子,可以更好的理解概念。
var func = function() { alert(func ===
arguments.callee);}func();
  执行上述代码,可以看到alter出来的结果是true,注意,此处用的是“===”,就是说func与arguments.callee对象类型和值都相等。
  上面讲了arguments.callee的定义,那么它用在什么场合呢?一般来说,它会和匿名函数一起结合来用。
  例如js脚本当前等待页面某种条件是否满足,如果满足进行相应初始化处理,但不是一直等下去,超过一定时间就放弃等待
var flag = false, start = (new Date()).getTime();//普通实现
1function fun1() { //flag状态会在其他地方修改,当满足条件后执行相应逻辑 if (flag) { // do
} //超过等待时间,放弃 if ((new Date()).getTime() - start
& 3000) { } //等待一秒后重试 setTimeout(fun1,
1000);}fun1();//普通实现 2function fun2() { if (flag) { // do something
clearInterval(handler); } if ((new Date()).getTime() -
start & 3000) { clearInterval(handler);
}}var handler = setInterval(func2, 1000);//匿名函数实现(function(){ if
(flag) { // } if ((new Date()).getTime() -
start & 3000) { }
setTimeout(arguments.callee, 1000);})();
  比如执行初始化操作,使用匿名函数的好处是确保只被执行一次,而前面两种实现,由于定义了函数,就有可能在别处被误调用,从而执行多次初始化。
  再看一递归调用例子:求一个数的阶乘
//普通实现function fun2(n) { if (n & 1) { return n *
fun2(n -1); } return 1;}var r1 = fun2(3);//使用匿名函数var r2 =
(function(n) { if (n & 1) { return n *
arguments.callee(n -1); } return 1;})(3);
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。js arguments,jcallee caller用法总结
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了js中arguments, jcallee caller用法。需要的朋友可以过来参考下,希望对大家有所帮助
关键字:arguments,callee,callerarguments:表示传入函数的参数callee:表示函数和函数主体的语句caller:表示调用该函数的函数arguments
该对象代表正在执行的函数和调用它的函数的参数。
返回一个对函数的引用,该函数调用了当前函数。functionName.callerfunctionName 对象是所执行函数的名称。
说明对于函数来说,caller属性只有在函数执行时才有定义。如果函数是由顶层调用的,那么 caller包含的就是 null 。如果在字符串上下文中使用 caller 属性,那么结果和functionName.toString一样,也就是说,显示的是函数的反编译文本。
返回正被执行的 Function 对象,也就是所指定的Function 对象的正文。
[function.]arguments.callee
可选项 function 参数是当前正在执行的 Function 对象的名称。
callee 属性的初始值就是正被执行的 Function 对象。
callee 属性是 arguments对象的一个成员,它表示对函数对象本身的引用,这有利于匿名函数的递归或者保证函数的封装性,例如下边示例的递归计算1到n的自然数之和。而该属性仅当相关函数正在执行时才可用。还有需要注意的是callee拥有length属性,这个属性有时候用于验证还是比较好的。arguments.length是实参长度,arguments.callee.length是形参长度,由此可以判断调用时形参长度是否和实参长度一致。 代码如下:&script type='text/javascript'&function test(x,y,z) { alert("实参长度:"+arguments.length);alert("形参长度:"+arguments.callee.length);alert("形参长度:"+test.length);alert(arguments[ 0 ])&&&&&&&& alert(test[ 0 ])&&&&&&&&&& // undefined 没有这种用法
//test(1,2,3); test(1,2,3,4);
/**& arguments不是数组(Array类)*/Array.prototype.selfvalue& =&& 1 ;function& testAguments() {&&& alert( " arguments.selfvalue= " + arguments.selfvalue);}alert("Array.sefvalue="+new Array().selfvalue);testAguments();
/**/ /*&* 演示函数的caller属性.&* 说明:(当前函数).caller:返回一个对函数的引用,该函数调用了当前函数& */
function& callerDemo()& {&&&& if& (callerDemo.caller)& {&&&&&&&& var& a =& callerDemo.caller.arguments[ 0 ];&&&&&&& alert(a);&&& }&& else&& {&&&&&&& alert( " this is a top function " );&&& }}function& handleCaller()& {&&& callerDemo();}
&callerDemo();&handleCaller("参数1","参数2");
/**/ /*&* 演示函数的callee属性.&* 说明:arguments.callee:初始值就是正被执行的 Function 对象,用于匿名函数& */function& calleeDemo()& {&&& alert(arguments.callee);}&calleeDemo();&(function(arg0,arg1){alert("形数数目为:"+arguments.callee.length)})();
/**/ /*&* 演示apply,call函数的用法&* 说明:作用都是将函数绑定到另外一个对象上去运行,两者仅在定义参数方式有所区别:&*&&&&&& apply(thisArg,argArray);&*&&&& call(thisArg[,arg1,arg2…] ]);&*&&&& 即所有函数内部的this指针都会被赋值为thisArg& */
& function& ObjectA() {&&& alert( " 执行ObjectA() " );&&& alert(arguments[ 0 ]);&&&& this .hit = function (msg) {alert(msg)}&&&& this .info = " 我来自ObjectA "&}& function& ObjectB() {&&& alert( " 执行ObjectB() " );&&&& // 调用ObjectA()方法,同时ObjectA构造函数中的所有this就会被ObjectB中的this替代&&& ObjectA.apply( this ,arguments); // ObjectA.call(this);&&& alert( this .info);&}& ObjectB('参数0');
& var& value = " global 变量 " ;& function& Obj() {&&&& this .value = " 对象! " ;&}& function& Fun1() {&&& alert( this .value);&}&& Fun1();&& Fun1.apply(window); && Fun1.apply(new Obj());
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具函数表达式的基本概念
name属性和函数提升
首先,name属性,通过这个属性可以访问到给函数指定的名字。(非标准的属性)如:
function People(){};
console.log(People.name); //People
其次,函数声明提升,意味着可以把函数声明放在调用它的语句后面。如:
sayHi(); //调用函数
function sayHi(){ //声明函数
console.log("Hi");
} //不会报错
使用函数表达式则不可以:
var sayHi = function(){
console.log("Hi");
创建函数的两种方式,一个是函数声明(如第一种方式);一个是函数表达式(如第二种方式)。第二种函数创建方式创建的函数叫“匿名函数”或“拉姆达函数”,因为function 关键字后面没有标识符。
函数提升的常见错误
需要注意的是,作为对比,下面的两种代码中,第一个是错误的(会导致各浏览器出现不同的问题);第二个才使正确的。代码如下:
var condition =
if (condition){
function sayHI(){
console.log("hi")
sayHI(); //"hello"
function sayHI(){
console.log("hello")
var condition =
var sayHi;
if(condition){
sayHi = function(){
console.log("hi")
sayHi = function(){
console.log("hello")
sayHi(); //hello
var condition =
if(condition){
var sayHi = function(){
console.log("hi")
sayHi(); //hi
var sayHi = function(){
console.log("hello")
sayHi(); //hello
这里也不会出现问题。出现上面问题的根源就是函数提升,就是函数声明和函数表达式之间的区别所导致的。
函数的递归
递归函数就是在一个函数通过名字调用自身的情况下构成的。如:
function factorial(num){
if(num &= 1){
return num * factorial(num - 1);
console.log(factorial(4)); //24 4*3*2*1
但是,函数里面包含了函数自身所以,在应该使用arguments.callee来解决该问题。如:
function factorial(num){
if(num &= 1){
return num * arguments.callee(num - 1);
console.log(factorial(4)); //24 4*3*2*1
但如果使用上面这种方法,则在严格模式下行不通。不过可以使用命名函数表达式来达成相同的结果。如:
var factorial = (
function f(num){
if(num &= 1){
return num * f(num - 1);
console.log(factorial(4)); //24 4*3*2*1
即,把它包含在一个变量里面,在遇到其他这种需要使用arguments.callee的时候都可以这样做。
函数的闭包
闭包就是有权访问另一个函数作用域中的变量的函数。常见的创建闭包的方式就是在一个函数内部创建另一个函数。在此之前应该先掌握作用域链的概念(见《Javascript执行环境和作用域的注意要点》一文)
以下面的代码为例
function compare(value1,value2){
if (value1 & value2){
}else if (value1 & value2){
return -1;
var result = compare(5,10);
调用函数compare时,函数执行环境中的作用域链:
作用域链本质上是一个指向变量对象的指针列表。
另一个例子:
function createComparisonFunction(propertyName){
return function(object1,object2){
var value1 = object1[propertyName];
var value2 = object2[propertyName];
if (value1 & value2){
return -1;
}else if(value1 & value2){
var compare = createComparisonFunction("name");
var result = compare({name: "Nicholas"},{name: "Greg"});
这个就相当于:
var compare = function(object1,object2){
var value1 = object1["name"];
var value2 = object2["name"];
if (value1 & value2){
return -1;
}else if(value1 & value2){
var result = compare({name: "Nicholas"},{name: "Greg"});
var result = function(){
var value1 = {name: "Nicholas"}["name"];
var value2 = {name: "Greg"}["name"];
if (value1 & value2){
return -1;
}else if(value1 & value2){
console.log(result()); //1
所以,完整的代码如下:
var compareNames = createComparisonFunction("name");
function createComparisonFunction(propertyName){
return function(object1,object2){
var value1 = object1[propertyName];
var value2 = object2[propertyName];
if (value1 & value2){
return -1;
}else if(value1 & value2){
var result = compareNames({name: "Nicholas"},{name: "Greg"});
compareNames =
调用compareNames()函数的过程中产生的作用域链之间的关系图如下:
常见的闭包的模式一般都是这样:
var X = function A(a){
return function(b1,b2){...a...} //匿名函数
var Y = X(b1,b2);
举个例子:
var obj1 = {
name: "co",
color: ["white","black"]
var obj2 = {
name: "lor",
color: ["yellow","red"]
function displayProperty(propertyName){
return function(obj1,obj2){
var value1 = obj1[propertyName];
var value2 = obj2[propertyName];
if(typeof value1 === "string"){
return value1 + " and " + value2 + "&br/&";
}else if(value1 instanceof Array){
return value1.toString() + "&br/&" + value2.toString();
var displayP = displayProperty("name");
var displayStr = displayP(obj1,obj2);
document.write(displayStr);
displayP =
var displayP = displayProperty("color");
var displayStr = displayP(obj1,obj2);
document.write(displayStr);
co and lor
white,black
yellow,red
闭包会携带他包含的函数的作用域,因此会更多的占用内存资源,建议只有在绝对必要的时候再考虑使用闭包。V8 优化后的js 引擎会尝试收回被闭包占用的内存。
闭包与变量
闭包的副作用是闭包只能取得包含函数中任何变量的最后一个值。
全局函数中this = window;当函作为位某个对象的方法调用时this = 那个对象;但是匿名函数的执行环境又全局性,this 通常指向window;但也有例外:
var name = "the window";
var obj = {
name: "the obj",
getNameFunc: function(){
return function(){
return this.
console.log(obj.getNameFunc()()); //"the window" 别忘了要写两个小括号
因为每个函数在被调用的时候都会自动取得两个特殊的变量:this 和arguments;内部函数在搜索这两个变量时,只会搜索到其活动对象为止。
var obj = {
name: "Oliver",
friends: ["alice","troy"],
sayName: function(){
return this.
sayFriends: function(){
return function(){
return this.
console.log(obj.sayFriends()()); //undefined
上面这个代码就是因为闭包的问题,导致错误。又如:
var friends = "window's friends";
var obj = {
name: "Oliver",
friends: ["alice","troy"],
sayName: function(){
return this.
sayFriends: function(){
return function(){
return this.
console.log(obj.sayFriends()()); //window's friends 匿名函数执行环境的全局性
解决这个问题的方法是:
var friends = "window's friends";
var obj = {
name: "Oliver",
friends: ["alice","troy"],
sayName: function(){
return this.
sayFriends: function(){
var outer =
return function(){
return outer.
console.log(obj.sayFriends()()); //["alice","troy"] 这样就可以正常搜索到了
var friends = "window's friends";
var obj = {
name: "Oliver",
friends: ["alice","troy"],
sayWindowFriends: function(){
return function(){
return this.
sayFriends: function(){
var outer =
return function(){
return function(){
return function(){
return outer.friends
console.log(obj.sayWindowFriends()()); //"window's friends"
console.log(obj.sayFriends()()()()); //["alice", "troy"]
再举个例子:
var obj = {
name: "Oliver",
friends: ["alice","troy"],
sayFriends: function(i){
var outer =
return function(j){
return outer.friends[i] + outer.friends[j];
console.log(obj.sayFriends(0)(1)); //alicetroy
另外,在几种特殊情况下,this 的值可能会发生改变。如:
var name = "the window";
var obj = {
name: "my object",
getName: function(){
return this.
console.log(obj.getName()); //my object
console.log((obj.getName)()); //my object 与上面的是相同的,多了个括号而已
console.log((obj.getName = obj.getName)()); //the window
只要不用下面两种方式调用函数即可。
经过上面的一番折腾,最明显的就是window.name 一直占用内存,无法清空。必须手动把它清理掉,用window.name = null来操作。
你可能感兴趣的文章
13 收藏,518
4 收藏,166
36 收藏,4.1k
本文采用 ,分享、演绎需署名且使用相同方式共享,不能用于商业目的。
本文隶属于专栏
前端和PHP学习笔记
分享到微博?
与我们一起探索更多的未知
专业的开发者技术社区,为用户提供多样化的线上知识交流,丰富的线下活动及给力的工作机会
我要举报该,理由是:
扫扫下载 App
SegmentFault
一起探索更多未知

我要回帖

更多关于 js 递归 的文章

 

随机推荐