Code inside block is wrapped inside parens. Why? - javascript

I came across this code and don't understand why the code within the block is wrapped in the parens like an auto-executing function.
function foo(a,b) {
var b = b || window,
a = a.replace(/^\s*<!(?:\[CDATA\[|\-\-)/, "/*$0*/");
if (a && /\S/.test(a)) {
(b.execScript || function (a) {
b["eval"].call(b, a)
})(a);
}
}
The first parameter is the text from a script tag. The only part I don't get is why the script eval is wrapped in parens.

I assume you are talking about this part:
(b.execScript || function (a) {
b["eval"].call(b, a)
})(a);
This is short form of writing:
if (b.execScript) {
b.execScript(a);
}
else {
b["eval"].call(b, a);
}
I.e. execute b.execScript if it is defined, otherwise call b["eval"].call(b, a).
The purpose of the grouping operator is to evaluate ... || ... before the function call, i.e. whatever the result of the grouping operator is, it is treated as function and called by passing a to it.
It looks like the code could be simplified to
(b.execScript || b["eval"])(a);
Though if explicitly setting this to b is necessary, then the function expression is necessary as well, to have two functions that only accept one argument, a.

(b.execScript || function (a) {
b["eval"].call(b, a)
})(a)
This is wrapped in parens because the || statement needs to be evaluated to determine what function to run before being passed an argument.
This code calls b.execScript with argument a if b.execScript exists and is truthy. Otherwise it defines a new function and passes a as an argument to that.
The parens wrap is to make sure that the || statement is evaluated before the function is executed. Without it the logic would go basically, if b.exec doesn't exist, evaluate to the value of the custom function, if it does, evaluate to b.exec.
So with the parens the logic is equivalent to:
if(b.execScript){
b.execScript(a)
}
else{
function (a) {
b["eval"].call(b, a)
})(a)
}
without it, its equivalent to
if(!b.execScript){
function (a) {
b["eval"].call(b, a)
})(a)
}

It's parenthesized because the || operator binds more loosely than the function invocation operator (). Without the enclosing parentheses, the expression would be evaluated as if it were written:
b.execScript || (function (a) { b["eval"].call(b, a); })(a)
That is, it'd be either the plain value of b.execScript or the value of invoking that function. What the author wanted was invoke either the value of b.execScript (which would presumably be a function) or that little anonymous function.

Because of the (a) afterwards. The expression:
(b.execScript || function (a) {
b["eval"].call(b, a)
})
returns a closure which is then executed with a passed as a parameter.

The parenthetical expression returns either the result of b.execScript, or a new function. In either case, the result is then invoked with a as a parameter. The parens make sure the interpreter evaluates the || before the invocation.

why the code within the block is wrapped in the parens like an auto-executing function.
Because that particular part of the code is an auto-executing function:
(b.execScript || function (a) {
b["eval"].call(b, a)
})(a);
Here, the variable b references the execution container, e.g. window, and a contains JavaScript code that needs to be executed.
Since some browsers support execScript() while some only support eval(), the code supports them both by testing this browser feature like so:
var tmp = b.execScript || function (a) {
b["eval"].call(b, a)
};
Here, tmp is a function that takes a single parameter a and executes the code within; if execScript is not available, a small helper function is used instead. And then it's called like this:
tmp.call(b, a);
The first parameter to .call() defines what this refers to when tmp is called; the second parameter becomes the first parameter of tmp.

Related

Immediately invoked function expression without using grouping operator

I'm trying to immediately invoke a function without using IIFE pattern (enclosing a function definition inside parentheses). Here I see two scenarios:
When a function declaration is invoked immediately: gives SyntaxError.
When a function expression is invoked immediately: executes successfully.
Example 1: gives SyntaxError
//gives `SyntaxError`
function() {
console.log('Inside the function');
}();
Example 2: Executes without any error
// Executes without any error
var x = function() {console.log('Inside the function')}(); // Inside the function
So, I have these doubts:
With this approach, why does it give an error for function declaration but not for function expression?
Is there a way we can immediately invoke a function declaration without using IIFE pattern?
In your code you don't have name for the function that's the reason for syntax error. Even if you would had name it would have thrown error.
function func(){
console.log('x')
}();
The reason is the function declaration doesn't return the values of the function however when you wrap function declaration inside () it forces it be a function expression which returns a value.
In the second example the function() {console.log('Inside the function')} is considered expression because it's on RightHandSide. So it executes without an error.
Is there a way we can immediately invoke a function declaration without using IIFE pattern
You can use + which will make function declaration an expression.
+function(){
console.log('done')
}()
If you don't want to use + and () you can use new keyword
new function(){
console.log('done')
}
Extra
A very interesting question is asked by #cat in the comments. I try to answer it.There are three cases
+function(){} //returns NaN
(+function(){return 5})() //VM140:1 Uncaught TypeError: (+(intermediate value)) is not a function
+function(){return 5}() //5
+function(){} returns NaN
+ acts as Unary Plus here which parses the value next to it to number. As Number(function(){}) returns NaN so it also returns NaN
(+function(){return 5;})() returns Error
Usually IIFE are created using (). () are used to make a function declaration an expression + is short way for that. Now +function(){} is already an expression which returns NaN. So calling NaN will return error. The code is same as
Number(function(){})()
+function(){return 5;}() returns 5
In the above line + is used to make a statement an expression. In the above example first function is called then + is used on it to convert it to number. So the above line is same as
Number(function(){return 5}())
In the proof of statement "+ runs on after the function is called" Consider the below snippet
console.log(typeof +function(){return '5'}());
So in the above snippet you can see the returned value is string '5' but is converted to number because of +
A function declaration, like
function foo() {
}
defines (and hoists) the variable name foo as a function in the current scope. A function declaration doesn't evaluate to a value; it just does something, a bit like an if does something (rather than evaluate to a value).
You can only invoke values which are functions, eg
<somevalue>()
where somevalue is a variable name that refers to a function.
Note that function declarations require function names, because otherwise there's no variable name to assign the function to - your original
//gives `SyntaxError`
function() {
console.log('Inside the function');
}();
throws not because of the () at the end, but because of the lack of a name.
You can put parentheses at the end of a function declaration, as long as there's something inside the parentheses - but these parentheses do not call the function, they evaluate to a value:
function x() {
console.log('Inside the function');
}(console.log('some expression inside parentheses'));
The interpreter sees these as two separate statements, like
function x() {
console.log('Inside the function');
}
// completely separate:
(console.log('some expression inside parentheses'));
The inside of the parentheses gets evaluated and then discarded, since it doesn't get assigned to anything.
(Empty parentheses are forbidden because they can't be evaluated to a value, similar to how const foo = () is forbidden)
The E in IIFE stands for expression, and without the wrapping parenthesis your function is not evaluated as an expression thus the syntax error.
creating an expression is a way of tricking the interpreter and be able to invoke the function immediatly
(function() {
console.log('Inside the function');
})();
In your example you have a function statement followed by the grouping operator, but it's syntactically incorrect for two reasons, first it doesn't have a name, and second because the grouping operator must have an expression inside it, infact if you add a valid one the error will disappear, still you won't obtain your desired result.
function foo() {
console.log('Inside the function');
}();
function foo() {
console.log('Inside the function');
}(1+2);
In order to invoke something, it has to be a function value, a declaration just declares a name, and does not evaluate to the function value itself, hence you cannot invoke it.
A declaration cannot be invoked for the above reason. You have to end up with an expression somehow, either through assignment or grouping (IIFE). So that is a no.
If you give us more context on why you would want to do that, maybe we can help with suggestions.
Not sure why you would want to do it, but:
Is there a way we can immediately invoke a function declaration without using IIFE pattern?
Well, if for function declaration you mean using the keyword function as in:
function name() { return this.name; }
As far as I know, no. You need the extra parentheses to tell the runtime not to assign the function to a name variable, if I understand this stuff right.
Now, what you actually can do is to use Function as in:
new Function('console.log("ey there")')();
Which will execute the console.log code. No need for IIFE here. But I don't see how this could be better than an IIFE.
you can call in either below ways -
~function(){console.log("hi")}()
!function(){console.log("hi")}()
+function(){console.log("hi")}()
-function(){console.log("hi")}()
(function(){console.log("hi")}());
var i = function(){console.log("hi")}();
true && function(){ console.log("hi") }();
0, function(){ console.log("hi") }();
new function(){ console.log("hi") }
new function(){ console.log("hi") }()

Function returning function and no reference

My question is about this function:
function d() {
function e() {
alert('E');
}
return e;
}
d()();//alerts 'E'
When function d is called first time function e is returned, however, nothing holds reference to the returned value( function e in this case), and this returned value should be lost. So, how does this d()() work ? It's not a closure according to my understanding. Thank you !
The call to d (which is d() in that last line) returns e, and then the last () immediately calls that function.
Consider
function n() { return 5; }
console.log(n() + 1); // 6
Nothing holds the return value from the call to n(), and yet the return value can be used in the addition operation. The return value from the call to d() can similarly be used as a reference to a function in a function call expression, which is exactly what happens in your code.
To put it another way, d() returns a reference to a function (e). In order to call a function, all you need is a reference to a function taken from somewhere, and a parenthesized argument list. That's what d()() gives you.
You don't need a named reference to a function in order to use it. You can apply an operator to the result of any expression in place, and the () function call is just another operator.
So it's little different from performing addition on the result of a function call.
function returnTwo() {
return 2;
}
console.log(returnTwo() + 40);
Here we don't store the result of returnTwo(), but we can still use it as the left operand of the + operator. So with the function call in your example, you're doing the same thing.
function d() {
function e() {
alert('E');
}
return e;
}
d()();
//alerts 'E'
It doesn't need a reference because it is explicitly transformed into the returned value. Unless stored, the result of a JavaScript Expression( a sequence of interpreted variables, functions, and/or operations that returns a value ) will be fully evaluated and then removed from memory. The key is that it has to be fully evaluated. You can almost think of functional execution as horizontal Russian Nesting Dolls. The JavaScript expression is:
d()();
So it begins left-to-right with:
d()
which is executed and returns:
function e() { ... }
which turns the line into:
function e() { ... }()
which is then executed, alerts, and returns:
//nothing
The full Expression is completed. There is nothing left for it to do. The reference isn't stored anywhere and immediately after this expression is resolved everything that was returned from its evaluations is thrown away.

Function is working when assigned to a variable but throwing SyntaxError when executed by itself

I had an IIFE like this one:
(function a() {
return "b";
}());
Executed in the console, it returns "b".
I removed the first set of parentheses, thinking that this'll make the "a" function global, but still work, and return "b":
function a() {
return "b";
}();
But it throws a SyntaxError:
Uncaught SyntaxError: Unexpected token )
Then, I tried converting the function to an expression by assigning to a variable, and it worked:
var c = function a() {
return "b";
}();
console.log(c); // prints b
Why does this happen? Why is it working as an expression but not by itself?
The second piece of code is not what it looks like.
This code looks like a function that is being immediately executed:
function a() {
return "b";
}()
But in reality, it's just a function declaration followed by an empty expression, which is not allowed:
function a() {
return "b";
}
() // not allowed - empty expression
Ben Alman explains this in his article on IIFE's:
When the parser encounters the function keyword in the global scope or
inside a function, it treats it as a function declaration (statement),
and not as a function expression, by default.
...
While parens placed after an expression indicate that the expression
is a function to be invoked, parens placed after a statement are
totally separate from the preceding statment, and are simply a
grouping operator (used as a means to control precedence of
evaluation).
The grouping operator needs to contain an expression to evaluate. By itself it's of no meaning:
() // meaningless
2 + 3 * 4 // 15
(2 + 3) * 4 // 20
In IIFE's, the outer parentheses are just a means of forcing the parser to expect an expression.
This is why the expression var c = function() { return "b"; }(); also works; it's because the parser knows to expect an expression because of the assignment to c.
Side Note
Alman also recommends against using self-invoking functions without using the outer parentheses when assigning to variables(i.e. var v = function(){...}()) because it's bad practice:
In cases where the extra “disambiguation” parens surrounding the
function expression are unnecessary (because the parser already
expects an expression), it’s still a good idea to use them when making
an assignment, as a matter of convention.
Such parens typically indicate that the function expression will be
immediately invoked, and the variable will contain the result of the
function, not the function itself. This can save someone reading your
code the trouble of having to scroll down to the bottom of what might
be a very long function expression to see if it has been invoked or
not.

Why can I not .bind(this) when a function is directly declared

Given the following:
function x() {
this.abc = 1;
function f1() {
alert(this.abc);
}.bind(this)
var f2 = function b() {
alert(this.abc);
}.bind(this);
}
What I would like is for the "this" of the outer function to be available inside the f1 and f2 functions.
Why is it that VS2013 tells me there's a syntax error with the bind(this) on function f1() ?
There's a difference between a function declaration statement and a function instantiation expression. Both involve the keyword function, but a declaration statement cannot immediately be used as a reference to a function. A function instantiation expression is part of the expression grammar, so it can be used freely in that context as a reference to a function because that's what it evaluates to.
You can of course do this:
(function a() {
}).bind(this);
though without using the return value from .bind() it's not very useful.
If the first token in a statement is function, then you've got a function declaration statement. If the first token is not function, then you've either got another sort of keyword-introduced statement (for, return, var, try, whatever), or else you've got an expression statement. In that expression (or in any expression in another context), your function instantiations are part of the expression grammar and the value can be used as a reference to a function.
Here's another way to think about the problem. Let's pretend that there is only one way to instantiate a function in JavaScript, and that's the function expression. That is, let's pretend that any use of the function keyword means to instantiate a function and return a reference to that function as it's value.
Now, thinking generally about expressions and the things that participate in expressions, the point is to compute some sort of value. When you need the value 5 as part of an expression, you put 5 in its place and that's that. By itself, 5 is a valid expression, so this is not a syntax error:
5;
What does that do, however? It does nothing. Similarly, in our make-believe JavaScript without function declaration statements,
function foo(a, b) {
return a + b;
};
would also do nothing at all. What would happen is simply that the function would be instantiated but thrown away because the value — the reference to the instantiated function — is not saved as the value of a variable or passed to some function or anything else. In this make-believe JavaScript, you'd use
var foo = function(a, b) {
return a + b;
};
all the time.
The language design does have function declaration statements, however. As a simplifying approach, the language just recognizes a statement whose first token is the keyword function as a completely different sort of statement than an expression statement that happens to contain a function instantiation. There are other ways in which the problem could have been addressed (such as the use of a different keyword), but I suspect that there'd still be confusion.
Note that there are JavaScript programmers who strongly prefer using var declarations for functions. It's a matter of style really.

Detail of operation of !function() { return false; } ()

!function() { return false; } ()
I'm aware why you might write something like this, but I have a question about the way it works. As I understand it, the exclamation mark does two things:
It acts on function() { return false; }, changing it into an expression
It also acts on the result of the executed function, so that the whole line evaluates to true
So my questions are:
Is this the correct explanation?
If it is correct, then since () binds more tightly than !, how did the first part (the change of the function itself into an expression) happen? Why doesn't the exclamation mark act on the whole line throughout?
according to operator precedence, the function declaration (which is shorthand for new Function) would happen first, the function call () would happen second, and the negation ! would happen last.
edit for clarity: You could rewrite that one line as this to accomplish the same thing:
// declare an anonymous function and assign it to the myFunc variable
var myFunc = function () {
return false;
};
// execute the function and store it's return value (false) in returnValue
var returnValue = myFunc();
// negate the return value (true)
var output = !returnValue;
1) It doesnt "change" it. It makes so when the parser goes through the "function" bit it goes expecting an expression, so the "function" is parsed as part of an (possibly anonymous) function expression instead of as a function statement.
2) It is acting on the whole line. If you look at the precedences, as suggested by jbabey, you see that function call binds more tightly then the negation operator so the whole like is evaluated as
! ((function(){})());
Or in a similar, perhaps more readable version:
var f = function(){ ... };
! (f());

Categories

Resources