CF Objective Notes - Javascript: Understanding the Confusing Bits

May 15, 2014

Javascript: Understanding the Confusing Bits
Jason Dean

JavaScript is the most confusing thing I've ever tried to learn
If you want to advance in JavaScript (beyond jQuery basics) you need to understand the 'weird stuff'.
Why things work the way they do.
Can get by for a long time without understanding them but it will make troubleshooting easier if you do understand them.

JS has no classes, no "classical inheritance" ala other OO languages
it has unusual inheritance
the "this" scope will change on you without warning.
Weird object creation
functions within functions
functions as objects
functions can have their own properties
can have unusual variable behavior that can make things confusing

Scoping –
JS scopes != C-style scopes
JS does not have block scope
if you create a variable it does NOT live in the context of that block where it was created (if, loop, etc)
the variable lives in the EXECUTION CONTEXT where it was created

Function scope aka execution context
when a var is created, it is created in that scope
the execution context where it was created
the function in which it was created

Variable Hoisting –

function and variable declarations get "hoisted" to the top of the executable content
functions FIRST then variables
JavaScript actually rewrites our code!

A variable that has not been ASSIGNED a VALUE is undefined.

Var foo;

foo is undefined.

Prototypal Inheritance
Objects from Objects

there are no "classes"
you don't define a "blueprint" like you do in C++
you create an object that you want other objects to inherit from
then you tell those new objects to inherit from the first one
can be confusing but many people consider it elegant

can be done 2 ways
1. constructor functions
2. Object.create()
Both are acceptable but Object.create() is recommended
Object.create() is not supported by ALL browsers, but it is in all MODERN browsers. Can use Webshim.lim to make it work everywhere.

Prototypal Inheritance "feels" like classic OO but it's different internally
every object has a __proto__ property
(in modern browsers)
__proto__ should NEVER be used in production (it is deprecated)
great learning tool to use for looking at your objects
can use it to look at an object's prototype in the console

Functions as First Class Objects
can create a function that has "properties"
not local variables but persistent properties FOR that function
Everything has a __proto__
Function Objects ALSO have a "prototype" property
NOT the function's prototype
functions are regular functions until you combine then with the "new" keyword
then they become factory functions and return brand new objects
"this" becomes bound to the new object being created

"this" creates 'instance variables'
when you do this, you get your own copies. You don't inherit the variable from the parent (__proto__) class
best option is to combine instance and prototypal variables to get what we want
each instance of Car should have it's own name, wheel count, etc. so use "this" to set these
should all use the same method for go(), stop(), etc so inherit those parts via "prototype"

Object.create()
have to use the "property descriptor" things which are annoying

...note "writable"...REQUIRED if you want the variable to be changeable. Lame.

Would rather use new() to get the "good" usable version of an object.

Or can write an init() method to initialize the "this" variables. And "return this"

Remember: Chevette.__proto__ == Car.prototype

So which one should I use? This is confusing.
Experts: object.create(), new is evil
new is not evil. Just requires that you remember something.
But so does var'ing your variables and people still do that.
Just pick one you like and be consistent

changing "this" scope
this = the constructed object if you use "new"
this = the global context if you forget to use "new"

the object assigned to "this" changes depending on how the object is CALLED
in Java, this is defined by how an object is CREATED. So in JavaSCRIPT it's different.

Can change what "this" is bound to by using call() and apply()

...all 3 return the same results (the testObject's version of the function)