assign a function into a variable and run itself - javascript

I have read a interested blog where this above technique is applied, i understand it will run the function itself. but what's the purpose assign to a variable, when i try to console.log the variable i get undefiend.
var test1 = (function(){
console.log('yay')
})();
console.log(test1)
what's the differnet doing this way below
(function test1(){
console.log('yay');
})();
Suggestion are appreciated. :)

The immediately invoked function expression (IIFE) in Javascript serves to introduce a closure via a new scope. This is often done to compensate for the lack of block scoping in Javascript or provide information hiding a la module pattern (seen often in jQuery plugins).
Minimal example below:
var counter = (function() {
var i = 0;
function inc() {
i++;
return i;
}
return inc;
})();
The return exposes assigns the function inc to the variable counter. Successive invocations of counter() will result in 1, 2, etc. while keeping i hidden.
This is roughly equivalent to an object oriented approach that declared i as private.

In your sample above the function is void which makes no sense to assign the function result to a variable since it is returning nothing:
However tweaking your sample a little bit:
var test1 = (function(){
console.log('yay'); return "hello";
})();
then it makes sense since test1 will return "hello".
So in your original sample there are not differences and the fact that you assign a the result of a function which is not returning values is a bit odd.

Related

JavaScript completely wrapping ()? [duplicate]

I have been reading a lot of Javascript lately and I have been noticing that the whole file is wrapped like the following in the .js files to be imported.
(function() {
...
code
...
})();
What is the reason for doing this rather than a simple set of constructor functions?
It's usually to namespace (see later) and control the visibility of member functions and/or variables. Think of it like an object definition. The technical name for it is an Immediately Invoked Function Expression (IIFE). jQuery plugins are usually written like this.
In Javascript, you can nest functions. So, the following is legal:
function outerFunction() {
function innerFunction() {
// code
}
}
Now you can call outerFunction(), but the visiblity of innerFunction() is limited to the scope of outerFunction(), meaning it is private to outerFunction(). It basically follows the same principle as variables in Javascript:
var globalVariable;
function someFunction() {
var localVariable;
}
Correspondingly:
function globalFunction() {
var localFunction1 = function() {
//I'm anonymous! But localFunction1 is a reference to me!
};
function localFunction2() {
//I'm named!
}
}
In the above scenario, you can call globalFunction() from anywhere, but you cannot call localFunction1 or localFunction2.
What you're doing when you write (function() { ... })(), is you're making the code inside the first set of parentheses a function literal (meaning the whole "object" is actually a function). After that, you're self-invoking the function (the final ()) that you just defined. So the major advantage of this as I mentioned before, is that you can have private methods/functions and properties:
(function() {
var private_var;
function private_function() {
//code
}
})();
In the first example, you would explicitly invoke globalFunction by name to run it. That is, you would just do globalFunction() to run it. But in the above example, you're not just defining a function; you're defining and invoking it in one go. This means that when the your JavaScript file is loaded, it is immediately executed. Of course, you could do:
function globalFunction() {
// code
}
globalFunction();
The behavior would largely be the same except for one significant difference: you avoid polluting the global scope when you use an IIFE (as a consequence it also means that you cannot invoke the function multiple times since it doesn't have a name, but since this function is only meant to be executed once it really isn't an issue).
The neat thing with IIFEs is that you can also define things inside and only expose the parts that you want to the outside world so (an example of namespacing so you can basically create your own library/plugin):
var myPlugin = (function() {
var private_var;
function private_function() {
}
return {
public_function1: function() {
},
public_function2: function() {
}
}
})()
Now you can call myPlugin.public_function1(), but you cannot access private_function()! So pretty similar to a class definition. To understand this better, I recommend the following links for some further reading:
Namespacing your Javascript
Private members in Javascript (by Douglas Crockford)
EDIT
I forgot to mention. In that final (), you can pass anything you want inside. For example, when you create jQuery plugins, you pass in jQuery or $ like so:
(function(jQ) { ... code ... })(jQuery)
So what you're doing here is defining a function that takes in one parameter (called jQ, a local variable, and known only to that function). Then you're self-invoking the function and passing in a parameter (also called jQuery, but this one is from the outside world and a reference to the actual jQuery itself). There is no pressing need to do this, but there are some advantages:
You can redefine a global parameter and give it a name that makes sense in the local scope.
There is a slight performance advantage since it is faster to look things up in the local scope instead of having to walk up the scope chain into the global scope.
There are benefits for compression (minification).
Earlier I described how these functions run automatically at startup, but if they run automatically who is passing in the arguments? This technique assumes that all the parameters you need are already defined as global variables. So if jQuery wasn't already defined as a global variable this example would not work. As you might guess, one things jquery.js does during its initialization is define a 'jQuery' global variable, as well as its more famous '$' global variable, which allows this code to work after jQuery has been included.
In short
Summary
In its simplest form, this technique aims to wrap code inside a function scope.
It helps decreases chances of:
clashing with other applications/libraries
polluting superior (global most likely) scope
It does not detect when the document is ready - it is not some kind of document.onload nor window.onload
It is commonly known as an Immediately Invoked Function Expression (IIFE) or Self Executing Anonymous Function.
Code Explained
var someFunction = function(){ console.log('wagwan!'); };
(function() { /* function scope starts here */
console.log('start of IIFE');
var myNumber = 4; /* number variable declaration */
var myFunction = function(){ /* function variable declaration */
console.log('formidable!');
};
var myObject = { /* object variable declaration */
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
})(); /* function scope ends */
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
In the example above, any variable defined in the function (i.e. declared using var) will be "private" and accessible within the function scope ONLY (as Vivin Paliath puts it). In other words, these variables are not visible/reachable outside the function. See live demo.
Javascript has function scoping. "Parameters and variables defined in a function are not visible outside of the function, and that a variable defined anywhere within a function is visible everywhere within the function." (from "Javascript: The Good Parts").
More details
Alternative Code
In the end, the code posted before could also be done as follows:
var someFunction = function(){ console.log('wagwan!'); };
var myMainFunction = function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
};
myMainFunction(); // I CALL "myMainFunction" FUNCTION HERE
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
See live demo.
The Roots
Iteration 1
One day, someone probably thought "there must be a way to avoid naming 'myMainFunction', since all we want is to execute it immediately."
If you go back to the basics, you find out that:
expression: something evaluating to a value. i.e. 3+11/x
statement: line(s) of code doing something BUT it does not evaluate to a value. i.e. if(){}
Similarly, function expressions evaluate to a value. And one consequence (I assume?) is that they can be immediately invoked:
var italianSayinSomething = function(){ console.log('mamamia!'); }();
So our more complex example becomes:
var someFunction = function(){ console.log('wagwan!'); };
var myMainFunction = function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
}();
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
See live demo.
Iteration 2
The next step is the thought "why have var myMainFunction = if we don't even use it!?".
The answer is simple: try removing this, such as below:
function(){ console.log('mamamia!'); }();
See live demo.
It won't work because "function declarations are not invokable".
The trick is that by removing var myMainFunction = we transformed the function expression into a function declaration. See the links in "Resources" for more details on this.
The next question is "why can't I keep it as a function expression with something other than var myMainFunction =?
The answer is "you can", and there are actually many ways you could do this: adding a +, a !, a -, or maybe wrapping in a pair of parenthesis (as it's now done by convention), and more I believe. As example:
(function(){ console.log('mamamia!'); })(); // live demo: jsbin.com/zokuwodoco/1/edit?js,console.
or
+function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wuwipiyazi/1/edit?js,console
or
-function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wejupaheva/1/edit?js,console
What does the exclamation mark do before the function?
JavaScript plus sign in front of function name
So once the relevant modification is added to what was once our "Alternative Code", we return to the exact same code as the one used in the "Code Explained" example
var someFunction = function(){ console.log('wagwan!'); };
(function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
})();
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
Read more about Expressions vs Statements:
developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Function_constructor_vs._function_declaration_vs._function_expression
Javascript: difference between a statement and an expression?
Expression Versus Statement
Demystifying Scopes
One thing one might wonder is "what happens when you do NOT define the variable 'properly' inside the function -- i.e. do a simple assignment instead?"
(function() {
var myNumber = 4; /* number variable declaration */
var myFunction = function(){ /* function variable declaration */
console.log('formidable!');
};
var myObject = { /* object variable declaration */
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
myOtherFunction = function(){ /* oops, an assignment instead of a declaration */
console.log('haha. got ya!');
};
})();
myOtherFunction(); // reachable, hence works: see in the console
window.myOtherFunction(); // works in the browser, myOtherFunction is then in the global scope
myFunction(); // unreachable, will throw an error, see in the console
See live demo.
Basically, if a variable that was not declared in its current scope is assigned a value, then "a look up the scope chain occurs until it finds the variable or hits the global scope (at which point it will create it)".
When in a browser environment (vs a server environment like nodejs) the global scope is defined by the window object. Hence we can do window.myOtherFunction().
My "Good practices" tip on this topic is to always use var when defining anything: whether it's a number, object or function, & even when in the global scope. This makes the code much simpler.
Note:
javascript does not have block scope (Update: block scope local variables added in ES6.)
javascript has only function scope & global scope (window scope in a browser environment)
Read more about Javascript Scopes:
What is the purpose of the var keyword and when to use it (or omit it)?
What is the scope of variables in JavaScript?
Resources
youtu.be/i_qE1iAmjFg?t=2m15s - Paul Irish presents the IIFE at min 2:15, do watch this!
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions
Book: Javascript, the good parts - highly recommended
youtu.be/i_qE1iAmjFg?t=4m36s - Paul Irish presents the module pattern at 4:36
Next Steps
Once you get this IIFE concept, it leads to the module pattern, which is commonly done by leveraging this IIFE pattern. Have fun :)
Javascript in a browser only really has a couple of effective scopes: function scope and global scope.
If a variable isn't in function scope, it's in global scope. And global variables are generally bad, so this is a construct to keep a library's variables to itself.
That's called a closure. It basically seals the code inside the function so that other libraries don't interfere with it. It's similar to creating a namespace in compiled languages.
Example. Suppose I write:
(function() {
var x = 2;
// do stuff with x
})();
Now other libraries cannot access the variable x I created to use in my library.
You can use function closures as data in larger expressions as well, as in this method of determining browser support for some of the html5 objects.
navigator.html5={
canvas: (function(){
var dc= document.createElement('canvas');
if(!dc.getContext) return 0;
var c= dc.getContext('2d');
return typeof c.fillText== 'function'? 2: 1;
})(),
localStorage: (function(){
return !!window.localStorage;
})(),
webworkers: (function(){
return !!window.Worker;
})(),
offline: (function(){
return !!window.applicationCache;
})()
}
In addition to keeping the variables local, one very handy use is when writing a library using a global variable, you can give it a shorter variable name to use within the library. It's often used in writing jQuery plugins, since jQuery allows you to disable the $ variable pointing to jQuery, using jQuery.noConflict(). In case it is disabled, your code can still use $ and not break if you just do:
(function($) { ...code...})(jQuery);
To avoid clash with other methods/libraries in the same window,
Avoid Global scope, make it local scope,
To make debugging faster (local scope),
JavaScript has function scope only, so it will help in compilation of codes as well.
We should also use 'use strict' in the scope function to make sure that the code should be executed in "strict mode". Sample code shown below
(function() {
'use strict';
//Your code from here
})();
Provide an example for the accepted answer, from https://requirejs.org/docs/whyamd.html:
(function () {
var $ = this.jQuery;
this.myExample = function () {};
}());
The code demonstrates that we can:
use global variables inside the scope
export functions, variables etc.. by binding on this, which is the window object as for browsers.
Its called encapsulation in OOP.

Do javascript functions need to be declared in the reverse order?

Elaboration: If I would have, for example the following code:
//Javascript example
var alice = function() {
var value = bob() + 1;
console.log value
}
var bob = function() {
var value = 1;
return value;
}
//Running function A
alice()
Would I have to declare function B first, because I am calling it in function A without reaching function B yet.
No.
If you have a function declaration, then it will be hoisted and order doesn't matter (although putting functions in an order so that a function call doesn't appear before the function being called is good practice).
If you have function expressions (as you do in your example), then you need to have the functions created before they are called, noting that in this example none of them are called before the line alice() so only that line needs to be after the functions and the order of the functions themselves doesn't matter. (But the best practise principles described above hold).
No, because the Javascript interpreter will recognize the functions declared after and link them appropriately to the line in question.
The only limitation is the definition of every function before utilization

Why Self-Executing Anonymous Functions

Today I came a cross the self executing functions, than somehow I ended up knowing about
Self-Executing Anonymous Functions, then I've read this article: http://briancrescimanno.com/how-self-executing-anonymous-functions-work/
The thing is that I don't know WHY to use Self-Executing Anonymous Functions because if I need to do something like:
var test = "a";
(function(foo) {
alert(foo);
})(test);
I could just make something like:
var test = "a";
alert(foo);
Or did I miss anything?
also this can be done to any code inside the function, but I used alert() to make simple
Update:
Even thought I've already accepted and answer I would like to share something I've found, if anyone came across this question later :)
Using this notation we can also make an endless loop like following:
(function loop(){
// do something here
loop();
)();
There are a couple of reasons why one would use an IIFE:
1) No littering
var a = 'foo';
alert(a);
vs
(function() {
var a = 'foo';
alert(a);
}())
Both examples do the same thing, but in the second example there is no a variable inside the outer scope.
2) State capturing
var a = 'foo';
window.setTimeout(function() { alert(a); }, 1);
a = 'bar';
vs
var a = 'foo';
window.setTimeout( (function(a_copy) {
return function() { alert(a_copy); }
}(a)), 1);
a = 'bar';
The first example alerts bar, while the second alerts foo. You will find this technique used especially with loops.
Your initial example isn't worth to be executed in an anonymous function, so its a bad example to understand WHY to use this technique. Here is a good example to explore state capturing:
var list = [{id: 1, data: null}, ...];
for (var i = 0; i < list.length; i++) {
(function(item) {
// start async request, for each item in the list, in the order of the list
asyncAjax("get-data-from-somewhere.json?what=" + list[i].id, function (response) {
// thats the on success callback, which gets executed when the server responded
// each item will have different response times, therefore the order of response is various
// if we would use simply list[i].data, it wouldn't work correctly, because "i" would has the value of list.length, because the iteration has been finished yet.
item.data = response;
});
})(list[i]); // the function will preserve the reference to the list item inside, until the function has been fully executed
}
When writing sync. code, you can always fallback to classic object oriented style of structering your code. So you can avoid closures / instant-anonymous function calls. But as soon as you use async. mechanics, closures get very handy and make your code looking more clean, off course only if you can read and understand closures :)
By the way, you could also simply write:
function(private) {}(outer)
is the same as
(function(private) {})(outer)
but the second is better, because its simply more obvious for the reader.
The syntax you describe is commonly referred to as an "immediately invoked function expression", or IIFE.
One of the common use cases is to emulate private variables:
var ns = (function () {
var x = 1; // "private"
return {
getX: function () {
return x;
}
}
}());
ns.getX(); // 1
ns.x; // undefined because x is "private"
In that example the x variable is local to the IIFE. It's not directly accessible outside of it. However, since it is referred to by the getX method, which is accessible outside of the IIFE (because it's part of the returned object) a reference to x is kept alive. This is what is usually meant by the term "closure".
Self executing functions are not really useful if you just do an alert inside.
Consider something like this:
(function(foo) {
var a = ..
// do something with a and foo
})(test);
The advantage here is that a is "private" inside the method and cannot be used outside the method. So a doesn't end up as a global variable and can't be overwritten by some other piece of javascript which uses a variable of the same name.

When will I need a javascript anonymous function immediately invoked?

I see no situation where I need this
(function(param){
alert(param);
//do something
})("derp");
istead of this
alert("derp");
//do something
EDIT: ok, thanks everybody, i think i got it.
so if you have this:
var param = "x";
var heya = "y";
(function(param){
alert(param);
//do something
})(heya);
the global variable "param" will be ignored in the scope of the anonymous function?
How about this scenario?
Example #1 - Uses an Immediately Invoked Function Expression that closes over a single variable and returns another function. Resulting in a beautiful, encapulated function.
var tick = (function () {
//Example of function expression + closure
var tock = 0;
return function() {
return ++tock;
}
}());
//It is impossible to alter `tock` other than using tick()
tick(); //1
tick(); //2
tick(); //3
tick(); //4
VERSUS
Example #2 - Uses a Function Declaration w/ a global variable
//Unnecssary global (unless wrapped in another function, such as jQuery's ready function)
var tock = 0;
function tick() {
return ++tock;
}
tick(); //1
tock = 4; //tock is exposed... and can be manipulated
tick(); //5
tock = 6;
tick(); //7
It is a contrived example but still a real case scenario in situations where people may want to generate consecutive UNIQUE ID's with no possibility of collision.
Well, you don't - for this simple example.
In JavaScript, variables are scoped to functions; therefore, if you wrap it in a function, you avoid global namespace pollution.
Well, in the example you've given, no, there probably isn't any reason why you would do this.
However, such a pattern is used typically to ensure that variables or functions, you require at a global level
Can be isolated from others potentially defined in other libraries
thus is an effective way to hide private variables
Can be protected against being tampered with by other libraries
Globals in Javascript are evil.
In particular, when working with jQuery I will frequently enclose the $(callback(){}) in a function like this, so that I can have global state for the jQuery code that I don't want inside the callback itself, usually because I have other code that isn't necessarily dependant on the jQuery ready initialisation:
function(){
var something = 'something';
$(function(){
something = 'jQuery bound';
});
}();
Aside from polluting the global namespace, memory usage is the other reason to do this - if you're pulling in a big data structure that only gets used once, wrapping that in a (function(){})() block means that you know it will be cleaned up once the function is finished executing.

Trouble using 'eval' to define a toplevel function when called from within an object

I've written (in JavaScript) an interactive read-eval-print-loop that is encapsulated
within an object. However, I recently noticed that toplevel function definitions specified to the interpreter do not appear to be 'remembered' by the interpreter. After some diagnostic work, I've reduced the core problem to this:
var evaler = {
eval: function (str)
{
return eval(str);
},
};
eval("function t1() { return 1; }"); // GOOD
evaler.eval("function t2() { return 2; }"); // FAIL
At this point, I am hoping that the following two statements wil work as expected:
print(t1()); // => Results in 1 (This works)
print(t2()); // => Results in 2 (this fails with an error that t2 is undefined.)
What I get instead is the expected value for the t1 line, and the t2 line fails with an error that t2 is unbound.
IOW: After running this script, I have a definition for t1, and no defintion for t2. The act of calling eval from within evaler is sufficiently different from the toplevel call that the global definition does not get recorded. What does happen is that the call to
evaler.eval returns a function object, so I'm presuming that t2 is being defined and stored in some other set of bindings that I don't have access to. (It's not defined as a member in evaler.)
Is there any easy fix for this? I've tried all sorts of fixes, and haven't stumbled upon one that works. (Most of what I've done has centered around putting the call to eval in an anonymous function, and altering the way that's called, chainging __parent__, etc.)
Any thoughts on how to fix this?
Here's the result of a bit more investigation:
tl;dr: Rhino adds an intermediate scope to the scope chain when calling a method on an instance. t2 is being defined in this intermediate scope, which is immediately discarded. #Matt: Your 'hacky' approach might well be the best way to solve this.
I'm still doing some work on the root cause, but thanks to some quality time with jdb, I now have more understanding of what's happening. As has been discussed, a function statement like function t1() { return 42; } does two things.
It creates an anonymous instance of a function object, like you'd get with the expression function() { return 42; }
It binds that anonymous function to the current top scope with the name t1.
My initial question is about why I'm not seeing the second of these things happen when I call eval from within a method of an object.
The code that actually performs the binding in Rhino appears to be in the function org.mozilla.javascript.ScriptRuntime.initFunction.
if (type == FunctionNode.FUNCTION_STATEMENT) {
....
scope.put(name, scope, function);
For the t1 case above, scope is what I've set to be my top-level scope. This is where I want my toplevel functions defined, so this is an expected result:
main[1] print function.getFunctionName()
function.getFunctionName() = "t1"
main[1] print scope
scope = "com.me.testprogram.Main#24148662"
However, in the t2 case, scope is something else entirely:
main[1] print function.getFunctionName()
function.getFunctionName() = "t2"
main[1] print scope
scope = "org.mozilla.javascript.NativeCall#23abcc03"
And it's the parent scope of this NativeCall that is my expected toplevel scope:
main[1] print scope.getParentScope()
scope.getParentScope() = "com.me.testprogram.Main#24148662"
This is more or less what I was afraid of when I wrote this above: " In the direct eval case, t2 is being bound in the global environment. In the evaler case, it's being bound 'elsewhere'" In this case, 'elsewhere' turns out to be the instance of NativeCall... the t2 function gets created, bound to a t2 variable in the NativeCall, and the NativeCall goes away when the call to evaler.eval returns.
And this is where things get a bit fuzzy... I haven't done as much analysis as I'd like, but my current working theory is that the NativeCall scope is needed to ensure that this points to evaler when execution in the call to evaler.eval. (Backing up the stack frame a bit, the NativeCall gets added to the scope chain by Interpreter.initFrame when the function 'needs activation' and has a non-zero function type. I'm assuming that these things are true for simple function invocations only, but haven't traced upstream enough to know for sure. Maybe tomorrow.)
Your code actually is not failing at all. The eval is returning a function which you never invoke.
print(evaler.eval("function t2() { return 2; }")()); // prints 2
To spell it out a bit more:
x = evaler.eval("function t2() { return 2; }"); // this returns a function
y = x(); // this invokes it, and saves the return value
print(y); // this prints the result
EDIT
In response to:
Is there another way to create an interactive read-eval-print-loop than to use eval?
Since you're using Rhino.. I guess you could call Rhino with a java Process object to read a file with js?
Let's say I have this file:
test.js
function tf2() {
return 2;
}
print(tf2());
Then I could run this code, which calls Rhino to evaluate that file:
process = java.lang.Runtime.getRuntime().exec('java -jar js.jar test.js');
result = java.io.BufferedReader(java.io.InputStreamReader(process.getInputStream()));
print(result.readLine()); // prints 2, believe it or not
So you could take this a step further by WRITING some code to eval to a file, THEN calling the above code ...
Yes, it's ridiculous.
The problem you are running into is that JavaScript uses function level scoping.
When you call eval() from within the eval function you have defined, it is probably creating the function t2() in the scope of that eval: function(str) {} function.
You could use evaler.eval('global.t2 = function() { return 2; }'); t2();
You could also do something like this though:
t2 = evaler.eval("function t2() { return 2; }");
t2();
Or....
var someFunc = evaler.eval("function t2() { return 2; }");
// if we got a "named" function, lets drop it into our namespace:
if (someFunc.name) this[someFunc.name] = someFunc;
// now lets try calling it?
t2();
// returns 2
Even one step further:
var evaler = (function(global){
return {
eval: function (str)
{
var ret = eval(str);
if (ret.name) global[ret.name] = ret;
return ret;
}
};
})(this);
evaler.eval('function t2() { return 2; }');
t2(); // returns 2
With the DOM you could get around this function-level scoping issue by injecting "root level" script code instead of using eval(). You would create a <script> tag, set its text to the code you want to evaluate, and append it to the DOM somewhere.
Is it possible that your function name "eval" is colliding with the eval function itself? Try this:
var evaler = {
evalit: function (str)
{
return window.eval(str);
},
};
eval("function t1() { return 1; }");
evaler.evalit("function t2() { return 2; }");
Edit
I modified to use #Matt's suggestion and tested. This works as intended.
Is it good? I frown on eval, personally. But it works.
I think this statement:
evaler.eval("function t2() { return 2; }");
does not declare function t2, it just returns Function object (it's not function declaration, it's function operator), as it's used inside an expression.
As evaluation happens inside function, scope of newly created function is limited to evaler.eval scope (i.e. you can use t2 function only from evaler.eval function):
js> function foo () {
eval ("function baz() { return 'baz'; }");
print (baz);
}
js> foo ();
function baz() {
return "baz";
}
js> print(baz);
typein:36: ReferenceError: baz is not defined
https://dev.mozilla.jp/localmdc/developer.mozilla.org/en/core_javascript_1.5_reference/operators/special_operators/function_operator.html
https://dev.mozilla.jp/localmdc/developer.mozilla.org/en/core_javascript_1.5_reference/statements/function.html
I got this answer from the Rhino mailing list, and it appears to work.
var window = this;
var evaler = {
eval : function (str) {
eval.call(window, str);
}
};
The key is that call explicitly sets this, and this gets t2 defined in the proper spot.

Categories

Resources