JavaScript Theweird Parts
JavaScript Theweird Parts
• 42 - Understanding Closures
• 43 - Understanding Closures Pt. 2
• 44 - Framework Aside Function Factories
• 45 - Closures And Callbacks
• 46 - call(), apply(), and bind()
• 47 - Functional Programming
• 48 - Functional Programming Pt. 2
• 49 - Conceptual Aside Classical vs Prototypal Inheritance
• 50 - Understanding The Prototype
• 51 - Everything is an Object (Or a primitive)
• 52 - Reflection and Extend
• 53 - Functions Contructors, new And The History Of JavaScript
• 54 - Function Constructors and .prototype
• 55 - Dangerous Aside new and functions
• 56 - Conceptual Aside Built-In Function Constructors
• 57 - Dangerous Aside Built-In Function Constructors 2
• 58 - Dangerous Aside Arrays and for..in
• 59 - Object.create and Pure Prototypal Inheritance
• 60 - ES6 and Classes
• 61 - Initialization
• 62 - typeof, instanceof, and Figuring Out What Something Is
• 63 - Strict Mode
• 64 - Learning From Other's Good Code
• 65 - Deep Dive into Source Code jQuery - Part 1
• 66 - Deep Dive into Source Code jQuery - Part 2
• 67 - Deep Dive into Source Code jQuery - Part 3
• 68 - Requirements
• 73 - Good Commenting
• 76 - TypeScript, ES6, and Transpiled Languages
When you write JavaScript it isn't directly telling computer what to do. You're writing code,
but then someone else built programs that convert your JS into something that computer
can understand. Those programs are called compilers or interpreters.
Compilers go character by character and translate your code into a set of instructions.
Important to understand is that during that process programmers who wrote that compiler
can choose to do extra stuff. Your code is not what actually is given to a computer but a
translation of it.
3
Lexical environment - where something sits physically in the code you write and what
surrounds it. In JavaScript where you write something is important.
Execution context - a wrapper to help manage the code that is running. There are lots of
lexical environments, areas of the code that you look at physically, but which one is
currently running is managed via execution contexts. Execution context contains your
running code, but it can also contain things beyond what you've written in your code.
Because remember that your code is being translated by a syntax parser.
b();
function b() {
console.log('This works!');
}
When parser runs through code it recognizes where you created variables and functions
and it sets up memory space for them. So before your code begins to be executed, JS
engine has already set aside memory space for all the variables and functions you created.
When the code begins to execute line by line it can access it.
However, for variables JS engine puts a placeholder undefined, because it doesn't know
what it's value will ultimately end up being until it starts executing that line of code.
console.log(a);
Execution Stack - every time you invoke a function a new execution context is created for
that function and is put on top of execution stack.
So in this example myVar would actualy log 1 even though it sits inside a function which is
inside another. myVar sits in the outer global environment so JS will go down the scope
chain until it finds it.
function a() {
function b() {
console.log(myVar);
}
b();
}
var myVar = 1;
a();
let - allows JS engine block scoping. During execution context that variable is still placed
in memory and set to undefined, however, you're not allowed to use it until the line of
code is run during the execution phase. So if you try to use a variable before, you'll get an
error. Also, it is declared within a block. A block is usually defined by {} (function, if
5
statement etc). So if you're running let inside a loop a new variable will be placed in
memory after each iteration.
Event queue - events like click and others are placed in the queue. And this queue starts to
get processed in the order it happened only when execution stack is empty.
18 - Primitive Types
Primitive type - a type of data that represents a single value. That is, not an object.
Primitives:
Associativity - what order operator functions get called in: left-to-right or right-to-left
when functions have the same precedence.
22 - Comparison Operators
When true is coerced to number it is 1.
=== is a strict comparison operator and doesn't do conversion. So it's the best practice to
always use it to prevent strange bugs due to conversion.
We can use that to our advantage. This pattern is used in many JS libraries and good open
source code. Whatever is in parenthesis of if statement it is converted to a boolean. So this
statement returns true if a is set or false if not.
var a;
if (a) {
console.log('Something is there.');
}
Also worth mentioning that false || true returns true.
24 - Default Values
If you pass two values to || operator it will return a first one which returns true.
Object can have a primitive(string, boolean) and that will be called a property. It can have
another object and it will also be a property.
person['firstName'] = 'Jason';
var Jason = {
firstname: 'Jason',
lastname: 'Baciulis',
address: {
street: '111 Main St.',
city: 'New York',
state: 'NY'
}
};
First class functions - everything you can do with other types you can do with functions.
Assign them to variables, pass them around as parameters to other functions, you can
create functions on the fly.
Just like any object, function object resides in memory. Though, it's a special type of object
because it has all the features of a normal object but has some other special properties. It's
hidden special properties:
The code that you write gets placed in the special property of the function object. So it isn't
like the code you write is a function. The function is an object with other properties. And the
code that you write is just one of those properties that you're adding onto it. What is
special about that property that it's invocable. You can say run that code and that's when
execution context creation and execution happens.
It's important that you have this mental model of functions in your mind. You have to think
of functions as objects whose code just happens to be one of the properties. There are
other things that functions can have attached to it. And it can be moved around and copied
just like other object.
You have to think about functions as more than just containers of code.
function greet() {
console.log('hi');
}
It is put into memory. But it doesn't return a value until a function is invocated.
This is expression:
var a = 3; b = a;
When you set b equals to a, equals operator sees these are primitives creates a new spot in
memory and makes a copy of it. b and a will be both 3 but they are copies sitting on
separate spots in memory. So if I change a = 5 it doesn't affect b, it is still 3, because after
making a copy these values are on their own.
this inside a method points to that object from which it is called. Left of the dot rule.
But this inside a function which is inside a method will point to the global object.
With ES5 JavaScript using var you could solve this by setting inside a method var _this
= this; which is a very common pattern.
(function(name) {
}(firstname)); // IIFE
Function statements can't be anonymous.
42 - Understanding Closures
When a function runs and completes it is removed from execution stack, but variables
created and saved in that execution phase are still stored in memory and can be accessed
from down the scope.
function greet(whattosay) {
return function(name) {
console.log(whattosay + ' ' + name;
}
call() invokes the function but also lets you to decide what this variable will be, by
passing an object: call(object, 'param', 'param2'). Unlike bind, it executes the
function instead of copying it.
apply() is almost the same as call() but instead you need to pass an array as a
parameter: .apply(object, [parameters])
In practice, you can use call() and apply() to borrow methods/functions from objects
and use on another object with the same property names.
Function currying - creating a copy of a function but with some preset parameters.
47 - Functional Programming
A mapping function is a function which takes one array and outputs another array. It is very
powerful and useful technique that you will see in codebases.
return newArr;
}
12
You should avoid mutating/changing things. That's why it is better to return a new array
than change existing one.
Classical inheritance is the way it's been done a long time, it's what Java, C# uses. It's very
verbose.
Each object inherits properties and methods of other objects through a prototype. So if you
call a property on one object and it doesn't find it there it goes the prototype chain and
looks for it on a prototype.
All objects, functions, arrays have their prototype pointing to the special object where you
can access methods like call(), bind(), push().
extend(obj, obj2, obj3) takes all properties and methods of given objects and
passes them to the first object.
It is not a built in feature but many libraries have it and ES6 have extends.
new keyword creates an object and functions constructors are used for adding properties
and methods to that object.
It's better to put your methods on the prototype to save memory space as it gets shared
between all objects.
Although worth mentioning that creating objects with function constructors is going away
because of new methods and ES6.
These constructors look like you're creating primitives but you are not. You are creating
objects.
When you use some methods like .length on a string, your string is boxed in
a String object automatically to get access to all its methods.
Although it doesn't work like that for numbers and you would need to
create Number object first.
All these built-in function constructors have a prototype and you can actually add your own
methods to it.
String.prototype.isLengthGreaterThan = function(limit) {
return this.length > limit;
}
console.log("John".isLengthGreaterThan(3));
var a = 3;
var b = new Number(3);
john.firstname = 'John';
john.lastname = 'Doe';
And you can override properties and methods by adding new ones to this object with the
same names.
Polyfill - code that adds a feature which the engine may lack.
class doesn't change anything how objects and prototypes work under the hood. It just
gives you a different way to type. Because of it you may hear JavaScript classes being called
syntactic sugar.
Syntactic sugar - a different way to type something that doesn't change how it works
under the hood.
61 - Initialization
Large arrays of objects are useful for testing and initialization before you have an actual
data to pull from, like a JSON file.
15
instanceof will tell you if it has something in its prototype chain by returning a boolean.
var a = 3;
console.log(typeof a); // returns a string 'number'
var b = "Hello";
console.log(typeof b); // returns a string 'string'
var c = {};
console.log(typeof c); // returns a string 'object'
var d = [];
console.log(typeof d); // also returns a string 'object', weird!
function Person(name) {
this.name = name;
}
var e = new Person('Jane');
console.log(typeof e); // also an object
var z = function() { };
console.log(typeof z); // returns a 'function'
63 - Strict Mode
JavaScript is a more liberal of what it allows.
"use strict"; - enforces more strict rules. E.g. in this mode you must declare var first to
use it. In not strict mode if you forget to type var, it will still be created on the global
object window.
16
You can use use strict at the top of the document or at the top of a function to use strict
only inside it's execution context.
It may sound as fun as reading an encyclopedia, but you don't need to spend hours reading
the source code. Find some area that's interesting to you. Don't get intimidated by famous
libraries and what may seems complex patterns. Look at the structure, see what you could
take away and imitate.
This is a great way to learn advanced patterns and concepts in JavaScript. So make a
practice to occasionally look at the source code of the library or framework you're using.
Inside jQuery there is Sizzle CSS Selector library for handling selectors.
68 - Requirements
First of all, before building any application let's think of the requirements. What this
app/library should do?
73 - Good Commenting
Remember to write good comments for your code. Because even if you are the sole
developer for a project you may need to come back after a year and you'll have to figure it
out how everything works like it was someone else's code.
In this case, languages that don't really ever run anywhere, but instead are processed by
transpilers that generate JavaScript.
17
TypeScript - one of the most popular transpiled languages and is created by Microsoft.
The biggest difference that it uses strict types for its variables instead of dynamic types like
JavaScript.