How to dynamically set a function/object name in Javascript as it is displayed in Chrome

前端 未结 11 1458
萌比男神i
萌比男神i 2020-11-28 07:21

This is something which has been bugging me with the Google Chrome debugger and I was wondering if there was a way to solve it.

I\'m working on a large Javascript ap

相关标签:
11条回答
  • 2020-11-28 07:46

    Similar to @Piercey4 answer, but I had to set the name for the instance as well:

    function generateConstructor(newName) {
      function F() {
        // This is important:
        this.name = newName;
      };
    
      Object.defineProperty(F, 'name', {
        value: newName,
        writable: false
      });
    
      return F;
    }
    
    const MyFunc = generateConstructor('MyFunc');
    const instance = new MyFunc();
    
    console.log(MyFunc.name); // prints 'MyFunc'
    console.log(instance.name); // prints 'MyFunc'
    
    0 讨论(0)
  • 2020-11-28 07:49

    This won't totally solve your problem, but I would suggest overriding the toString method on the class's prototype. For instance:

    my_class = function () {}
    my_class.prototype.toString = function () { return 'Name of Class'; }
    

    You'll still see the original class name if you enter an instance of my_class directly in the console (I don't think it's possible to do anything about this), but you'll get the nice name in error messages, which I find very helpful. For instance:

    a = new my_class()
    a.does_not_exist()
    

    Will give the error message: "TypeError: Object Name of Class has no method 'does_not_exist'"

    0 讨论(0)
  • 2020-11-28 07:54

    If you want to dynamically create a named function. You can use new Function to create your named function.

    function getMutableCopy(fnName,proto) {
        var f = new Function(`function ${fnName}(){}; return ${fnName}`)()
        f.prototype = proto;
        return new f();
    }
    
    getMutableCopy("bar",{}) 
    // ▶ bar{}
    
    0 讨论(0)
  • 2020-11-28 07:56
    Object.defineProperty(fn, "name", { value: "New Name" });
    

    Will do the trick and is the most performant solution. No eval either.

    0 讨论(0)
  • 2020-11-28 07:56

    Based on the answer of @josh, this prints in a console REPL, shows in console.log and shows in the debugger tooltip:

    var fn = function() { 
       return 1917; 
    };
    fn.oldToString = fn.toString; 
    fn.toString = function() { 
       return "That fine function I wrote recently: " + this.oldToString(); 
    };
    var that = fn;
    console.log(that);
    

    Inclusion of fn.oldToString() is a magic which makes it work. If I exclude it, nothing works any more.

    0 讨论(0)
  • 2020-11-28 08:01

    Although it is ugly, you could cheat via eval():

    function copy(parent, name){
      name = typeof name==='undefined'?'Foobar':name;
      var f = eval('function '+name+'(){};'+name);
      f.prototype = parent;
      return new f();
    }
    
    var parent = {a:50};
    var child = copy(parent, 'MyName');
    console.log(child); // Shows 'MyName' in Chrome console.
    

    Beware: You can only use names which would be valid as function names!

    Addendum: To avoid evaling on every object instantiation, use a cache:

    function Cache(fallback){
      var cache = {};
    
      this.get = function(id){
        if (!cache.hasOwnProperty(id)){
          cache[id] = fallback.apply(null, Array.prototype.slice.call(arguments, 1));
        }
        return cache[id];
      }
    }
    
    var copy = (function(){
      var cache = new Cache(createPrototypedFunction);
    
      function createPrototypedFunction(parent, name){
        var f = eval('function '+name+'(){};'+name);
        f.prototype = parent;
        return f;
      }
    
      return function(parent, name){
        return new (cache.get(name, parent, typeof name==='undefined'?'Foobar':name));
      };
    })();
    
    0 讨论(0)
提交回复
热议问题