开发者

Naming an anonymous function

开发者 https://www.devze.com 2023-01-18 20:07 出处:网络
Is it possible to somehow set a name for anonymous functions? There is no need to add function names to the namespace for anonymous functions but I would like to avoid seeing a large amount of (?) in

Is it possible to somehow set a name for anonymous functions?

There is no need to add function names to the namespace for anonymous functions but I would like to avoid seeing a large amount of (?) in my javascript debugger so I can keep the call stack trace informative.

Also can I safely pass normal declared functions as arguments instead of anonymous functions or will I walk into some strange errors. It seems to work.

$("object").bind("click", function() { alert("x"); });

$("object").bind("click", function debuggingName() { alert("x"); });

[Edit]

I meant something along the likes of

$("object").bind("click"开发者_Python百科, function() { Function.Name = "debuggingName"; alert("x"); });


Your second example is using a named function expression, which works fine in most browsers but has some problems in IE that you should be aware of before using it. I recommend reading kangax's excellent article on this subject.


You could do something like this with arrow functions, it works for me on Node.

const createTask = ([name, type = 'default']) => {
  const fn = () => { ... }

  Object.defineProperty(fn, 'name', {
    value: name,
    configurable: true,
  })

  return fn
}

MDN is somewhat misleading here:

You cannot change the name of a function, this property is read-only...

To change it, you could use Object.defineProperty() though.

This answer provides more details.


With ECMAScript2015 (ES2015, ES6) language specification, it is possible to do without the use of slow and unsafe eval function and without Object.defineProperty method which both corrupts function object and does not work in some crucial aspects anyway.

See, for example, this nameAndSelfBind function that is able to both name anonymous functions and renaming named functions, as well as binding their own bodies to themselves as this and storing references to processed functions to be used in an outer scope (JSFiddle):

(function()
{
  // an optional constant to store references to all named and bound functions:
  const arrayOfFormerlyAnonymousFunctions = [],
        removeEventListenerAfterDelay = 3000; // an auxiliary variable for setTimeout

  // this function both names argument function and makes it self-aware,
  // binding it to itself; useful e.g. for event listeners which then will be able
  // self-remove from within an anonymous functions they use as callbacks:
  function nameAndSelfBind(functionToNameAndSelfBind,
                           name = 'namedAndBoundFunction', // optional
                           outerScopeReference)            // optional
  {
    const functionAsObject = {
                                [name]()
                                {
                                  return binder(...arguments);
                                }
                             },
          namedAndBoundFunction = functionAsObject[name];

    // if no arbitrary-naming functionality is required, then the constants above are
    // not needed, and the following function should be just "var namedAndBoundFunction = ":
    var binder = function() 
    { 
      return functionToNameAndSelfBind.bind(namedAndBoundFunction, ...arguments)();
    }

    // this optional functionality allows to assign the function to a outer scope variable
    // if can not be done otherwise; useful for example for the ability to remove event
    // listeners from the outer scope:
    if (typeof outerScopeReference !== 'undefined')
    {
      if (outerScopeReference instanceof Array)
      {
        outerScopeReference.push(namedAndBoundFunction);
      }
      else
      {
        outerScopeReference = namedAndBoundFunction;
      }
    }
    return namedAndBoundFunction;
  }

  // removeEventListener callback can not remove the listener if the callback is an anonymous
  // function, but thanks to the nameAndSelfBind function it is now possible; this listener
  // removes itself right after the first time being triggered:
  document.addEventListener("visibilitychange", nameAndSelfBind(function(e)
  {
    e.target.removeEventListener('visibilitychange', this, false);
    console.log('\nEvent listener 1 triggered:', e, '\nthis: ', this,
                '\n\nremoveEventListener 1 was called; if "this" value was correct, "'
                + e.type + '"" event will not listened to any more');
  }, undefined, arrayOfFormerlyAnonymousFunctions), false);

  // to prove that deanonymized functions -- even when they have the same 'namedAndBoundFunction'
  // name -- belong to different scopes and hence removing one does not mean removing another,
  // a different event listener is added:
  document.addEventListener("visibilitychange", nameAndSelfBind(function(e)
  {
    console.log('\nEvent listener 2 triggered:', e, '\nthis: ', this);
  }, undefined, arrayOfFormerlyAnonymousFunctions), false);

  // to check that arrayOfFormerlyAnonymousFunctions constant does keep a valid reference to
  // formerly anonymous callback function of one of the event listeners, an attempt to remove
  // it is made:
  setTimeout(function(delay)
  {
    document.removeEventListener('visibilitychange',
             arrayOfFormerlyAnonymousFunctions[arrayOfFormerlyAnonymousFunctions.length - 1],
             false);
    console.log('\nAfter ' + delay + 'ms, an event listener 2 was removed;  if reference in '
                + 'arrayOfFormerlyAnonymousFunctions value was correct, the event will not '
                + 'be listened to any more', arrayOfFormerlyAnonymousFunctions);
  }, removeEventListenerAfterDelay, removeEventListenerAfterDelay);
})();


I normally do: $("object").bind("click" , function name() { alert("x"); });

and don't run into any problems.

Doing so is encouraged in some of the major libraries:

https://groups.google.com/forum/m/#!topic/firebug/MgnlqZ1bzX8

http://blog.getfirebug.com/2011/04/28/naming-anonymous-javascript-functions/


If dynamic function name is the issue. You can try this:

function renameFunction(name, fn) {
    return (new Function("return function (call) { return function " + name +
       " () { return call(this, arguments) }; };")())(Function.apply.bind(fn));
} 

renameFunction('dynamicName',function() { debugger })();

source: Nate Ferrero


An anonymous function is a function without a name, it is executed from where it is defined. Alternatively, you can define the debugging function before using it.

function debuggingName() { 
    alert("x"); 
}

$("object").bind("click", debuggingName);
0

精彩评论

暂无评论...
验证码 换一张
取 消