Javascript for Beginners
Part 2: Advanced Javascript
By Dallin Osmun
@dallinosmun
If you haven't seen part 1, go back and watch it!
Lexical Scoping
Hoisting
This
First Class Functions
Asynchronous Coding
Prototypical Inheritance
Tips and Tricks
Lexical Scoping
Scoping works very differently in Javascript and is one of the main things that trips up experienced developers. Variables aren't hidden inside blocks (like if-statements and loops) but only in functions.
For Example:
if (true) {
    var foo = 'bar';
}
console.log(foo); // returns 'bar'
Is perfectly valid in Javascript whereas in a more classical language like C++, you'd get a sytax error.
This is where immediate functions come in. If you really need to encapsulate your data, do it with a function.
(function () {
    var foo = 'bar';
}());
console.log(foo); // returns undefined
Don't let this trip you up!
for (var i = 0; i < 10; ++i) {
    console.log(i);
}
for (var i; i < 10; ++i) {
    // this will never get called!! By the
    // time the code gets here, i is set to 10
}
This is a common technique for hiding your private data and giving public methods to manipulate it:
var counter = (function () {
    var count = 0;
    return {
        increment: function () {
            count++;
        },
        getCount: function () {
            return count;
        }
    };
}());
counter.increment(); // increments the count
counter.getCount();  // returns 1
Hoisting
Because of Lexical Scoping, Javascript Compilers perform an action called Hoisting before actually running your code. Hoisting is where all of your variables get raised to the top of the scope they belong to. They're declared at the top and initialized where you initialized them.
For Example, this code:
for (var i = 0; i < 10; ++i) {
    var b = i * 3;
    console.log(b);
}
becomes this:
var i = undefined;
var b = undefined;
for (i = 0; i < 10; ++i) {
    b = i * 3;
    console.log(b);
}
This becomes more apparent and relevant when trying to fix bugs like this:
console.log(foo); // returns undefined!
// do something
var foo = 'baz';
What's actually happening is this:
var foo = undefined; // foo is hoisted, it's value is not
console.log(foo);
// do something
foo = 'baz'; // foo doesn't get initialized til here
This works because the function isn't run until after bar is declared.
var foo = function () {
    console.log(bar);
};
var bar = "hey world";
foo(); // displays 'hey world'
What the code looks like after hoisting:
var foo = undefined;
var bar = undefined;
foo = function () {
    console.log(bar);
};
bar = "hey world";
foo(); // displays 'hey world'
var foo = "bar";
(function () {
    console.log(foo); // prints undefined?
    var foo = "baz";  // scoped variable that hides the other foo
    console.log(foo); // prints baz
}());
Actually looks like:
var foo = undefined;
foo = "bar";
(function () {
    var foo = undefined;
    console.log(foo); // prints undefined?
    foo = "baz";  // scoped variable that hides the other foo
    console.log(foo); // prints baz
}());
Here's why we use the javascript style of function declaration.
foo();
bar();
function foo() {        // bad way
    console.log('foo called');
};
var bar = function () { // good way
    console.log('bar called');
};
// outputs: foo called
//          Type Error!!
Here's what hoisting does to that problem. bar() behaves like expected. You can't call it until it's declared. foo() on the other hand has all of it's code hoisted with it.
function foo() {
    console.log('foo called');
};
var bar = undefined;
foo();
bar();
bar = function () {
    console.log('bar called');
};
This

Tom Valletta has a great presentation about this. I highly recommend reading through it.

This will trip you up. A Lot. Unless you learn to get it down right now and practice it tons. This changes based on how the function was called.

First of all, if you just reference this from your code, you'll get the global object.
console.log(this);
// this is the global window object
In a baseless function, this references the window object. In a method, it references it's object.
var foo = function () {
    console.log(this);
}
foo(); // this is the global window object
var myObj = { foo: foo };
myObj.foo(); // this is myObj
When using call() or apply(), this references whatever context you passed in.
var foo = function (a, b) {
    console.log((a + b) + " " + this);
}
foo.apply(Window, [1, 2]);
foo.call(Window, {'0': 1, '1': 2});
// output for both of these is '3 Window'
// this is only because I passed Window in as the context
In a constructor, this references the object you are making.
var Person = function (name) {
    this.name = name;
    return this;
};
var fred = new Person('fred');
// this references fred
Be careful with how you call your functions. You can get some pretty unexpected results. In the following example, this references myObj when called as a method and then the Window object when called as a baseless function.
var myObj = {
    age: 21,
    getAge: function () {
        return this.age;
    }
};
myObj.getAge(); // returns 21;
var functionCaller = function (func) {
    func();
};
functionCaller(myObj.getAge); // returns undefined
First Class Functions
Coming Soon!
Asynchronous Coding
Coming Soon!
Prototypical Inheritance
Coming Soon!
Tips and Tricks
Coming Soon!

Thanks for watching!