HI and thanks for taking the time. When you add a function as an accessible property of a module and expose it through the return statement. In other words, if you have an object and add a property such that "name:function(){return;}:" and expose that through the return statement of the module or object. is this an expression or a declaration? Once again thanks
I apologize I am not having a great day, no I am not taking a test but I described this incorrectly. When you export functions declared in a module, are they declarations or expressions? Thanks for your patience
A value part of an object literal, such as in a name: function(){return;} property, is an expression.
An expression is any valid set of literals, variables, operators and expressions that evaluates to a single value. We distinguish expressions to
Assignment Expressions - x = 7
Evaluation expressions - 3 + 4 - commonly written in curly brackets (x + y)
While what our goal behind these two expressions is different, it doesn't matter if they consist of 3 characters or a code that goes to 40 lines*, in the end, they all evaluate to a single decisive value, be it certain primitive value (number, string, boolean, null, undefined, symbol) or an object
Meanwhile, a declaration is well.. precisely as a name suggests.. a declaration of something
var x;
declares an undefined variable of name x
functions in javascript are simply sub-types of the object data type. So by doing
function foo (){} We simply declare an object (function) that to the top of the module.
Keep in mind, declaration and expressions do not have to be some sort of separate techniques that may never be combined, in fact, in real JS world it's quite the opposite:
var obj = {
foo: function bar() { console.log('baz'); }
};
Contains declaration of object obj. Assignment expression and declaration of function bar to the propety foo and also expression of the function bar itself.
Perhaps a much easier way to comprehend this would be:
var x = 7;
Where we first declare a variable x (var x) which is hoisted by the compiler to the top of our scope and then we assign it x = 7; but as a line by itself, it contains both a declaration and an expression
Related
This may be a silly question, but why are function arguments in JavaScript not preceded by the var keyword?
Why:
function fooAnything(anything) {
return 'foo' + anyThing;
}
And not:
function fooAnything(var anything) {
return 'foo' + anyThing;
}
I have a feeling the answer is because that's what the Spec says but still...
Most dynamicaly-typed programming languages don't have explicit vars in the argument list. The purpose of the var keyword is to differentiate between "I am setting an existing variable" and "I am creating a new variable" as in
var x = 17; //new variable
x = 18; //old variable
(Only few languages, like Python, go away with the var completely but there are some issues with, for example, closures and accidental typos so var is still widespread)
But in an argument list you cannot assign to existing variables so the previous ambiguity does not need to be resolved. Therefore, a var declaration in the arguments list would be nothing more then redundant boilerplate. (and redundant boilerplate is bad - see COBOL in exibit A)
You are probably getting your idea from C or Java but in their case type declarations double up as variable declarations and the cruft in the argument lists is for the types and not for the declarations.
We can even get away with a "typeless, varless" argument list in some typed languages too. In Haskell, for example, types can be inferred so you don't need to write them down on the argument list. Because of this the argument list consists of just the variable names and as in Javascript's case we don't need to put the extraneous "let" (Haskell's equivalent to "var") in there:
f a b = --arguments are still variables,
-- but we don't need "let" or type definitions
let n = a + b in --extra variables still need to be declared with "let"
n + 17
It would be a redundant use of the var keyword. Items that appear in the parentheses that follow a function name declaration are explicitly parameters for the function.
The var keyword declares the scope of the variable. A function argument also introduces the scope for that argument. Hence there's no need for it, since it serves the same function.
I think the question comes up because we're used to seeing function bla (int i) in many languages. The same, syntactically, as the int i; somewhere in the function body to declare a variable. The two ints are however not doing the same; the first defines the type, the second defines type and the scope. If you don't have to declare the type, the scope-declaration still needs to happen (which is why we have var in the second case) but there is no information needed in front of arguments.
As per the Mozilla docs in order to execute a function using eval it must be wrapped inside ( ) i.e. if you don't use them then it treated as a string.
eval as a string defining function requires "(" and ")" as prefix and suffix
when I execute normal function it returns undefined as expected but not in the case of ES6 functions. My Question is ES6 functions are treated differently by javascript engines or only within eval function.
var fn = "function a(){}";
var es6fn = "()=>{}";
console.log(eval(fn)); // undefined
console.log(eval(es6fn)); // ()=>{}
console.log(typeof eval(es6fn)); // ()=>{} i.e. a function
Lets take a step back and see what is actually going on here. I think you are misunderstanding the point MDN is trying to make. The only function that is executed in your example is eval. The (...) the documentation is mentioning are not for executing the function inside the string but for changing how the function definition is evaluated.
A function call would function a(){}() but the docs talk about putting the function definition inside parenthesis: (function(){}).
There are basically thee major ways to define functions:
Function declaration
function foo() {}
Function expression
var foo = function() {}
Arrow function
var foo = () => {}
To understand the difference between a function declaration and a function expression, we have to understand the difference between statements and expressions (a declaration is basically like a statement).
A statement is something that has side effects and does not produce a value. if, for, switch, etc are all statements.
An expression is something that produces a value. E.g. 5 is a number literal that produces the value 5. 5 + 3 is an expression that computes the sum of the two literals, i.e. evaluating it will return the value 8.
A function declaration is like a statement. It doesn't produce a value itself, but as a side effect, a variable is defined whose value is a function (you can see in the specification that nothing happens when a function declaration is evaluated (they have already been processed at that point)).
A function expression is very similar, but instead of defining a variable, evaluating it simply results in the function object.
And that is the reason why
eval('function a() {}') // undefined, but a is defined as side effect
eval('(function a() {})') // a function object
produce different results. The first is interpreted as function declaration. A variable a will be created, but no value is created that eval could return. In the second case, the grouping operator ((...)) forces the function definition to be interpreted as a function expression, which means that a value is produced and return by eval.
Now regarding arrow functions: There is no ambiguity here. Arrow function definitions are always expressions, i.e. evaluating them always produces a value.
eval(`() => {}`) // a function object
To sum up
While there is a difference between arrow functions and function declarations/expressions, this difference is not the reason for the results you are seeing with eval. The difference here is because of evaling a statement/declaration and an expression.
In your example, a is declared as it's a named function. In the second case, you just write an expression which is a lambda function. See here and here.
If you want to get the same effect for fn, do
`console.log(eval("var a = function(){}"))`; //`function(){}`.
First of all, EcmaScript is the "official" name for JavaScript. Now that ES2015 is finalised, it effectively just becomes JavaScript v6 to most people. So, this difference does not come from the different engin.
The origin of the different behavior comes from the result of the string which is written in the eval function. the result of the first eval string is a function definition and there is not anything to return. On the other side, the second eval is evaluating a lambda function, so the result of the eval is that function. To clear this concept, you can rewrite the code like the following:
var fn = "function a(){ return 1;}";
var es6fn = "()=>{}";
console.log(eval(fn)); // undefined
console.log(eval(es6fn)); // ()=>{}
console.log(typeof eval(es6fn)); // ()=>{} i.e. a function
console.log(a()); // call the a() function
As, you can see, the a() is defined as a function, and you can use the function after the first eval. So, the first eval is run and all back to the return value for eval function.
The documentation says nothing on function execution. The functions won't be executed, unless they are executed explicitly like (() => {})().
The quote
eval as a string defining function requires "(" and ")" as prefix and suffix
refers to interpreting the string as function expression rather than function declaration.
// will throw SyntaxError
// because function declaration requires a name
typeof eval('function (){}');
typeof eval('function a(){}') === 'undefined';
typeof eval('(function a(){})') === 'function';
typeof eval('null, function a(){}') === 'function';
typeof eval('()=>{}') === 'function';
Arrow function is always an expression, it doesn't need auxiliary constructions like comma or parentheses to interpret is an expression, here is the difference.
This question already has answers here:
Explain the encapsulated anonymous function syntax
(10 answers)
Closed 7 years ago.
I'm reading up on JavaScript IIFE and so far the understand concept, but I am wondering about the outside parenthesis. Specifically, why are they required? For example,
(function() {var msg='I love JavaScript'; console.log(msg);}());
works great, but
function() {var msg='I love JavaScript'; console.log(msg);}();
generates a syntax error. Why? There are lots of discussions on IIFE, but I'm not seeing a clear explanation about why the parentheses are required.
There are two ways to create functions in JavaScript (well, 3, but let's ignore new Function()). You can either write a function declaration or write a function expression.
A function declaration in itself is a statement and statements by themselves don't return values (let's also ignore how the debugging console or Node.js REPL print return values of statements). A function expression however is a proper expression and expressions in JavaScript returns values that can be immediately used.
Now, you may have seen people saying that the following is a function expression:
var x = function () {};
It may be tempting to conclude that the syntax:
function () {};
is what makes it an expression. But that's wrong. The syntax above is what makes it an anonymous function. And anonymous functions can either be a declaration or an expression. What makes it an expression is this syntax:
var x = ...
That is, everything to the right of an = sign is an expression. Expressions make it easier to write math formulas in programming languages. So in general everywhere that math is expected to be processed is an expression.
Some of the forms of expressions in JavaScript include:
everything to the right of an = operator
things in braces () that are not function call braces
everything to the right of a math operator (+,-,*,/)
all the arguments to the ternary operator .. ? .. : ..
When you write:
function () {}
it is a declaration and does not return a value (the declared function). Therefore trying to call the non-result is an error.
But when you write:
(function () {})
it is an expression and returns a value (the declared function) which may be used immediately (for example, may be called or may be assigned).
Note the rules for what counts as expressions above. From that it follows that braces are not the only things that you can use to construct an IIFE. Below are valid ways for constructing IIFEs (because we write function expressions):
tmp=function(){}()
+function(){}()
-function(){}()
0/function(){}()
0*function(){}()
0?0:function(){}()
(function(){}())
(function(){})()
You may actually see one of the above non-standard forms (particularly the + version) in third-party libraries, because they want to save one byte. But I strongly advise you to only use the brace forms (either are fine), because they are widely recognized as IIFEs by other programmers.
The version of IIFE that is wrapped in parenthesis works, because this marks the declaration of the internal function declaration as an expression.
http://benalman.com/news/2010/11/immediately-invoked-function-expression/
For more detailed explanation please see:
Advanced JavaScript: Why is this function wrapped in parentheses?
HINT:
The invocation operator (()) only works with expressions, not declarations.
This will be a long-winded answer, but will give you the necessary background. In JavaScript there are two ways functions can be defined:
A function definition (the classical kind)
function foo() {
//why do we always use
}
and then the more obscure type, a function expression
var bar = function() {
//foo and bar
};
In essence the same thing is going on at execution. A function object is created, memory is allocated, and an identifier is bound to the function. The difference is in the syntax. The former is itself a statement which declares a new function, the latter is an expression.
The function expression gives us the ability to insert a function any place where a normal expression would be expected. This lends its way to anonymous functions and callbacks. Take for instance
setTimeout(500, function() {
//for examples
});
Here, the anonymous function will execute whenever setTimeout says so. If we want to execute a function expression immediately, however, we need to ensure the syntax is recognizable as an expression, otherwise we have ambiguity as to whether of not we mean a function expression or statement.
var fourteen = function sumOfSquares() {
var value = 0;
for (var i = 0; i < 4; i++)
value += i * i;
return value;
}();
Here sumOfSquares is immediately invoked because it can be recognized as an expression. fourteen becomes 14 and sumOfSquares is garbage-collected. In your example, the grouping operator () coerces its content into an expression, therefore the function is an expression and can be called immediately as such.
One important thing to note about the difference between my first foo and bar example though is hoisting. If you don't know what that it is, a quick Google search or two should tell you, but the quick and dirty definition is that hoisting is JavaScript's behavior to bring declarations (variables and functions) to the top of a scope. These declarations usually only hoist the identifier but not its initialized value, so the entire scope will be able to see the variable/function before it is assigned a value.
With function definitions this is not the case, here the entire declaration is hoisted and will be visible throughout the containing scope.
console.log("lose your " + function() {
fiz(); //will execute fiz
buzz(); //throws TypeError
function fiz() {
console.log("lose your scoping,");
}
var buzz = function() {
console.log("and win forever");
};
return "sanity";
}()); //prints "lose your scoping, lose your sanity"
This is what object literal syntax looks like:
var x = {property:value};
Now, please correct me if I am wrong but what I'm looking at is the word "var" here, and that seems to imply "variable". Does this mean that fundamentally "objects" are variables (with the caveat that they behave similar to arrays)? I recently asked a question about whether variables were objects and everyone said no.
But it's strange that the keyword "var" is used when creating an object literal, and if they aren't variables (which I'm assuming for now) why would ecmascript incorporate this use if object literals are not in some way or another variables? It seems syntactically confusing.
The object { property: value } is not a variable, but x is, and that’s what the var refers to. var creates a variable, and optionally gives it a value; x is the variable, and { property: value } is the object you’re assigning to it. The object has nothing to do with a variable. Consider
var x = 5;
5 isn’t a variable.
var x = null;
null isn’t a variable.
console.log({ foo: 70 }.foo + " boxes");
No variables involved here, but there is an object literal, just like 70 is a numeric literal and " boxes" is a string literal.
The variable here is x. You are declaring x and then assigning it to point to an object literal.
Remember that with hoisting, your code ends up being processed like this:
var x;
x = {property:value};
As you can see, it really doesn't matter what you set x to, or even if you don't set it at all. var x declares a variable in the current scope named x.
Playing on JS console I faced a curious syntax. I wonder if someone can tell me more on that..
Try this:
>( function f(){console.log('i am f')} , (function x(){console.log('i am x')})() , y=2 , console.log('hello') )
i am x
hello
undefined
>f()
ReferenceError: f is not defined
>this.y
2
This will fail:
( var c=2 )
SyntaxError: Unexpected token var
So comma separated expressions inside parentheses are evaluated, assignments happens to be against global scope, but named function declarations references stay trapped inside just like a closure
more...
putting that line inside a function declaration called with new:
function C(){
( function f(){console.log('i am f')} , (function x(){console.log('i am x')})() , y=2 , console.log('hello') )
}
and then instantiating:
>var c=new C()
i am x
hello
undefined
>c.y
undefined
>this.y
2
Happens exactly the same, just as executed in the global scope!
What's the usage / purpose of this construct?
One more:
>( function f(){console.log('i am f')} , f() )
ReferenceError: f is not defined
So the named function can't be referenced neither inside brackets.
The named functions aren't "trapped inside", because they're not function declarations (using function as a statement), they are in fact function expressions (using function as an operator). This means that their names do not become references to themselves in the current namespace.
Certain keyword/tokens can only be used as statements, such as var, hence an error is thrown if you try to use them in conditions which the interpreter expects to be an expression.
As for the y === 2, this is because you did not var y; inside C, so y = 2 sets window.y, and in the global scope this === window.
whats the usage / purpose of this construct?
The comma operator , lets you do multiple expressions on one line.
function expressions are useful for a great many things, be it immediately invoking them so you have a closure, or storing them inside variables, etc.
Wrapping code in parentheses forces it to be parsed as an expression.
The var keyword is only valid as a statement, so this creates a syntax error.
Function declarations can either be statements (which create a hoisted variable) or expressions (which do not create any variable).
Thus, wrapping the function in parentheses turns it into a function expression, which does not create an externally-visible name.
For more information, see here.