admin管理员组

文章数量:1400108

I tried some thing following, it fullfils 80% of the need though not enough to use.

// 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();
}

How to retrieve the class name from caller prototype, as it is of type object.

I would be more helpful, if we able to get the caller function context.

I tried some thing following, it fullfils 80% of the need though not enough to use.

// 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();
}

How to retrieve the class name from caller prototype, as it is of type object.

I would be more helpful, if we able to get the caller function context.

Share Improve this question edited May 11, 2015 at 8:21 T.J. Crowder 1.1m200 gold badges2k silver badges1.9k bronze badges asked May 11, 2015 at 8:11 kalkikalki 4951 gold badge7 silver badges16 bronze badges 1
  • 1 This is almost certainly the X/Y problem: You want to do X, and you think you can do that by doing Y, but you're having trouble doing Y and so asked how to do it. But if we knew what X was, we could almost certainly suggest a better way than Y. – T.J. Crowder Commented May 11, 2015 at 8:21
Add a ment  | 

2 Answers 2

Reset to default 4

How to retrive the class name from caller prototype

You can't*, for a couple of reasons:

  1. Functions don't have a name property. They will in ES6, but they don't yet. (You could assign a property to B with the name, though.)

  2. Although you can get a reference to the function that's on B.prototype.bo, there's no link from there back to B. The linkage is one-way. (Not least because the same function could be on multiple objects.)

Note that using arguments.callee is strongly discouraged, and disallowed in strict mode, and using caller is especially discouraged. There's almost always a better way to do what you're trying to do.


* On some engines, you might be able to figure it out from the call stack, e.g.:

A.prototype.ao = function(){
    try {
        throw new Error();
    }
    catch (e) {
        // Examine e.stack here
    }
};

You'd be relying on platform-specific naming and such.

But again, there's almost certainly a better option than trying to know who's calling you.


Re your ment:

Here my requirement is to track an API function usage, in order to achieve it I am following this way...And further I can't change the existed framework.

You probably can but don't realize it, because JavaScript is that powerful. :-)

For instance: Once whatever framework creates B is loaded on the page, here's code that will wrap every function on B.prototype with a version that tells you it's running:

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);

That's the beginning of "instrumentation." But note that there are proper libraries out there for this that have solved the edge cases and such.

Live Example:

// 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./a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

You can include a method in the object which returns its type. Another option is to use instanceof and check for all possible types.

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);
}

Here you will also have to redefine getType in all of your inherited types and return the correct type. You also need to invoke the desired method with apply(this) to provide the context of the current caller.

本文标签: javascriptHow to get caller function class nameStack Overflow