0

One of the many fascinating things about JavaScript is that functions are actually objects, and they can be constructed a number of ways, one of which is using its constructor directly:

var func = new Function( "arg1" , "arg2" , "arg3" , "function_body" );

Considering that it is a javascript object, I assume that I could attach a property to the object:

func.propertyA = "whatever I want this to be";

So with that in consideration, how would I reference the property within the function?

Like this for clarity (this doesn't work):

var func = new Function( "arg1" , "arg2" , "arg3" , "alert( func.propertyA );" );
func.propertyA = "hello world";
func();

This is supposed to alert "hello world."

When you run this script in JSFiddle, you get an error in the console instead saying that "func" is undefined.

  • which property you want to refer? – brk Oct 21 '16 at 05:05
  • Did you try `func.propertyA` ? – Rayon Oct 21 '16 at 05:06
  • @Rayon doesn't work as expected [run this JSfiddle here and check console](https://jsfiddle.net/4zqprzb0/) –  Oct 21 '16 at 05:07
  • @DaMaxContent — I could see `"whatever I want this to be"` in console.. – Rayon Oct 21 '16 at 05:08
  • @Rayon ...I'm speechless... did you even read the function body argument in `new Function()` in the fiddle I made and what the function was supposed to do. –  Oct 21 '16 at 05:09
  • smh. what was supposed to happen was there was supposed to be an alert "hello world." Didn't happen, because `func` is undefined within `func` –  Oct 21 '16 at 05:11
  • @DaMaxContent Your fiddle doesn't work because `func` isn't in scope. If you made it global by deleting the `var` keyword in front of it, it would work: https://jsfiddle.net/4zqprzb0/1/ – Paul Oct 21 '16 at 05:19
  • @Paulpro Ok, now I'm confused. How in the world did that fix it? –  Oct 21 '16 at 05:20
  • 1
    Doesn't matter whether you use it from a normal function definition or from the `new Function` (which you really shouldn't be doing), you can get the current function from `arguments.callee` (which you also probably shouldn't be doing). – Amadan Oct 21 '16 at 05:20
  • 1
    I don't see why you would want to do that for a function like that, but it is fairly common to assign properties to functions that are to be used as constructors. Properties on a constructor act similarly to static/class variables in other languages. – Paul Oct 21 '16 at 05:21
  • @DaMaxContent The function constructor constructs a function in a new context, not in the current context, so it doesn't have access to local variables, like `func`, but it can access globals. Your code doesn't work for the same reason that this doesn't work: https://jsfiddle.net/yyqs55wp/ – Paul Oct 21 '16 at 05:23
  • @Paulpro — Could you explain why __`var func = 'Hi..'; var a = new Function("arg1", "arg2", "arg3", "debugger;alert(func)"); a();`__ is failing ? `func` is in global-scope in this example.. – Rayon Oct 21 '16 at 05:24
  • 2
    @Rayon It's not in the global scope if it's in the JavaScript section of a JsFiddle (by default), since JsFiddle runs your script in a `window.onload` callback function (by default). If you pasted that whole thing into your console directly it would work, or if you clicked the gear in JsFiddle and changed it to one of the "No wrap" options. – Paul Oct 21 '16 at 05:26
  • @Paulpro Trust me. I don't believe you will see this issue common either. However, I am working on a JavaScript-based AI, and one thing it does is creates functions with properties that all reference one object. The reason I chose to do it this way is that this is the only way I want the object to be referenced. Meaning, without accessing the properties on the functions, there is no way to reference the object. It helps keep my code cleaner –  Oct 21 '16 at 05:26
  • @Paulpro — "_Functions created with the Function constructor do not create closures to their creation contexts; they always are created in the global scope. When running them, they will only be able to access their own local variables and global ones, not the ones from the scope in which the Function constructor was called._"[[Ref](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function#Difference_between_Function_constructor_and_function_declaration)] made me understand things :) Thank you! – Rayon Oct 21 '16 at 05:28
  • @DaMaxContent I don't know the particulars of what you're dealing with, so I can't say for sure, but there may be a nicer solution (one that avoids unnecessary globals), EG. using the module pattern to declare a variable containing the object that the functions can all access. Something like this: https://jsfiddle.net/e0sejo09/1/ – Paul Oct 21 '16 at 05:38
  • @Rayon No problem! – Paul Oct 21 '16 at 05:50

1 Answers1

0

I really don't recommend doing this, but there is a way.

When you set a value on a function object it could be reached of this is bound correctly. When dealing with a function, as opposed to a method, the simplest way to assign this is to use <function>.bind or function.call/function.apply

// Not all JavaScript engines support multiple arguments to new Function

var func1 = new Function( "console.log(this.prop1)" );
func1.prop1 = "Test prop";

func1();

// Bind `this` properly
func2 = func1.bind(func1);
func2();

// Or use apply
func1.apply(func1);
Jeremy J Starcher
  • 23,369
  • 6
  • 54
  • 74