Indirect references to functions in javascript - javascript

I was just reading the book, "You don't know JS" by kyle simpson and came across the following sinppet of code that somewhat confused me. basically I was reading a topic on the this keyword. below is the snippet:
function foo() {
console.log( this.a );
}
var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };
o.foo(); // 3
(p.foo = o.foo)(); // 2
So far reading the book I do understand how this works, but for me its hard to understand whats really happening on the last line of the snippet.
if I analysis it bymyself the last line is an iffe executing in the global scope and if in the iffe the foo() fuction executes, the this.a in the foo() function will point to the a in the global scope, which is indeed 2.
But somehow I don't feel i totally understand whats happening on the last line, can somebody break it down for me?
Thank you.
Alexander.

The final line is passing along the reference to the foo function and then executing in the global scope, just as you see. It is equivalent to this
var f = p.foo = o.foo;
f();

The return value of an assignment is always the value itself. At this example the return value is a reference to the function foo. Therefore two steps are executed on one line.
p.foo = o.foo;
foo();

This is whats happening:
when (p.foo = o.foo)(); is called, JS transforms it into
function foo() {
console.log( this.a );
}
and since var a = 2 is set in the global scope, and nothing is passed to the function, your result is 2
So then the question is why does JS transform (p.foo = o.foo) into the foo() function?
well if you break it down, you have this:
p.foo = o.foo : this is assigning the variable from right to left. Just like var a = "something"; so this means that now, p.foo equals o.foo, and since o.foo equals foo, we are now saying p.foo = foo, in other words this:
(p.foo = o.foo)(); is the same as (foo)() which then runs the foo function.
To further explain:
console.log(p.foo); //returns undefined because nothing was set to it
console.log(o.foo); //returns foo, because it was assigned var o = {foo: foo};
p.foo = o.foo; // this assignes foo to p.foo
console.log(p.foo); //returns foo, it is no longer undefined, because of our assignment
(p.foo)(); // will run the function
I had problems with getting undefined before, but that was because I was running tests on http://jsfiddle.net/ which prevented me from accessing my function correctly.

Related

module.exports.variable vs module.exports={variable} [duplicate]

Original Question:
JSHint complains when my JavaScript calls a function that is defined further down the page than the call to it. However, my page is for a game, and no functions are called until the whole thing has downloaded. So why does the order functions appear in my code matter?
EDIT: I think I may have found the answer.
http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
I am groaning inside. Looks like I need to spend ANOTHER day re-ordering six thousand lines of code. The learning curve with javascript is not steep at all, but it is very loooooong.
tl;dr If you're not calling anything until everything loads, you should be fine.
Edit: For an overview which also covers some ES6 declarations (let, const): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Scope_Cheatsheet
This weird behavior depends on
How you define the functions and
When you call them.
Here's some examples.
bar(); //This won't throw an error
function bar() {}
foo(); //This will throw an error
var foo = function() {}
bar();
function bar() {
foo(); //This will throw an error
}
var foo = function() {}
bar();
function bar() {
foo(); //This _won't_ throw an error
}
function foo() {}
function bar() {
foo(); //no error
}
var foo = function() {}
bar();
This is because of something called hoisting!
There are two ways to define functions: Function declaration and function expression. The difference is annoying and minute, so let's just say this slightly wrong thing: If you're writing it like function name() {}, it's a declaration, and when you write it like var name = function() {} (or an anonymous function assigned to a return, things like that), it's a function expression.
First, let's look at how variables are handled:
var foo = 42;
//the interpreter turns it into this:
var foo;
foo = 42;
Now, how function declarations are handled:
var foo = 42;
function bar() {}
//turns into
var foo; //Insanity! It's now at the top
function bar() {}
foo = 42;
The var statements "throws" the creation of foo to the very top, but doesn't assign the value to it yet. The function declaration comes next in line, and finally a value is assigned to foo.
And what about this?
bar();
var foo = 42;
function bar() {}
//=>
var foo;
function bar() {}
bar();
foo = 42;
Only the declaration of foo is moved to the top. The assignment comes only after the call to bar is made, where it was before all the hoisting occurred.
And finally, for conciseness:
bar();
function bar() {}
//turns to
function bar() {}
bar();
Now, what about function expressions?
var foo = function() {}
foo();
//=>
var foo;
foo = function() {}
foo();
Just like regular variables, first foo is declared at the highest point of the scope, then it is assigned a value.
Let's see why the second example throws an error.
bar();
function bar() {
foo();
}
var foo = function() {}
//=>
var foo;
function bar() {
foo();
}
bar();
foo = function() {}
As we've seen before, only the creating of foo is hoisted, the assignment comes where it appeared in the "original" (un-hoisted) code. When bar is called, it is before foo is assigned a value, so foo === undefined. Now in the function-body of bar, it's as if you're doing undefined(), which throws an error.
The main reason is probably that JSLint does only one pass on the file so it doesn't know you will define such a function.
If you used functions statement syntax
function foo(){ ... }
There is actually no difference at all where you declare the function (it always behaves as if the declaration is on the beginning).
On the other hand, if your function was set like a regular variable
var foo = function() { ... };
You have to guarantee you wont call it before the initialization (this can actually be a source of bugs).
Since reordering tons of code is complicated and can be a source of bugs in itself, I would suggest you search for a workaround. I'm pretty sure you can tell JSLint the name of global variables beforehand so it doesn't complain about undeclared stuff.
Put a comment on the beggining of the file
/*globals foo1 foo2 foo3*/
Or you can use a text box there for that. (I also think you can pass this in the arguments to the inner jslint function if you can meddle with it.)
There are way too many people pushing arbitrary rules about how JavaScript should be written. Most rules are utter rubbish.
Function hoisting is a feature in JavaScript because it is a good idea.
When you have an internal function which is often the utility of inner functions, adding it to the beginning of the outer function is an acceptable style of writing code, but it does have the drawback that you have to read through the details to get to what the outer function does.
You should stick to one principle throughout your codebase either put private functions first or last in your module or function. JSHint is good for enforcing consistency, but you should ABSOLUTELY adjust the .jshintrc to fit your needs, NOT adjust your source code to other peoples wacky coding concepts.
One coding style that you might see in the wild you should avoid because it gives you no advantages and only possible refactoring pain:
function bigProcess() {
var step1,step2;
step1();
step2();
step1 = function() {...};
step2 = function() {...};
}
This is exactly what function hoisting is there to avoid. Just learn the language and exploit its strengths.
Only function declaration are hoisted not function expression (assignment).

what is the javascript mechanism/rules that allow `p.foo = o.foo` to return a reference to the function `foo`?

I'm currently studying javascript by following the book "you dont know js" series.
In the "this & object prototype" section, when discussing "indirect references to functions", the author states
function foo() {
console.log( this.a );
}
var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };
o.foo(); // 3
(p.foo = o.foo)(); // 2
The result value of the assignment expression p.foo = o.foo is a
reference to just the underlying function object. As such, the
effective call-site is just foo(), not p.foo() or o.foo() as you might
expect. Per the rules above, the default binding rule applies.
So apparently, (p.foo = o.foo) return a reference to the function foo. But what is the mechanism/rules that allow (p.foo = o.foo) return a reference to the function foo? In other words, why a simple assignment return a reference to foo function?
When I want to understand something like this, I find it helpful to break it down step by step.
o.foo looks at the o object and finds a property named foo. It returns a reference that property, whatever it might be. In this case, the o.foo property is a reference to the function foo.
p.foo = o.foo takes the result from above (a reference to the function foo), creates a property in the p object which is also named foo. So now p.foo is also a reference to the foo function, exactly the same thing as o.foo.
That expression is wrapped in parentheses, so now you have whatever was on the left side of the = sign, or p.foo, which is (as a reminder) still a reference to the foo function.
Now we find the () at the end. This calls whatever function we have on hand at this moment. That is the foo function. Note in particular that we are not calling p.foo(). That would be a method call to the function that p.foo is a reference to, so inside that function, this would be set to p. But we're not doing that. We're just calling whatever function was returned by ( p.foo = o.foo ). As before, this is the same foo function, but we've now lost any connection it may have ever had to the o object or the p object.
So, when we make that call at the end, we are merely calling the foo function without setting this to any particular object. Because of that, when we make the call, this is set to undefined.
But we're not running in strict mode, so JavaScript "helpfully" doesn't want to give us an undefined this, so it sets this to the window object in a browser or the global object in Node.
Previously we did var a = 2;. So the window or global object actually now has a property named a, and the value of that property is 2.
So now when we do the console.log(this.a), we pick up the a property from the window or global object. That value is 2.
What if all this code was not running at the global level, but instead it was inside a function? What would happen then?
function test() {
function foo() {
console.log( this.a );
}
var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };
o.foo(); // 3
(p.foo = o.foo)(); // was 2, but now is undefined
}
test();
Now when we call console.log( this.a ); inside foo, this still refers to the window or global object. But when we set var a = 2;, we aren't setting a global property any more. We're just creating a local variable. window.a or global.a is undefined (unless some other code previously set it).
Strict mode avoids some this weirdness. If we put a 'use strict'; at the top of the code, it will compile in strict mode. And now when we make that last function call at the end, where we're calling the foo function (again not as a method!), this is now set to undefined instead of window or global. Therefore, when we try to call console.log(this.a), the code fails because this is the same as undefined, and undefined does not (and couldn't) have an a property.
Let's try it:
'use strict';
function foo() {
console.log( this.a );
}
var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };
o.foo(); // 3
(p.foo = o.foo)(); // was 2 in the original, but now throws an exception
The bottom line, at least for this particular example: always use strict mode! It is your friend.
The assignment operator = is an expression in JavaScript that produces (returns) the assigned value. Because it is an expression it can be used anywhere an expression is allowed, such as inside parenthesis.
For example:
let test = (a = b = c = { name: 'test' })
The code above would first evaluate the expression in the parenthesis and point the variables c, b, and a to the test object (in that order), then it would point test to the produced value from this expression. After that line is executed, a, b, c, and test will all point to the same object.
Similarly,
(p.foo = o.foo)
Would produce o.foo back (technically it would produce whatever o.foo is pointing to, which is the function foo).
As far as
(p.foo = o.foo)()
By adding the additional () after the parenths, we are telling the engine that we want to invoke whatever the expression (p.foo = o.foo) ends up producing. Thus we end up invoking the function foo. Similar patterns is used in IIFEs.
A helpful rewrite would be to think of the line above as doing this:
let produced = (p.foo = o.foo)
produced()
Further reading about statements vs expressions.

Are functions defined regardless of the order?

I'm not really a javascript noob at all, although in my whole life I've never came across this, but am I right in assuming that javascript must assign functions before running anything or something?
In all my experience, I expected this to return 'undefined', but obviously it returns 'function'.
function bar() {
return foo;
foo = 10;
function foo() {}
var foo = '11';
}
alert(typeof bar());
Is someone able to explain this for me?
This behaviour of JavaScript is called hoisting. There is a good explanation on the MDN (https://developer.mozilla.org/en-US/docs/Glossary/Hoisting)
In JavaScript, functions and variables are hoisted. Hoisting is JavaScript's behavior of moving declarations to the top of a scope (the global scope or the current function scope).
That means that you are able to use a function or a variable before it has been declared, or in other words: a function or variable can be declared after it has been used already.
Basically, if you declare a variable like this:
console.log(s); // s === undefined
var s = 'some string';
s declaration will be "hoisted" to the beginning of the scope (i.e. there will be no ReferenceError on the line with console.log). The variable's value will not be defined at that moment though.
The same goes with assigning an anonymous function to a variable, so:
console.log(f); // f === undefined
f(); // TypeError: f is not a function
var f = function () {}; // assigning an anonymous function as a value
f(); // ok, now it is a function ;)
The variable will be hoisted and thus visible in the entire scope, but it's value, even if it's a function, will still be undefined - hence the error if you try to execute it.
On the other hand if you declare a named function:
console.log(f); // f === function f()
f(); // we can already run it
function f() {}; // named function declaration
It's definition will also be hoisted so you can run it even in the first line of the scope you've declared it.
This is quite easily tested;
foo(1);
function foo(i) {
if (bar()) {
alert("foo called, bar true, i = " + i);
};
}
foo(2);
function bar() {
return true;
}
foo(3);
DEMO
This shows that Javascript loads all functions before executing anything. Therefor it does not matter what order functions are defined.
Well in JavaScript function is nothing but Object.
When you say typeof bar(),in the bar function you are returning foo which is another function.You just returning name of the function,So,it return the constructor of the foo function.So,your typeof get the value of foo constructor which is type of function.So,it alert function.It still refer the foo because of closure
Again in the bar defination,you returning foo,but its definition is still not encountered.In JavaScript when while parsing the instruction,declaration of variable and function is placed on top in current function scope.
So,
your statement
function bar() {
return foo;
foo = 10;
function foo() {}
var foo = '11';
}
is equivalent to
function bar() {
function foo() {}
return foo;
foo = 10;
var foo = '11';
This is called JavaScript top hoist
}

Reusable Javascript function

I'm building reusable function, but I can't change global variables values.
var foo = 5;
function MyFunction(arg) {
setInterval(function(){
foo = 2 + arg;
return foo;
}) ;
}
foo = MyFunction(1);
alert( foo );
After function complete I'm getting undefined;
Thanks in advance.
var foo = 5;
function MyFunction(arg) {
foo = 2 + arg;
}
MyFunction(1);
alert( foo );
You assigned the result of MyFunction invocation to foo and that's why you got undefined. MyFunction has no return statement.
ekuusela gives the right answer as to why your (presumably simplified) example doesn't work.
There are lots of reasons why you could have problems with globals, the most common being that you are accidentally clobbering a global by using the same identifier in some other function, and forgetting to declare it locally. To this day I still get problems where I've written for (i=0;i<n;i++) without first declaring var i in that function-- which then uses a global i, and works fine until 6 months later I make the same mistake somewhere else...
As a useful tip for debugging, the expression var G = (function(){return this})() will always give you the global object, no matter where you run it, including eval'd code. You can then access the global variable foo as G.foo, evaluate ('foo' in G) to check whether such a global exists, and so on.
In order to define a global variable you can use variable name without var keyword or define the variable outside any function scope. Then you can access it by the given method :
foo = 5;
function MyFunction(arg) {
window.foo = 2 + arg;
}
MyFunction(1);
alert( window.foo );
Note: Now foo is a part of window object.

JavaScript function order: why does it matter?

Original Question:
JSHint complains when my JavaScript calls a function that is defined further down the page than the call to it. However, my page is for a game, and no functions are called until the whole thing has downloaded. So why does the order functions appear in my code matter?
EDIT: I think I may have found the answer.
http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
I am groaning inside. Looks like I need to spend ANOTHER day re-ordering six thousand lines of code. The learning curve with javascript is not steep at all, but it is very loooooong.
tl;dr If you're not calling anything until everything loads, you should be fine.
Edit: For an overview which also covers some ES6 declarations (let, const): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Scope_Cheatsheet
This weird behavior depends on
How you define the functions and
When you call them.
Here's some examples.
bar(); //This won't throw an error
function bar() {}
foo(); //This will throw an error
var foo = function() {}
bar();
function bar() {
foo(); //This will throw an error
}
var foo = function() {}
bar();
function bar() {
foo(); //This _won't_ throw an error
}
function foo() {}
function bar() {
foo(); //no error
}
var foo = function() {}
bar();
This is because of something called hoisting!
There are two ways to define functions: Function declaration and function expression. The difference is annoying and minute, so let's just say this slightly wrong thing: If you're writing it like function name() {}, it's a declaration, and when you write it like var name = function() {} (or an anonymous function assigned to a return, things like that), it's a function expression.
First, let's look at how variables are handled:
var foo = 42;
//the interpreter turns it into this:
var foo;
foo = 42;
Now, how function declarations are handled:
var foo = 42;
function bar() {}
//turns into
var foo; //Insanity! It's now at the top
function bar() {}
foo = 42;
The var statements "throws" the creation of foo to the very top, but doesn't assign the value to it yet. The function declaration comes next in line, and finally a value is assigned to foo.
And what about this?
bar();
var foo = 42;
function bar() {}
//=>
var foo;
function bar() {}
bar();
foo = 42;
Only the declaration of foo is moved to the top. The assignment comes only after the call to bar is made, where it was before all the hoisting occurred.
And finally, for conciseness:
bar();
function bar() {}
//turns to
function bar() {}
bar();
Now, what about function expressions?
var foo = function() {}
foo();
//=>
var foo;
foo = function() {}
foo();
Just like regular variables, first foo is declared at the highest point of the scope, then it is assigned a value.
Let's see why the second example throws an error.
bar();
function bar() {
foo();
}
var foo = function() {}
//=>
var foo;
function bar() {
foo();
}
bar();
foo = function() {}
As we've seen before, only the creating of foo is hoisted, the assignment comes where it appeared in the "original" (un-hoisted) code. When bar is called, it is before foo is assigned a value, so foo === undefined. Now in the function-body of bar, it's as if you're doing undefined(), which throws an error.
The main reason is probably that JSLint does only one pass on the file so it doesn't know you will define such a function.
If you used functions statement syntax
function foo(){ ... }
There is actually no difference at all where you declare the function (it always behaves as if the declaration is on the beginning).
On the other hand, if your function was set like a regular variable
var foo = function() { ... };
You have to guarantee you wont call it before the initialization (this can actually be a source of bugs).
Since reordering tons of code is complicated and can be a source of bugs in itself, I would suggest you search for a workaround. I'm pretty sure you can tell JSLint the name of global variables beforehand so it doesn't complain about undeclared stuff.
Put a comment on the beggining of the file
/*globals foo1 foo2 foo3*/
Or you can use a text box there for that. (I also think you can pass this in the arguments to the inner jslint function if you can meddle with it.)
There are way too many people pushing arbitrary rules about how JavaScript should be written. Most rules are utter rubbish.
Function hoisting is a feature in JavaScript because it is a good idea.
When you have an internal function which is often the utility of inner functions, adding it to the beginning of the outer function is an acceptable style of writing code, but it does have the drawback that you have to read through the details to get to what the outer function does.
You should stick to one principle throughout your codebase either put private functions first or last in your module or function. JSHint is good for enforcing consistency, but you should ABSOLUTELY adjust the .jshintrc to fit your needs, NOT adjust your source code to other peoples wacky coding concepts.
One coding style that you might see in the wild you should avoid because it gives you no advantages and only possible refactoring pain:
function bigProcess() {
var step1,step2;
step1();
step2();
step1 = function() {...};
step2 = function() {...};
}
This is exactly what function hoisting is there to avoid. Just learn the language and exploit its strengths.
Only function declaration are hoisted not function expression (assignment).

Categories

Resources