How to run Global Constant Function from Variable in Browser - javascript

I can access and run any function resides in window Object Using name String.
for e.g,
function abc() {
console.log("abc");
}
var str = "abc";
window[str](); // abc
but I want to know, is it somehow possible to run function declared with const keyword.
const xyz = () => console.log("xyz");
const str = "xyz";
window[str](); // TypeError: window.xyz is not a function

It's possible, but the only way to do it I can think of is a Bad Idea™ in most cases: eval or its close cousin new Function:
const xyz = () => console.log("xyz");
const str = "xyz";
(0,eval)(str + "()");
new Function(str + "()")();
The problem with eval (whether direct or, as above, indirect) and new Function is that they run arbitrary code from a string, firing up a full JavaScript parser to do so. Used incorrectly, that opens the door to XSS attacks or issues with inefficient code (though parsers are amazingly fast these days).
For any who don't know (I think the OP does): Global const, let, and class bindings are not added as properties to the global object like global var and function bindings are. That's why window[str](); won't work.
About
(0,eval)(str + "()");
above: that's an indirect eval. It works by separating the lookup of the identifier eval from the call, which breaks eval's special link with local scope. In that case, it's using the comma operator to do that. Details:
You probably know that eval has access to local scope (and all containing scopes), so for instance this works:
function foo() {
const answer = 42;
eval("console.log(answer);");
}
foo();
The code in eval can see answer because it has access to the scope where you called eval.
To try to limit the power of eval a bit, you can turn off its access to local scope and have it run its code at global scope instead by using eval indirectly. For instance, if you put it in a variable:
function foo() {
const answer = 42;
const e = eval;
e("console.log(answer);"); // Fails with ReferenceError
}
foo();
By separating the lookup of the identifier eval from calling the function it refers to, you break the special link it has with local scope.
The comma operator is one of JavaScript's more unusual operators: It evalutes its left-hand operand, throws away the result, evaluates its right-hand operand, and takes that value as the result of the comma expression:
function foo() {
console.log("foo ran and returned 1");
return 1;
}
function bar() {
console.log("bar ran and returned 2");
return 2;
}
const x = (foo(), bar());
console.log(`x = ${x}`);
Using (0, eval)(str) separates the lookup of the identifier eval from the call to the function just like assigning it to e did above. 0 is evaluated, thrown away, then eval is evaluated resulting in a function reference, and that function reference is the result of the comma expression; then we use it to eval str.

Related

In Javascript, when is it necessary to assign a named function to a variable?

In the online REPL of Babel JS (http://babeljs.io/repl/), when I type in :
let a = (x) => x+1
It will be transpiled to:
"use strict";
var a = function a(x) {
return x + 1;
};
Here the var a = function a(x) looks a bit confusing to me, because either var a = function(x) or function a(x) is enough as I understand.
Does anyone have ideas about when and why it is necessary to assign a named function to a variable?
There are really two different questions here:
What are the differences between the different ways of defining or expressing functions?
Why does let a = (x) => x + 1 get transpiled this way?
In order to answer (2) we need to understand (1)-- which has been extensively discussed on SO and elsewhere.
Question 1
Let's go through the three alternatives you mentioned:
Function declaration:
function a(x) { ... }
Syntactically, these must always begin with function (reference). They are hoisted at parse time and create a named function in the local scope.
(Anonymous) Function expression:
var a = function (x) { ... }
var a itself will be hoisted at parse time, but it will be undefined until this line is executed at runtime.
Named Function expression:
var a = function a(x) { ... }
Though the syntax makes it looks like an assignment to a function declaration, this is actually just a function expression with a name. I find this confusing, but that's the syntax.
The big difference is between function declarations and function expressions. With a declaration, you can do:
a(1);
function a(x) { return x + 1; }
though attempting this with a function expression (named or anonymous) will cause an error.
Question 2
Why does let a = (x) => x + 1 get transpiled this way?
We're assigning the arrow function (x) => x + 1 to a block-scoped variable with let, so we should expect that a is not defined until after this line has been executed at runtime. This should be a function expression, not a function declaration.
Last, why is let a = (x) => x + 1 transpiled to a named function expression rather than a anonymous function expression? What's the difference? As Alnitak and others have pointed out:
Function names appear in debuggers, which can be helpful.
The scope inside of a named function definition has a reference to the function itself. This allows for recursion and accessing properties of the containing function.
So named function expressions have some nice properties that anonymous function expressions don't. But there actually seems to be disagreement on what should happen here. According to MDN:
Arrow functions are always anonymous
whereas this answer to Why use named function expressions? says:
"[As of ES6] a lot of "anonymous" function expressions create functions with names, and this was predated by various modern JavaScript engines being quite smart about inferring names from context... This is strewn throughout the spec"
Other references:
var functionName = function() {} vs function functionName() {}
Javascript - Precedence in hoisting
I've found that the best way to get a handle on this is playing around with the Babel REPL.
If you write:
function a(x) { }
then the function is hoisted to the top of the enclosing scope, and a becomes available immediately at parse time within the entire scope.
However, when you write:
var a = function a(x) { }
then var a will not have a defined value in the enclosing scope until this line is actually executed.
However, within that function, a different a will exist as a locally scoped reference to the function itself.
By using the let a = function ... construct Babel is being more consistent with the latter form, ensuring that a is assigned at run time to a (named) function expression instead of using a parse time function declaration.
It appears that this is according to standard (12.14.4):
AssignmentExpression[In, Yield] : LeftHandSideExpression[?Yield] = AssignmentExpression[?In, ?Yield]
1.If LeftHandSideExpression is neither an ObjectLiteral nor an ArrayLiteral, then
  a. Let lref be the result of evaluating LeftHandSideExpression.
  b. ReturnIfAbrupt(lref).
  c. Let rref be the result of evaluating AssignmentExpression.
  d. Let rval be GetValue(rref).
  e. If IsAnonymousFunctionDefinition(AssignmentExpression) and IsIdentifierRef of LeftHandSideExpression are both true, then
    I.   Let hasNameProperty be HasOwnProperty(rval, "name").
    II.  ReturnIfAbrupt(hasNameProperty).
    III. If hasNameProperty is false, perform SetFunctionName(rval, GetReferencedName(lref)).
So, whenever an assignment of an unnamed function expressions to a named identifier is evaluated, the function name should be set to the identifer name.
Babel follows this process, and generates a compatible ES5 implementation.
Chrome (v46.0.2490.71, V8 engine...), doesn't follow this process, and name equals '' in that cases.
As for the question itself...
In Javascript, when is it necessary to assign a named function to a variable?
The answer is never. It's up to the developer to decide if / when to use a named function. The decision boils down to specific need for a name (such as when "stringifying" a function), or debug needs (better stack traces...).

Global Eval with return value ?

After searching a while , I was hoping to find a solution for global eval with a return value.
eval will run in the current scope
Function constructor will execute in its own local scope with access to global scope
setTimeout trick is an async operation
script injection can not return value
window.execScript also - can not return value
So my question is:
Is there any other technique which runs at the global scope and can return value ?
(example will be much appreciated).
You can make eval to run in global scope, instead of
eval(s)
just use
window.eval(s);
or
var e=eval; e(s);
or
[eval][0](s)
This surprisingly happens because Javascript is weird and has a special rule about eval: when you're using the original eval object directly to evaluate a string the evaluation happens in the current context.
If an "indirect eval" is used instead (i.e. you store eval in a variable and then use the variable, or even if you access eval using the window object) the evaluation happens in the global context.
You can check this in a Javascript console:
function foo() {
eval("function square(x){ return x*x; }");
}
function bar() {
window.eval("function square(x){ return x*x; }");
}
foo()
square(12) // <-- this gives an error; direct evaluation was used
bar()
square(12) // <-- this returns 144
So window.eval(s) is not the same as eval(s) even if window.eval === eval.
PS
Note that eval has a special specific language rule for this to happen, but the same apparently strange behavior can also be observed in other cases for a different reason.
If you have an object x with a method defined m then
x.m()
is not the same as
var mm = x.m; mm();
because this in the first case will be bound to x during execution of the code in m while in the second case this will be the global object.
So also in this case x.m() is different from mm() even if x.m === mm.
For the same reason x.m() is not the same as [x.m][0]() because in the latter this will be bound to an array object during the execution of method code instead of being bound to x.

Any difference between f() and (f())?

Any difference between
var myfunc = (function () { return function () { ... } }());
and
var myfunc = function () { return function () { ... } }();
Is it just a matter of style or is there more to the surrounding () in the first form?
Nope. Or at least not in your example.
The outer parens only matter when the function keyword would be the first token in a statement.
// cool
var foo = function(){}();
var foo = (function(){}());
// also cool
(function(){}());
// not cool, syntax error
// parsed as function statement, expects function name which is missing
function(){}();
// also not cool, syntax error
// declares a function, but can't be executed immediately
function foo(){}();
When function is the first token in a statement, it's a function declaration (think named function), which behaves slightly differently than function in all other contexts. That leading paren forces the parses to treat it like a function expression (think anonymous function) instead, which allows immediate execution.
See: What is the difference between a function expression vs declaration in JavaScript?
If you start the line or statement with something else, like variable declaration, it technically doesn't matter at all.
No difference, though Crockford advises the use of the former, to ascertain that it's being treated as a function expression.
For more info, read these:
Immediately-Invoked Function Expression (IIFE)
Named function expressions demystified
There's no technical difference, It's just an idiomatic style used for readability to signal at the start that it's a self-invoking function.
no difference, it is just a matter of style. Both are executed functions and they return whatever they return in the variable and they are returning a function. check this out
the purpose is to avoid the global scope, adding the var myfunc = in front of (function (){ return function(){}}()); essentially defeats the purpose
compare the two
(function(){...do something...}());
this function is ran in a local scope, which is inside the parentheses.
var myfunc = function(){};
this function is ran on the global scope.
why not this way, because you can get your self into naming conflicts with other methods and var as well as plugin's named var and it can hinder your applications performance with the var being saved on the global scope.
I perfer
(function() {})();

Two functions with the same name in JavaScript - how can this work?

As far as I know, function foo() { aaa(); } is just var foo = function(){ aaa() } in JavaScript. So adding function foo() { bbb(); } should either overwrite the foo variable, or ignore the second definition - that's not the point. The point is that there should be one variable foo.
So, in this example the me variable should not be correctly resolved from inside the methods and it is not in Explorer 8 :-). I came to this example by trying to wrap them into another closure where (var) me would be, but I was surprised that it's not necessary:
var foo = {
bar1 : function me() {
var index = 1;
alert(me);
},
bar2 : function me() {
var index = 2;
alert(me);
}
};
foo.bar1(); // Shows the first one
foo.bar2(); // Shows the second one
Demo: http://jsfiddle.net/W5dqy/5/
AFAIK function foo() { aaa(); } is just var foo = function(){ aaa() } in JavaScript.
Not quite; they're similar, but also quite different. JavaScript has two different but related things: Function declarations (your first example there), and function expressions (your second, which you then assign to a variable). They happen at different times in the parsing cycle and have different effects.
This is a function declaration:
function foo() {
// ...
}
Function declarations are processed upon entry into the enclosing scope, before any step-by-step code is executed.
This is a function expression (specifically, an anonymous one):
var foo = function() {
// ...
};
Function expressions are processed as part of the step-by-step code, at the point where they appear (just like any other expression).
Your quoted code is using a named function expression, which look like this:
var x = function foo() {
// ...
};
(In your case it's within an object literal, so it's on the right-hand side of an : instead of an =, but it's still a named function expression.)
That's perfectly valid, ignoring implementation bugs (more in a moment). It creates a function with the name foo, doesn't put foo in the enclosing scope, and then assigns that function to the x variable (all of this happening when the expression is encountered in the step-by-step code). When I say it doesn't put foo in the enclosing scope, I mean exactly that:
var x = function foo() {
alert(typeof foo); // alerts "function" (in compliant implementations)
};
alert(typeof foo); // alerts "undefined" (in compliant implementations)
Note how that's different from the way function declarations work (where the function's name is added to the enclosing scope).
Named function expressions work on compliant implementations. Historically, there were bugs in implementations (early Safari, IE8 and earlier). Modern implementations get them right, including IE9 and up. (More here: Double take and here: Named function expressions demystified.)
So, in this example the me variable shoudl not be corectly resolved from inside the methods
Actually, it should be. A function's true name (the symbol between function and the opening parenthesis) is always in-scope within the function (whether the function is from a declaration or a named function expression).
NOTE: The below was written in 2011. With the advances in JavaScript since, I no longer feel the need to do things like the below unless I know I'm going to be dealing with IE8 (which is very rare these days).
Because of implementation bugs, I used to avoid named function expressions. You can do that in your example by just removing the me names, but I prefer named functions, and so for what it's worth, here's how I used to write your object:
var foo = (function(){
var publicSymbols = {};
publicSymbols.bar1 = bar1_me;
function bar1_me() {
var index = 1;
alert(bar1_me);
}
publicSymbols.bar2 = bar2_me;
function bar2_me() {
var index = 2;
alert(bar2_me);
}
return publicSymbols;
})();
(Except I'd probably use a shorter name than publicSymbols.)
Here's how that gets processed:
An anonymous enclosing function is created when the var foo = ... line is encountered in the step-by-step code, and then it is called (because I have the () at the very end).
Upon entry into the execution context created by that anonymous function, the bar1_me and bar2_me function declarations are processed and those symbols are added to the scope inside that anonymous function (technically, to the variable object for the execution context).
The publicSymbols symbol is added to the scope inside the anonymous function. (More: Poor misunderstood var)
Step-by-step code begins by assigning {} to publicSymbols.
Step-by-step code continues with publicSymbols.bar1 = bar1_me; and publicSymbols.bar2 = bar2_me;, and finally return publicSymbols;
The anonymous function's result is assigned to foo.
These days, though, unless I'm writing code I know needs to support IE8 (sadly, as I write this in November 2015 it still has significant global market share, but happily that share is plummetting), I don't worry about it. All modern JavaScript engines understand them just fine.
You can also write that like this:
var foo = (function(){
return {
bar1: bar1_me,
bar2: bar2_me
};
function bar1_me() {
var index = 1;
alert(bar1_me);
}
function bar2_me() {
var index = 2;
alert(bar2_me);
}
})();
...since those are function declarations, and thus are hoisted. I don't usually do it like that, as I find it easier to do maintenance on large structures if I do the declaration and the assignment to the property next to each other (or, if not writing for IE8, on the same line).
Both me lookups, are only visible/available inside the function expression.
Infact those two are named function expressions, and the ECMAscript specification tells us, that the name of an expression is not exposed to the such called Variable object.
Well I tried to put that only in a few words, but while trying to find the right words, this ends up in pretty deep chain of ECMAscript behavior. So, function expression are not stored in a Variable / Activation Object. (Would lead to the question, who those guys are...).
Short: Every time a function is called, a new Context is created. There is some "blackmagic" kind of guy that is called, Activation object which stores some stuff. For instance, the
arguments of the function
the [[Scope]]
any variables created by var
For instance:
function foo(test, bar) {
var hello = "world";
function visible() {
}
(function ghost() {
}());
}
The Activation Object for foo would look like:
arguments: test, bar
variables: hello (string), visible (function)
[[Scope]]: (possible parent function-context), Global Object
ghost is not stored in the AO! it would just be accesssible under that name within the function itself. While visible() is a function declaration (or function statement) it is stored in the AO. This is because, a function declaration is evaluated when parsing and function expression is evaluated at runtime.
What happens here is that function() has many different meanings and uses.
When I say
bar1 : function me() {
}
then that's 100% equivalent to
bar1 : function() {
}
i.e. the name doesn't matter when you use function to assign the variable bar1. Inside, me is assigned but as soon as the function definition is left (when you assign bar2), me is created again as a local variable for the function definition that is stored in bar2.

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