如何获取调用者函数类名

时间:2015-05-11 08:11:10

标签: javascript

我尝试了一些事情,它满足了80%的需求,但还不够用。

// Different file
function A(){}

A.prototype.ao = function(){
    // Here I want ot know the fucntion caller class name, for that I used
    arguments.callee.caller.prototype; // It retuens B.bo {} (object)
}

// Different file
function B(){}
B.prototype.bo = function(){
    var a = new A();
    a.ao();
}

如何从调用者原型中检索类名,因为它是object类型。

如果我们能够获得调用者函数上下文,我会更有帮助。

2 个答案:

答案 0 :(得分:3)

  

如何从调用者原型

中检索类名

你不能*,原因有两个:

  1. 函数没有name属性。 They will in ES6,但他们还没有。 (不过,您可以使用名称为B分配属性。)

  2. 虽然你可以获得B.prototype.bo上的函数的引用,但是没有从那里回到B的链接。联系是单向的。 (尤其是因为相同的功能可以在多个对象上。)

  3. 请注意,使用arguments.callee 强烈建议不要,并且在严格模式下禁止使用caller,并且不鼓励使用A.prototype.ao = function(){ try { throw new Error(); } catch (e) { // Examine e.stack here } }; 特别。几乎总有一种更好的方法来做你想要做的事情。

    *在某些引擎上,您可以从调用堆栈中找出它,例如:

    B

    您将依赖特定于平台的命名等。

    但同样,几乎肯定有一个更好的选择,而不是试图知道谁在打电话给你。

    重新评论:

      

    这里我的要求是跟踪API函数的使用情况,为了实现它我遵循这种方式......而且我不能改变现有的框架。

    你可能会但却没有意识到,因为JavaScript强大 。 : - )

    例如:一旦在页面上加载任何框架创建B.prototype,这里的代码将用function wrapFunctions(name, proto) { Object.keys(proto).forEach(function(key) { var original = proto[key]; if (typeof original === "function") { proto[key] = function() { var rv; starting(name, key); // <=== Your function to tracking the start of a call rv = original.apply(this, arguments); stopping(name, key); // <=== Your function tracking the end of the call return rv; }; } }); } wrapFunctions("B", B.prototype); 上的每个函数包装一个告诉你它正在运行的版本:

    // The framework
    function B() {}
    B.prototype.f1 = function() {
      snippet.log("Original functionality for f1");
    };
    B.prototype.f2 = function() {
      snippet.log("Original functionality for f2");
    };
    B.prototype.f3 = function() {
      snippet.log("Original functionality for f3 -- calling f2");
      this.f2();
      snippet.log("Original functionality for f3 -- done calling f2");
    };
    
    // Let's use f1 and f2 before we wrap them
    snippet.log("Before wrapping:");
    var b1 = new B();
    b1.f1();
    b1.f2();
    b1.f3();
    
    // Now your code runs and wraps them
    wrapFunctions("B", B.prototype);
    
    // Now let's use f1 and f2 again
    snippet.log("After wrapping:");
    var b2 = new B();
    b2.f1();
    b2.f2();
    b1.f3();
    
    // Our function to track that a call started
    function starting(ctor, name) {
      snippet.log(ctor + "#" + name + ": Started");
    }
    
    // Our function to track that a call stopped
    function stopping(ctor, name) {
      snippet.log(ctor + "#" + name + ": Stopped");
    }
    
    // Our function to wrap things
    function wrapFunctions(name, proto) {
      Object.keys(proto).forEach(function(key) {
        var original = proto[key];
        if (typeof original === "function") {
          proto[key] = function() {
            var rv;
            starting(name, key); // <=== Your function to tracking the start of a call
            rv = original.apply(this, arguments);
            stopping(name, key); // <=== Your function tracking the end of the call
            return rv;
          };
        }
      });
    }

    这是“仪器仪表”的开始。但请注意,有适当的库可以解决边缘情况等问题。

    直播示例

    <!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
    <script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
    {{1}}

答案 1 :(得分:0)

您可以在返回其类型的对象中包含一个方法。另一个选择是使用instanceof并检查所有可能的类型。

function A() {
    this.getType = function () {
        return "A";
    }
}

A.prototype.ao = function() {
    // Here I want ot know the fucntion caller class name, for that I used
    var type = this.getType();
    args.callee.caller.prototype; // It retuens B.bo {} (object)
}

function B(){
    this.getType = function () {
        return "B";
    }
}

B.prototype.bo = function(){
    var a = new A();
    a.ao.apply(this);
}

在这里,您还必须在所有继承的类型中重新定义getType并返回正确的类型。您还需要使用apply(this)调用所需的方法来提供当前调用者的上下文。