Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replicating arguments.callee in strict mode

I'm working in strict mode for the first time and, what-d'ya-know, it's also the first time in ages being able to use a non strict mode property would be useful. My question here outlines the exact problem I'm having, but the solution I've worked out could be adapted to something a lot more scaleable if I still had access to arguments.callee.

Without naming the function is there any way in strict mode that I can get a reference to the function whose scope I'm currently within?

like image 206
wheresrhys Avatar asked Apr 04 '12 10:04

wheresrhys


People also ask

What is not allowed in strict mode?

Not Allowed in Strict Mode Objects are variables too. Deleting a variable (or object) is not allowed. Deleting a function is not allowed. For security reasons, eval() is not allowed to create variables in the scope from which it was called.

What is arguments callee name?

callee is a property of the arguments object. It can be used to refer to the currently executing function inside the function body of that function. This is useful when the name of the function is unknown, such as within a function expression with no name (also called "anonymous functions").

Does strict mode improve performance?

The strict mode is not really about performance, it a strict variant of the language, its main goal is to avoid what are considered to be error-prone features.

When would you not use strict mode?

If you have such an unrestrictedly typed code, that is used variables without declaring. One variable declared within some function/scope and used from somewhere else(it will be undeclared there) and you can't rewrite/change them, then you should not go for "use strict;" mode because it will break the code.


2 Answers

Without naming the function is there any way in strict mode that I can get a reference to the function whose scope I'm currently within?

In 2012 when this answer was originally written, there were implementation bugs with the named function expressions you were using in your linked solution. There aren't now, it's been years since browsers with those bugs were still in significant circulation. So here in a (very) post-IE8 world, your named function expression approach is just fine:

UsageGraph = Graph.extend({
   generateScale: function GS() {
       var parentMethod = this.constructor._super.generateScale;
       if(parentMethod === GS) {
           parentMethod = this.constructor._super.constructor._super.generateScale;
       }
       parentMethod.call(this); // run the parent's method
       //do additional stuff
   }
});

But the question asks if you can avoid having a name. In 2012, my solution if you really didn't want the function to have a name was to assign an anonymous function to a variable:

UsageGraph = Graph.extend(function(){
   var GS = function() {
       var parentMethod = this.constructor._super.generateScale;
       if(parentMethod === GS) {
           parentMethod = this.constructor._super.constructor._super.generateScale;
       }
       parentMethod.call(this); // run the parent's method
       //do additional stuff
   };

   return {generateScale: GS};
}());

But that doesn't work anymore; since ES2015, even that function has a name, inferred from the name of the variable it's assigned to:

var GS = function() { };
console.log(GS.name); // "GS"

If you really don't want it to have a name, it's possible to avoid it, but you have to make an effort to defeat the automatic naming defined by the specification, for instance by making the function the return value of another function:

var GS = (() => function() { })();
console.log(GS.name); // ""

So if avoiding the name is important, you'd do something like this:

UsageGraph = Graph.extend(function(){
   const generateScale = (() => function() {
       let parentMethod = this.constructor._super.generateScale;
       if(parentMethod === generateScale) {
           parentMethod = this.constructor._super.constructor._super.generateScale;
       }
       parentMethod.call(this); // run the parent's method
       //do additional stuff
   })();

   return {generateScale};
}());
like image 120
T.J. Crowder Avatar answered Oct 20 '22 03:10

T.J. Crowder


Yes, but no... I'm not sure if this is the same manner of "naming" that you speak of:

var foo = function bob() {
    // call bob();
}

// bob is undeclared; here it's foo!

http://jsfiddle.net/4y8pY/

like image 40
Matt Avatar answered Oct 20 '22 03:10

Matt