如何在严格模式下获取调用者?

22

可以混合使用严格和非严格代码。但即使调用不在严格代码中,也不能使用caller。有人知道任何解决方法吗?

我尝试过这个:

(function strict(){
    "use strict";
    nonStrict();//ok
    nonStrictCaller();//error :(
})();

function nonStrict(){
    return 011;//Octal literals are not allowed in strict mode
}

function nonStrictCaller(){
    return nonStrictCaller.caller;
}

1
你可以把 this 传递给函数,对吧? - gdoron
我认为你可能想在这里看看,特别是评论区:https://dev59.com/NnVC5IYBdhLWcg3weBE-#280396 - Joseph
解决方法是使您的代码符合严格模式。这就是严格模式的目的; 它是严格的。在您的情况下,这意味着通过其他方式使调用者可访问,例如通过名称作为参数传递它。 - user1106925
@amnotiam 我正在编写框架,需要调用者在原型中的方法中访问实现私有和受保护的属性。 - Quadroid
2
如果这是你的方法,那么你的框架在严格模式下是行不通的。你是否正在使用caller属性来验证某个方法是否是从一个原型方法中调用的?或者类似的方式? - user1106925
如果"use strict"破坏了不在其范围内的代码,那么"use strict"有什么作用呢? - AndreKR
1个回答

12

这是一个只在V8中有效的邪恶黑客技巧。 140字节 版本:

function x(a,b,c){function d(e,f){d=f}c=(b=Error)[a='prepareStackTrace'];b.captureStackTrace(b[a]=d,x);d.stack;b[a]=c;return d}

还有不那么神秘的版本

if ('captureStackTrace' in Error) {
  void function(){
    function prepare(e, callsites){
      return callsites;
    }

    function stack(f){
      var e = {};
      var oldPrepare = Error.prepareStackTrace;
      Error.prepareStackTrace = prepare;
      Error.captureStackTrace(e, f || stack.caller);
      e = e.stack;
      Error.prepareStackTrace = oldPrepare;
      return e;
    }

    function lastReceiver(){
      return stack(lastReceiver)[2].receiver;
    }

    var CallSite = stack()[0].constructor;
    var callsiteMethods = {};

    Object.getOwnPropertyNames(CallSite.prototype).forEach(function(key){
      if (/^is|^get/.test(key)) {
        callsiteMethods[key.replace(/^is|^get/, '')] = CallSite.prototype[key];
      }
      callsiteMethods.location = CallSite.prototype.toString;
    });

    CallSite.prototype.resolve = function resolve(){
      for (var k in callsiteMethods)
        this[k] = callsiteMethods[k].call(this);
    }

  }();
}

3
这似乎不再在Chrome中起作用了。 :-\ 例如:http://jsbin.com/zifadipivo/12/?v8Hack=true - James M. Greene

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接