注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

网易邮箱前端技术中心

汇聚最新最劲爆的前端技术

 
 
 

日志

 
 
 
 

避免使用arguments.callee  

2013-10-24 01:30:42|  分类: javascript |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
近期在项目中使用jsHint,偶然发现代码中包含arguments.callee会无法通过验证。如此“高级”的特性不让用,大大降低代码的骚劲!深入了解了一番才知道其中另有乾坤。
正在执行的函数体中arguments对象的callee属性指向该函数本身,可以用来在函数体中调用函数本身,常见的递归调用:

function fFactorial (nNum) {
if (nNum <= 1) {
return 1;
}
return nNum * arguments.callee(nNum - 1); 

// nNum * fFactorial(nNum - 1);

}

其实,这种情况下可以直接使用函数名调用fFactorial函数,而在js中使用匿名函数则无法获知函数名,arguments.callee似乎成了不二之选:

fShowResult(10, function (nNum) {
if (nNum <= 1) {
return 1;
}
return nNum * arguments.callee(nNum - 1);
});

function fShowResult(nNum, fFunc) {
alert(fFunc(nNum));
}

问题来了,arguments.callee这个奇怪的东西之所以存在是因为早期版本的Javascript表达式中只能出现匿名函数,因而无法使用函数名进行递归调用。另外这种方式除了性能较差,在调用中this的值是不同的,有潜在的风险。

var oWin = this;
fCheckThis(false);
function fCheckThis(bStop) {
if (!bStop) {
return arguments.callee(true);
}
alert(this === oWin);
}
Result : false

好在ECMAScript 3提供了解决方案:表达式中函数可以有自己的名字

fShowResult(10, function fFactorial(nNum) {
if (nNum <= 1) {
return 1;
}
return nNum * fFactorial(nNum - 1);
});

function fShowResult(nNum, fFunc) {
alert(fFunc(nNum));
}

这样一来可以像普通函数一样通过函数名来进行递归调用,没有性能问题,this的值也没有发生改变。看起来匿名函数被“招安”了,但这个特殊的函数名不会污染全局或其他的命名空间,坚守着“匿名”的底线。
最后,以下这种情况,arguments.callee是无法被取代的:

function fCreate(sName){
var Cat = new Function('return "My name is " + arguments.callee.name;');
Cat.name = sName
return Cat;
}

alert(fCreate('Jack')());

Cat执行时的作用域是window而无法访问Cat声明时的作用域。
所以,尽量避免使用arguments.callee吧,给你的匿名函数起个好听的名字!


by Shaotu
  评论这张
 
阅读(876)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017