Function names ending with () - javascript

How does JavaScript deal with functions with names ending with ()? Consider for example the following piece of code:
var foo() = function () { }; // The empty function
var bar = function(foo) { var myVariable = foo(); };
It seems like there are two possible interpretations for what foo(); means:
Execute the argument foo. This assigns myVariable the returned value of foo.
Consider foo() as the name of the function defined at first. This assigns myVariable the empty function.
Is this even legal code? If so, what are the rules?

Is this even legal code?
No:
var foo() = function () { };
should be:
var foo = function () { };
If so, what are the rules?
In this case the foo argument will have precedence because it is defined in an inner scope than the foo function. So it's really a matter of scope: where is the variable defined. The interpreter first starts by looking in the innermost scope of the code, then in the outer, ... until it reaches the global scope (the window object).
So for example the result of the following code will be 123 as seen in this live demo:
var foo = function () { alert('we are in the foo function'); };
var bar = function(foo) { var myVariable = foo(); alert(myVariable); };
bar(function() { return 123; });

The () isn't considered part of the name. You'll probably get a syntax error. You can find some naming rules here.

In javascript, brackets mean execute. So your code will fail as it will be looking for a function foo on the first line.

Identifiers may not contain any parentheses, so the first statement is illegal. The second, however, is fine, myVariable = foo() executes the foo parameter and assigns the return value.

Do you really mean "Can I pass functions as references?" If so, then the answer is yes:
var foo = function() { return 2; }
var bar = function(fn){ return fn(); }
var two = bar(foo);

Related

How can an object access function expression?

For example:
(function foo() {
var a = 3;
console.log(a);
});
var obj = {
a: (function foo() {
var a = 2;
console.log(a);
})
};
obj.a(); // 2
foo(); // ReferenceError: Not Defined
How is that I can access a function expression within obj, but not in the global object?
Edits: for cohesion and clarity
You're confusing a couple of different things here.
Your first statement is a function expression, not a function declaration:
(function foo() {
var a = 3;
console.log(a);
});
This happens to be a named function expression ("foo"), but it does not introduce a variable foo in this scope. If you wanted to introduce foo so that it can be called again, you need either a function declaration...
function foo() {
var a = 3;
console.log(a);
}
foo();
or, you need to assign the function expression to a variable:
var foo = function () {
var a = 3;
console.log(a);
}
foo();
Your next bit of code, the object declaration, effectively does this by assigning the function expression to a variable, obj.a:
var obj = {
a: (function foo() {
var a = 2;
console.log(a);
})
};
The error in your thinking here is due to confusion around foo. In both cases, foo is the name of the function, but it's not actually relevant to invoking the function. You should drop the foo because it's only confusing things.
In essence, your first snippet is equivalent to:
(function () { alert('x'); });
This line of code defines an anonymous function, but does nothing with it. The function exists briefly, is never invoked, and then is lost, because it is not assigned to anything.
Your second snippet is equivalent to:
var x = function () { alert('y') };
This code defines a variable, x, and assigns a function to it. The function can then be invoked with x(), and the function remains available as long as x is in scope.
Your original question is:
How can an object access function expression?
Which doesn't really make sense. The object can't "access the function expression", it just contains a property to which a function has been assigned, while the snippet outside the object did not retain the function in a way that would allow you to invoke it.

What will the reference be when a variable and function have the same name?

I have a variable named foo and function named foo.
//variable followed by function declaration
var foo="bar";
function foo(){
return "bar";
}
//function declaration followed by variable
function foo(){
return "bar";
}
var foo="bar";
//When I call foo it returns string bar;
//When I enquired foo() it throws error
What's happening here?Why does the variable name override function declaration?
When I call foo it returns string bar;
Function declarations are hoisted to the top of their scope. The function definition are moved above by the compiler. And then the variable is overwriting to string.
Code is equivalent as
function foo() {
return "bar";
}
// Overwriting the value
var foo = "bar"
So, in both the cases, the output will be 'bar'.
Note that function expressions are not hoisted.
For more information on function hoisting, see Javascript function scoping and hoisting
When I enquired foo() it is undefined
foo here is not a function, it's a string. So, foo() will throw an error
Uncaught TypeError: a is not a function(…)
In a clearer and more explicit way of declaring variables, the latter will take account:
var foo = "bar";
var foo = function () {
return "bar";
};
console.log(foo);
output is a function
and the reversal:
var foo = function () {
return "bar";
};
var foo = "bar";
console.log(foo);
has "bar" as output.
In JavaScript, functions are processed upon entering the corresponding scope.
The variables are processed when the interpreter gets to their declaration.
Therefore in your example, the functions are processed first, the name foo is used by the last function and then overwritten by the variables.
Note that if you declare your function like this
var foo = function() {}
it is actually not processed at the beginning and also overwriting the variables declared beforehand.
var foo="bar";
var foo = function(){
return "bar";
};
They are the same. Don't miss to put ; in the end of line.
both cases will return the string "bar"
basically javascript grabs all functions and put them in the top of the file
its called hoisting .
so the string declaration will overwrite the function expression in both cases ;

Non-unique variable names in JS

Is it valid to use variable names again and again? For example:
function clicks() {
var foo = document.getElementById("cat");
foo.click();
var foo = document.getElementById("dog");
foo.click(); // Again! This works, but may be it is not valid?
}
Or I should use unique variable names, like below?
function clicks() {
var foo1 = document.getElementById("cat");
foo1.click();
var foo2 = document.getElementById("dog");
foo2.click();
}
Yes, it is valid. This is because the interpreter "hoists" the variable declaration. That is, it moves the declaration to the top of the current function scope.
To the interpreter, your code "looks" like this:
function clicks () {
var foo;
foo = /* something */
foo = /* something */
}
Now, if you don't want this behavior, you can use let, which stays at the current scope. For example:
function bar () {
if (true) {
let foo = 5
}
console.log(foo) // not defined
// you would need to declare foo again with `let foo = ...`
}
There's nothing wrong with overwriting the value of a variable. Do note that it can make the behavior of your application more confusing, e.g., if someone reading through your code misses where you redeclare the variable. Note that after you've declared it once you can just do foo = document.getElementById("dog"); instead of var foo = document.getElementById("dog");.
Technically, yes, you can use multiple variables with the same name but they all of them will share the same entity. It will be just one variable under that name.
But practically you should avoid that.
You can't re instantiate a variable in js so the var foo twice should not even work:/
the solution is to use something like this
function clicks() {
var foo = document.getElementById("cat");
foo.click();
//remove var in this line...
foo = document.getElementById("dog");
foo.click(); // Again! This works, but may be it is not valid?
}

Scope of variables (Hoisting) in Javascript

One of my friends was taking an online quiz and he asked me this question which I could not answer.
var global = false;
function test() {
global = true;
return false;
function global() {}
}
console.log(global); // says false (As expected)
test();
console.log(global); // says false (Unexpected: should be true)
If we assume that functions are hoisted at the top along with var variables, let's try this one.
var foo = 1;
function bar() {
return foo;
foo = 10;
function foo() {}
var foo = 11;
}
bar();
console.log(foo); //says 1 (But should be 11) Why 1 this time ??
Here is a JSBin Demo and JSBIN Demo2 to play with.
PS: If we remove function global() {} from test(), then it runs fine. Can somebody help me understand why is this happening ?
var statements and function declaration statements are "hoisted" to the top of their enclosing scope.
Therefore, the function global(){} in your function creates a local global name.
Assigning to global inside your functions binds to this local name. Here's how you can "rewrite" it using hoisting to understand how the compiler sees it:
function test() {
var global = function() {}; // hoisted; 'global' now local
global = true;
return false;
}
I'll answer the second part of your question,
If we assume that functions are hoisted at the top along with var variables
bar();
console.log(foo); //says 1 (But should be 11) Why 1 this time ??
You should try console.log(bar()); console.log(foo); instead. However, what hoisting does to your function is this:
function bar() {
var foo;
function foo() {}
return foo;
foo = 10;
foo = 11;
}
So you should expect to get the function returned, since your variable assignments are after the return statement. And both the var and the function declaration make foo a local variable, so the global foo = 1 is never changed.

Javascript Function-Pointer Assignment

Consider this javascript code:
var bar = function () { alert("A"); }
var foo = bar;
bar = function () { alert("B"); };
foo();
When running this code I get "A". Is this behavior a part of javascript specification and can I rely on it?
In other examples, nothing was passed by value; everything was passed by reference.
bar and foo are BOTH pointers
All vars/handles to NON primitive objects in javascript are pointers; pointers ARE native to javascript, they are the default.
var bar = function () { alert("A"); } //bar is a pointer to function1
var foo = bar; //pointer copied; foo is now also a pointer to function1
bar = function () { alert("B"); }; //bar points to function2
foo(); //foo is still a pointer to function1
You will run into hidden errors and bugs if you think they are copies. Especially so if you work with complex objects. For example
function person(name){this.name = name}
var john = new person("john")
var backup = john
backup.name //john
john.name = "jack"
backup.name //jack, NOT john
To really COPY a non-primitive in javascript takes more work than just a = b.
For example:
function person(name){ this.name = name}
var john = new person("john")
var backup = new Object()
backup = JSON.parse(JSON.stringify(john))
backup.__proto__ = john.__proto__ //useful in some cases
john.name = "jack"
backup.name //john
Yes that is expected and by design.
Your question is basically: does foo reference bar as a pointer or reference would in another language?
The answer is no: the value of bar at the time of assignment is assigned to foo.
I'm a bit late here but I thought I'd give an answer anyways and flesh something out.
It's best not to think in terms of pointers and memory references when discussing the internals of JavaScript (or ECMAScript) when dealing with the specifications. Variables are environment records internally and are stored and referenced by name, not memory address. What your assignment statement is doing, internally and by design, is looking up the environment record name (either "foo" or "bar") and assigning the value to that record.
So,
var bar = function () { alert("A"); }
is assigning the environment record "bar" the value (anonymous function).
var foo = bar;
internally calls GetValue("bar") which retrieves the value associated with the record "bar" and then associates that value with the record "foo". Hence, afterwards the original value of bar can still be used as it's now associated with foo.
Because JavaScript references by string and not memory address is precisely why you can do things like this:
someObject["someProperty"]
which is looking up the value based on the property name.
You are assigning the value of an anonymous function to a variable not a pointer.
If you want to play with pointers, you can use objects that are passed by reference, not copy.
Here are some examples:
"obj2" is a reference of "obj1", you change "obj2", and "obj1" is changed. It will alert false:
var obj1 = {prop:true},
obj2 = obj1;
obj2.prop = false;
alert(obj1.prop);
"prop" points to a property that is not an object, "prop" is not a pointer to this object but a copy. If you change "prop", "obj1" is not changed. It will alert true:
var obj1 = {prop:true},
prop = obj1.prop;
prop = false;
alert(obj1.prop);
"obj2" is a reference to the "subObj" property of "obj1". if "obj2" is changed, "obj1" is changed. It will alert false:
var obj1 = {subObj:{prop:true}},
obj2 = obj1.subObj;
obj2.prop = false;
alert(obj1.subObj.prop);
Yes, there's nothing special about the fact that the variables are referring to functions, there's no aliasing involved.
var bar = 1;
var foo = bar;
bar = "something entirely different";
// foo is still 1
Yes, this is the correct behavior.
//create variable bar and assign a function to it
var bar = function () { alert("A"); }
//assign value of bar to the newly created variable foo
var foo = bar;
//assign a new function to the variable bar
//since foo and bar are not pointers, value of foo doesn't change
bar = function () { alert("B"); };
//call the function stored in foo
foo();
This is assigning a variable to an unnamed function, not a pointer to a function
Yes, you've created a pointer to the original "A" function. When you reassign bar, you're reassigning it, but you're still leaving any references to the old function alone.
So to answer your question, yes, you can rely on it.
Those are not function pointers (and there are no pointers in JS natively). Functions in JS can be anonymous and are first class objects. Hence
function () { alert("A"); }
creates an anonymous function that alerts "A" on execution;
var bar = function () { alert("A"); };
assign that function to bar;
var foo = bar;
assign foo to bar, which is the function "A".
bar = function () { alert("B"); };
rebind bar to an anonymous function "B". This won't affect foo or the other function "A".
foo();
Call the function stored in foo, which is the function "A".
Actually in languages where there are function points e.g. C it won't affect foo either. I don't know where you get the idea of getting "B" on reassignment.
void A(void) { printf("A\n"); }
void B(void) { printf("B\n"); }
typedef void(*fptr_t)(void);
fptr_t foo = A;
fptr_t bar = foo;
bar = B;
foo(); // should print "A"
I would just like to add this also works for pre-defined named functions as well:
function myfunc() { alert("A"); }
var bar = myfunc;
var foo = bar;
bar = function () { alert("B"); };
foo();
This will do the same thing, indicating that function names act like array names (pointers).
For each FunctionDeclaration f in code, in source text order do:
Let fn be the Identifier in FunctionDeclaration f.
Let fo be the result of instantiating FunctionDeclaration f as described in Clause 13.
Let funcAlreadyDeclared be the result of calling env’s HasBinding concrete method passing fn as the argument.
If funcAlreadyDeclared is false, call env’s CreateMutableBinding concrete method passing fn and configurableBindings as the arguments.
References
ECMAScript-5: Section 10.5

Categories

Resources