How to force 'function' to be an expression, not a statement? - javascript

While this code is fine:
var x = function() { };
This code is not:
function() { };
The top example creates an anonymous function and assigns it to x. The bottom example is a statement, where a function name is required, so it is a syntax error.
Now, it may seem pointless to define an anonymous function and not assign it anywhere, but here's an example that confronts the behavior:
var x = eval('function() { }');
Which should behave just like the first example, but is a syntax error.
Deep in the app I'm working on, we come to this issue. I want function() { } to be an expression.
A short explanation why is that this is a native OSX app calling javascript into a WebView. We have an evaluateJavascript function which the native layer can use to call arbitrary javascript. evaluateJavascript wraps the given code with try/catch for error-handling, because it's the only way to get detailed error information. So if you call myCallback = evaluateJavascript("function() { }"), we generate a function with the following body:
try {
return eval('function() { }');
} catch(e) {
// ....
}
And return the result.

When possible, don't use eval. Another option to find errors is if you listen for errors on the window (or equivalent) object and import the scripts as <script>s which are added and removed immediately.
Doing anything on the same line before function will cause function to be an expression
All of the following are valid (although useless)
0, function () {};
(function() {});
+function () {};
-function () {};
!function () {};
// etc
Function expressions like this are usually done for IIFEs, i.e.
(function (foo) {
console.log(foo);
}('bar'));
// "bar" logged
But you can apply the style to your eval-ing. Either parenthesis or the comma operator should work for you
var code = 'function () {}';
var foo = eval('0, ' + code);
foo; // function () {}

Can't you do
x = eval('y = function() {}')
?

You say var x = eval('function() { }'); should behave just like the first example. Why do you think so? Your eval argument
function() { }
is a statement and invalid as you point out above. You could make it an expression like this:
var x = eval('(function() { })');

Attempt/Approach- 1 : Below should work
var scope = {};
eval('scope.x = function() { return "Hello World"; }');
console.log(scope.x());
Output
Hello World
[Finished in 0.3s]
** Approach - 2 **
After reading link on IIFE insuggested in comments of above question, I tried below - and it seems to work as well.
var x = eval('(function() { return "Hello World"; })');
console.log(x());
However, I realized that with IIFE, we need to have code like (function(){})() - note that trailing (). However, in the Approach-2 code - I did not have the trailing (). Then, I looked up the eval documentation, and from it I came to know the following (which explains why Approach-2 works):
eval as a string defining function requires "(" and ")" as prefix and
suffix

Related

What does placing parenthesis alone around a function mean? (function(){})

I know what an Immediately-Invoked Function Expression is. I know the difference between this
let x = function()
{
}
and this
let x = (function()
{
})()
but what about this
let x = (function()
{
})
do the parenthesis here have any significance alone? I've seen it in several places before.
I thought this was an example but it might not be one X)
edit: Those weren't really intended to be code snippets, anyhow assuming they're snippets, it turns out there's big difference between the case where they are function declarations and function expressions. I didn't expect this. Sorry for the context change and thanks for all the care!
Answer to the edited question:
but what about this
let x = (function()
{
})
There is no purpose served by those () at all. That's exactly the same as:
let x = function()
{
}
Answer to question embedded in comments:
In a comment you've said you actually were wondering about this:
let foo = () => ({ bar: { foo: 1, bar: 2, } });
The () are necessary because that's an arrow function with a concise body returning the result of an object initializer. But if there's a { immediately after the =>, the { would be the opening of a block (verbose) body instead (not the beginning of an object initializer). That's why the () are necessary around the expression body of the concise arrow, to disambiguate the {.
Note that the () are not around the function; just its body.
You can write it the way you did:
let foo = () => ({ bar: { foo: 1, bar: 2, } });
or with {} and return:
let foo = () => { return { bar: { foo: 1, bar: 2, } } };
but not:
let foo = () => { bar: { foo: 1, bar: 2, } }; // Wrong
because the { would be read as the beginning of a block body.
Answer to original question:
I'm going to assume these have names, as otherwise your first example is a syntax error.
but what about this
(function()
{
})
That would be a function expression that isn't immediateley invoked. Unlike your first example, it's evaluated when the step-by-step execution reaches it, instead of when the context it's in is initially created.
Unless something is using the result of that expression, it's a no-op (something that does nothing), since nothing in the expression runs it.
If the result of the expression is being used (it's the right-hand side of an assignment, it's being passed into a function as an argument, etc.), the () around it are unnecessary with a function expression. (That isn't always the case with an arrow function.)
Given the original question:
All else being equal (and it probably isn't because you omitted the context):
This is a syntax error. It starts off as a function declaration and then doesn't meet the syntax requirements.
This is an immediately invoked function expression.
The parenthesis make this a function expression (just like in example 2). It isn't invoked (the () are missing at the end). It isn't assigned anywhere. It does nothing.
But now you've rewritten the question and completely changed the meaning.
Example 3 and Example 1 are now the same.
Putting ( and ) around an expression does nothing except override operator precedence … and there are no operators inside them.
There's no difference between (function() {}) and function() {}.
This lines are also the same :
var test1 = (function() {});
var test2 = function() {};
BUT, if you only write this :
function() {};
You'll get a syntax error. If you don't want a syntax error you have to write this :
(function() {});
But this line is useless and do nothing at all. Because the defined function is never called and no one can access it.
Enclosing a function in parentheses in this way lets you package it for use in another variable or function.
For example, you could use this (somewhat redundantly) to set a variable to a function.
var foo = (function bar() { /* code */ });
foo(); // calls code in bar()
This is also a way to package a callback function, e.g.
asyncFunction((function callback() { /* code */ });
You wouldn't want to use this type of declaration on its own because it becomes hidden to the rest of your code as in the below example.
function foo() { /* code */ };
(function bar() { /* code */ });
foo(); // runs foo code
bar(); // ERROR - bar() undefined in this scope
A similar syntax is used with a trailing parentheses in an "Immediately-Invoked Function Expression". This passes a variable into your function and runs it inline.
(function foo(a) { console.log(a) })("Hello World!");
// Prints "Hello World"
TL;DR - Use it as a way to write a named function inline and package it into another function or variable or, with trailing parentheses, to call your function immediately with a specified input.

Determine function has defined as a expression or declaried as function

I want to know how the function has been initialized, with the expression or declaried as fuction. _ Amazon interview question
expression : var a = function (){ }
declaration: function a (){ }
You could just do a.toString() and parse out the name. Or do the same with regular expressions
a.toString().test(/^\s*function\s*\(/);
function a(){ }; // gives false
var a = function (){ }; // gives true
Of course as Grundy pointed out this fails with named functions. Something like
var a = function b() {};
or
function b() {};
var a = b;
And ES6 has .name (see the Browser table at the bottom for the current state of affairs) - https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Function/name
I don't think it's possible to do so. The only difference between:
var func = function(){ };
and:
function func() { };
Is that the first one gets assigned on runtime. The way I see it, is that both function statements return a reference to their respective function objects. In that sense they are both the same. The only thing you could argue is that one is not named and the other one is, but you could have assigned a named function to a variable too.
However, there seems to be a difference on how they get assigned. The second one seems to get assigned to a variable that its named after, right at the start of the execution context. The first one has to wait for the explicit assignment within the execution context.
So you'd be testing for when they get assigned. You might think that's is possible to do so within the global object like:
//some protected vars that can't work without same-origin
var protected = ['caches', 'localStorage', 'sessionStorage', 'frameElement'];
var definedAtInit = [];
for(prop in window){
if(!isSandboxed(prop) && typeof window[prop] === 'function'){
definedAtInit.push(prop);
}
};
function isSandboxed(prop){
return protected.indexOf(prop) !== -1;
}
function isItDefinedAtInit(funcName){
return definedAtInit.indexOf(funcName) !== -1;
}
var func = function() {
console.log('test');
}
var results = { isItDefinedAtInit : isItDefinedAtInit('isItDefinedAtInit'),
func : isItDefinedAtInit('func')
};
document.getElementById('results').innerHTML = JSON.stringify(results, '/t');
<pre id="results"></pre>
However, you could still do something like:
var isItDefinedAtInit = function() { };
//After this, isItDefinedAtInit('isItDefinedAtInit') would be wrong.
And you still have the problems with other execution contexts, I don't think functions declared within a function execution context get attached to any object.
I think these kind of checks are a bad idea to be honest.
There is only way, we can determine function has defined with function declarations not as expression.
as Grundy mentioned name property of the respective function gives require information, if it has been defined with expression name property holds undefined value, else it holds function name.
Here is the code :
var isDefinedAsFunction = function(fn){
return fn.name !== undefined
}

Why doesn't jslint like the use of call() on a function expression?

I'm getting this error.
Unexpected '.'.
for this line:
}).call(this);
I checked jslinterrors.com and could not find a reason.
Reproduce the error using:
(function () {
"use strict";
var a = 1;
a = a + 1;
}).call(this);
I don't see anything wrong with with the code that you supplied. Perhaps there is something not right in the parsing that jslint performs, or maybe there is a real reason for the warning, I can't find one. With a little dancing you can be off with the warning, by writing it like this.
/*global console */
(function () {
"use strict";
return function () {
var a = 1;
a = a + 1;
console.log(this);
};
}()).call([]); // used array rather than this so that it is easy to see in console
On jsFiddle
Probably because your using an anonymous function which is an anti pattern in this way. The following should work:
(function () {}())
Functions wrapped in parenthesis are meant to be invoked immediately so you cannot use .call() there.
Example of function use
(function () {
// do something
})();
Instead you could do
var foo = function () {
// do something
};
foo.call(this); // within scope

What is the difference between two declarations of module in javascript?

What is the different between two declarations of a module in JavaScript?
One has parentheses around the function and other one doesn't?
One article says that
Notice the () around the anonymous function. This is required by the
language, since statements that begin with the token function are
always considered to be function declarations. Including () creates a
function expression instead.
Both seem to do the same thing when checked.
var person = (function () {
// Private
var name = "Robert";
return {
getName: function() {
return name;
},
setName: function(newName) {
name = newName;
}
};
}());
var person = function () {
// Private
var name = "Robert";
return {
getName: function() {
return name;
},
setName: function(newName) {
name = newName;
}
};
}();
Functions are of two types in JavaScript - declarations and expressions.
This is the difference between the two:
Function declarations are hoisted. This means you can call the function before it appears in the program as declarations in JavaScript are hoisted.
Function expressions can be invoked immediately. A function declaration cannot. This is because expressions express (or return a value). Function expressions express a function.
An example of a function declaration:
foo("bar");
function foo(bar) {
alert("foo" + bar);
}
The above program will work because foo is a function declaration.
foo("bar"); // throws an error, foo is undefined - not a function
var foo = function (bar) {
alert("foo" + bar);
};
The above program will not work as foo is declared as undefined, hoisted and then later assigned the value of a function expression. Hence it's undefined when it's called.
An example of a function expression:
(function (bar) {
alert("foo" + bar);
}("bar"));
The above function will be immediately invoked as it's a function expression.
function (bar) {
alert("foo" + bar);
}("bar"); // throws an error, can't call undefined
The above function will not be immediately invoked as it's a function declaration. Remember, declarations do not express (or return a value). So it's like trying to invoke undefined as a function.
How does a function become an expression?
If a function is used in the context where an expression is expected then it's treated as an expression. Otherwise it's treated as a declaration.
Expressions are expected when:
You're assigning a value to a variable (i.e. identifier = expression).
Inside parentheses (i.e. ( expression )).
As an operand of an operator (i.e. operator expression).
Hence the following are all function expressions:
var foo = function () {};
(function () {});
~function () {};
Everything else is a function declaration. In short if your function is not preceded by anything, it's a declaration.
See this code: https://github.com/aaditmshah/codemirror-repl/blob/master/scripts/index.js#L94
The following function isExpression is used to test whether some arbitrary JavaScript code is an expression or not:
function isExpression(code) {
if (/^\s*function\s/.test(code)) return false;
try {
Function("return " + code);
return true;
} catch (error) {
return false;
}
}
Hope this clears any doubts in your mind.
In short:
A function expression expresses or returns a value (in this case a function). Hence it can be immediately invoked, but it can't be called before it appears in the program.
A function declaration is hoisted. Hence it can be called before it appears in the program. However since it doesn't express any value it can't be immediately invoked.
In the current context there's no difference for the interpreter. Usually preferable way of writing module is by wrapping the function with parentheses:
var person = (function () {
// Private
var name = "Robert";
return {
getName : function () {
return name;
}
};
}());
That's because the syntax is cleaner and it's obviously that you want to invoke the function immediately after it is declared. One more reason is because:
(function () {
//some stuff
}());
will work but
function () {
//some stuff
}();
this wont.
By wrapping the function each time you use common codding style which is usually a good thing :-).
The difference is that when writing:
var foo = (function () {
...
}());
the use of the (superfluous but useful) grouping () is a common coding style to make it clear from very like first line that the right hand side is most likely an immediately invoked function expression (IIFE). However, in the second:
var foo = function () {
...
}();
it doesn't become apparent until you read the last line, which might be quite a few lines down. Until you reach the last line, you probably thought you were reading a plain assignment:
var foo = function () {
...
};
Note that the parenthesis can be used in a plain assignment too:
var foo = (function () {
...
});
but in that case they really are superfluous (and probably misleading due to the convention of using them for IIFEs).
See An Important Pair of Parens.

eval returning variable name instead of undefined. (javascript)

Update
The code for the function / class is stored in a string which is why I cannot call it directly. The idea is to do introspection on the object and enumerate its data members which works when it is a function but doesn't work when a variable like the one below is eval'ed.
I am trying to evaluate an object in javascript. Something like this.
var myObj {
greet: "Greeting",
myPrint: function() {
alert("hello");
}
};
The idea is to be able to run this in eval and get the variable name somehow (myObj) or an object created. I have experimented with various methods using eval but cannot figure this out. This works when I have something like this.
function myObj() {
this.greet = "Greeting";
this.myPrint = function() {
alert("hello");
}
};
Running eval("(" + code + ")"); where code is a string containing the above function returns myObj() to me.
Update 2
So basically I want to evaluate something like this.
eval("var x = 5"); and I am trying to get x. Since its a string being evaluated, even though it gets added to the window namespace, there is no way to decipher it apart from parsing the string. Now this is just a simple example but as I said, it's a little difficult with the 1st piece of code. As I said...
eval("function test() { return 'hello'; }"); return test() which is similar to what I am expecting for the "var x = 5" statement.
Is there a way to do this similarly for the 1st case which I am missing ?
Thanks
A code:
var sCode = '{ great: "Greating", myPrint: function() { alert("hello!"); } }',
oObj = eval("(" + sCode + ")");
oObj.myPrint(); // alert "hello"
console.log(oObj.great); // prints "Greating"
Are you trying to dynamically call a callback?
var myObj = { // fixed this line of code as it was missing the =
greet: "Greeting", // replaced ; with ,
myPrint: function() {
alert("hello");
}
};
console.log(eval(myObj)); // returns obj as expected.
If I am correct in my assumption you would need to use bracket notation and EVAL is not needed
So if you were passing a String it would look like:
var str = 'myPrint';
var strTwo = 'greet'
myObj[str](); // to execute the function
myObj[strTwo]; // now contains "Greeting"
Which would execute that function.
Hope that helps!
Tim
EDIT:
var myObj = 'var myObj = { greet: "Greeting", myPrint: function() { alert("hello"); } }'
console.log(eval(myObj));
myObj.myPrint();
Then this is what you want if this does not work it means you are not escaping your string correctly:
http://jsfiddle.net/XtyHh/
You eval the object without executing the myPrint function.
You would need to do something like
myObj.myPrint()
To get it to throw the alert.
[edit] To immediately run the myPrint function change your code to this:
var myObj = {
greet: "Greeting",
myPrint: (function() {
alert("hello");
})();
};

Categories