5

In Javascript, is there a way to create a function from a string (such as through the new Function() constructor) and have it inherit the parent scope? For example:

(function(){
    function yay(){
    }
    var blah = "super yay"
    yay.prototype.testy = new Function("alert(blah)")
    yay.prototype.hello = function(){alert(blah)}
    whee = new yay();
    whee.hello()
    whee.testy()
})()

Is there any way to make whee.testy() also alert "super yay"?

antimatter15
  • 1,436
  • 1
  • 12
  • 18

6 Answers6

1

Actually, combining function and eval should do what you want:

// blah exists inside the 'hello' function
yay.prototype.hello = function(){ alert(blah) }
// blah also exists inside the 'testy' function, and
// is therefore accessible to eval().
yay.prototype.testy = function(){ eval('alert(blah)') }
levik
  • 114,835
  • 27
  • 73
  • 90
  • But the OP must be **very** sure that the string doesn't contain any malicious code. I'm interested in the way the string is assigned its value. – Marcel Korpel Feb 18 '10 at 13:24
  • 10
    Yes, yes... eval is evil and all that. Judging by the way OP created the anonymous function around his code, it's not his first day doing JS. – levik Feb 18 '10 at 20:58
  • I'm just using eval/Function to better compress some code, it's not stuff which is user-inputted, but I just have some code where there are lots of functions with very little code inside, function(e){var t=this;return e(t)?[t]:[]} and there's a substantial amount of bytes being used up with the function(e){var t=this;return}. – antimatter15 Feb 19 '10 at 21:02
  • LOL... +1 to your comment - I like the way you responded to the typical "eval is evil" advice – user266803 Feb 20 '10 at 16:24
1
(function(){
    function yay(){
    }
    var blah = "super yay"
    yay.prototype.testy = eval("(function(){alert(blah)})")//new Function("alert(blah)")
    yay.prototype.hello = function(){alert(blah)}
    whee = new yay();
    whee.hello()
    whee.testy()
})()

This seems to work for me, and none of the eval'd data is from any untrusted source. It's just to be used for minifying code.

antimatter15
  • 1,436
  • 1
  • 12
  • 18
1

This should give you what you want...

var inputAction = "alert(blah)";
yay.prototype.testy = eval("(function(){ " + inputAction + "; })")

It basically wraps your intended action inside an anonymous function, this gets fully evaluated on the eval, but isn't run right away, it's wrapped into a function.

You can go a little farther here, but without knowing what you want to accomplish it's hard to say.

Tracker1
  • 19,103
  • 12
  • 80
  • 106
0

The reason why whee.testy doesn't work is because declaring a function using new Function("alert(blah)") creates the function outside the current closure. Since blah is defined inside your closure, you do not have access to it, and it throws an undefined error.

Here is a proof of concept example:

var blah = "global (window) scope";

(function(){
    function yay(){
    }
    var blah = "closure scope";

    yay.prototype.testy = new Function("alert(blah)");
    yay.prototype.hello = function(){ alert(blah); }
    whee = new yay();
    whee.hello();
    whee.testy();
})();
Andrew Moore
  • 93,497
  • 30
  • 163
  • 175
-1

You mean eval?

(function(){
    function yay(){
    }
    var blah = "super yay"
    yay.prototype.testy = new Function(eval("alert(blah)")) // <---------------
    yay.prototype.hello = function(){alert(blah)}
    whee = new yay();
    whee.hello()
    whee.testy()
})()

However there are two morally objectionable feature of JS here. 1) eval is "evil", and 2) the code inside the eval can see the variables outside.

Jarne Cook
  • 183
  • 1
  • 5
  • `eval` is **evil**! Don't use it! Don't! – Marcel Korpel Feb 18 '10 at 03:23
  • And here's a better explanation why not to use eval: http://stackoverflow.com/questions/197769/when-is-javascripts-eval-not-evil/198031#198031 – Marcel Korpel Feb 18 '10 at 03:31
  • Like I said: morally objectionable – Jarne Cook Feb 18 '10 at 04:25
  • new Function(str) and eval(str) are practically identical. The way OP uses new Function() is correct - you don't need eval there. – levik Feb 18 '10 at 04:35
  • 1
    Here, I don't think doing new Function(eval("alert(blah)") works. There, alert(blah) is being executed immediately rather than when the function is called. Function and eval aren't exactly identical, and here is a case where it's different. Functions don't get access to the local variables of the scope they were created in, while eval does. – antimatter15 Feb 19 '10 at 21:09
  • @antimatter15 You are correct. Function(eval("alert(blah)") is executed immediately. eval("(Function(...))"); ... very tricky – Jarne Cook Feb 21 '10 at 22:21
-1

You don't need eval.

You have to concatenate the blah to the string function but JavaScript will complain that there is no ";" just before the concatenation this is because blah is just some text when you concatenate it. You have to escape two "\"" around the variable blah in order to make it look like a string with text in it.

(function(){
    function yay(){
    }
 var blah = "super yay"

 yay.prototype.testy = new Function("alert(\""+blah+"\")")
 yay.prototype.hello = function(){alert(blah)}
 whee = new yay();
 whee.hello()
 whee.testy()
})()

This will alert "super yay" two times!

Jonathan Czitkovics
  • 1,642
  • 11
  • 11