美文网首页
严格模式之caller callee..

严格模式之caller callee..

作者: 天外来人 | 来源:发表于2016-04-22 07:58 被阅读1195次

arguments.callee 从 ES5 严格模式中被移除掉的一个主要原因是递归调用会获取到一个不同的 this值,如:

var global = this;
var sillyFunction = function (recursed) {
  if (!recursed) {
    return arguments.callee(true);
 } 
  if (this !== global) { 
    alert("This is: " + this); 
  } else { 
    alert("This is the global"); 
  }
}
sillyFunction();

另外一个被废弃的特性是 arguments.callee.caller,具体点说则是 Function.caller。为什么? 额,在任何一个时间点,你能在堆栈中找到任何函数的最深层的调用者,也正如我在上面提到的,在调用堆栈有一个单一重大影响:不可能做大量的优化,或者有更多更多的困难。比如,如果你不能保证一个函数 f 不会调用一个未知函数,它就绝不可能是内联函数 f。基本上这意味着内联代码中积累了大量防卫代码:

function f (a, b, c, d, e) { return a ? b * c : d * e; }

如果JavaScript解释器不能保证所有提供的参数数量在被调用的时候都存在,那么它需要在行内代码插入检查,或者不能内联这个函数。现在在这个特殊例子里一个智能的解释器应该能重排检查而更优,并检查任何将不用到的值。然而在许多的情况里那是不可能的,也因此它不能够内联。

安全问题:
可以利用这个属性来得到当前调用栈的信息:

function getCallStack() {  
    var stack = [];  
    for (var f = getCallStack.caller; f; f = f.caller) {  
        stack.push(f);  
    }  
    return stack;  
}  

对于简单的调用关系,上述确实能够得到调用栈的信息:

function f1() {  
    return getCallStack();  
}  
function f2() {  
    return f1();  
}  
var trace = f2();  
trace; // [f1, f2]  

但是当一个函数在调用栈中出现不止一次时,就会发生问题了,比如下面的代码会产生一个死循环:

function f(n) {  
    return n === 0 ? getCallStack() : f(n - 1);  
}  
var trace = f(1); // infinite loop  

原因在于,当发生递归调用时,函数自身会被赋值给它的caller属性。因此getCallStack中的for循环的终止条件f永远不会为false:

for (var f = getCallStack.caller; f; f = f.caller) {  
    stack.push(f);  
}  

参考文献:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/arguments/callee#为什么arguments.calleeES5严格模式中移除掉
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Strict_mode
https://github.com/airbnb/javascript/issues/52

相关文章

  • 严格模式之caller callee..

    arguments.callee 从 ES5 严格模式中被移除掉的一个主要原因是递归调用会获取到一个不同的 thi...

  • callee和caller的使用

    callee的使用 在严格模式下caller,callee以及arguments都是不能使用的,会报错 calle...

  • 严格模式和非严格模式下的Function.caller

    最近一个活动项目中,在IOS的浏览器中会必现一个bug, 这个bug的起因是,我们在一个vue开发的项目中,通过s...

  • 面向对象-严格模式、作用域

    严格模式 js有两中开发模式:非严格模式(默认)+严格模式(“ues strict”) 严格模式:会进行更严格的代...

  • JavaScript this

    全局下this 非严格模式/严格模式 window 函数内this 非严格模式 window 严格模式 undef...

  • JavaScript 中的 this 关键字

    与其他语言相比,函数的 this 关键字在 JavaScript 中的表现略有不同,此外,在严格模式和非严格模式之...

  • JS基础知识-this

    与其他语言相比,函数的 this 关键字在 JavaScript 中的表现略有不同,此外,在严格模式和非严格模式之...

  • 开发中的严格模式

    js中有严格模式和非严格模式两种运行环境 在开发中,有非严格模式和严格模式2种开发模式 在严格模式下,会做更加严格...

  • 严格模式和非严格模式

    es6添加了严格模式("use strict")主要作用: 1.严格模式通过抛出错误来消除一些原有的静默错误。 2...

  • JS基本类型和变量

    严格模式 ECMAScripr5引入了严格模式。启用严格模式可以在顶部添加: “use strict” 严格模式下...

网友评论

      本文标题:严格模式之caller callee..

      本文链接:https://www.haomeiwen.com/subject/yrztrttx.html