Reopilation of book Up&Going from https://github.com/getify/You-Dont-Know-JS
//Objects
var obj = {
a: "hello world",
b: 42,
c: true
};
obj.a; // "hello world"
obj.b; // 42
obj.c; // true
obj["a"]; // "hello world"
obj["b"]; // 42
obj["c"]; // true
//Arrays
var arr = [
"hello world",
42,
true
];
arr[0]; // "hello world"
arr[1]; // 42
arr[2]; // true
arr.length; // 3
typeof arr; // "object"
//Functions
function foo() {
return 42;
}
foo.bar = "hello world";
typeof foo; // "function"
typeof foo(); // "number"
typeof foo.bar; // "string"
//Built-In Type Methods
var a = "hello world";
var b = 3.14159;
a.length; // 11
a.toUpperCase(); // "HELLO WORLD"
b.toFixed(4); // "3.1416"
//Coercion
var a = "42";
var b = Number( a );
a; // "42"
b; // 42 -- the number!
var a = "42";
var b = a * 1; // "42" implicitly coerced to 42 here
a; // "42"
b; // 42 -- the number!
//Truthy & Falsy
//specific list of "falsy" values
"" //(empty string)
0, -0, NaN //(invalid number)
null, undefined
false
//any value that's not on this "falsy" list is "truthy
"hello"
42
true
[ ], [ 1, "2", 3 ] //(arrays)
{ }, { a: 42 } //(objects)
function foo() { .. } //(functions)
//Equality
var a = "42";
var b = 42;
// == checks for value equality
a == b; // true
// === checks for value and type equality
a === b; // false
var a = [1,2,3];
var b = [1,2,3];
var c = "1,2,3";
a == c; // true
b == c; // true
a == b; // false
//NaN is neither greater-than nor less-than any other value.
var a = 42;
var b = "foo";
a < b; // false
a > b; // false
a == b; // false
//Hoisting
var a = 2;
foo(); // works because `foo()`declaration is "hoisted"
function foo() {
a = 3;
console.log( a ); // 3
var a; // declaration is "hoisted" to the top of `foo()`
}
console.log( a ); // 2
//Nested Scopes
function foo() {
var a = 1;
function bar() {
var b = 2;
function baz() {
var c = 3;
console.log( a, b, c ); // 1 2 3
}
baz();
console.log( a, b ); // 1 2
}
bar();
console.log( a ); // 1
}
foo();
//If-Else
if (a == 2) {
// do something
}
else if (a == 10) {
// do another thing
}
else if (a == 42) {
// do yet another thing
}
else {
// fallback to here
}
//Switch
switch (a) {
case 2:
// do something
break;
case 10:
// do another thing
break;
case 42:
// do yet another thing
break;
default:
// fallback to here
}
//The ? operator
var a = 42;
var b = (a > 41) ? "hello" : "world";
//Assign functions
var foo = function() {
// Anonymous function
};
var x = function bar(){
// Named function
};
//Immediately Invoked Function Expressions (IIFEs)
(function IIFE(){
console.log( "Hello!" );
})();
// "Hello!"
function foo() { .. }
// `foo` function reference expression,
// then `()` executes it
foo();
// `IIFE` function expression,
// then `()` executes it
(function IIFE(){ .. })();
//Hoisting into IIFE
var a = 42;
var x = (function IIFE(){
var a = 10;
console.log( a ); // 10
})();
console.log( a ); // 42
//Closure
//You can think of closure as a way to "remember" and continue
//to access a function's scope (its variables) even once the
//function has finished running.
function makeAdder(x) {
// parameter `x` is an inner variable
// inner function `add()` uses `x`, so
// it has a "closure" over it
function add(y) {
return y + x;
};
return add;
}
// `plusOne` gets a reference to the inner `add(..)`
// function with closure over the `x` parameter of
// the outer `makeAdder(..)`
var plusOne = makeAdder( 1 );
// `plusTen` gets a reference to the inner `add(..)`
// function with closure over the `x` parameter of
// the outer `makeAdder(..)`
var plusTen = makeAdder( 10 );
plusOne( 3 ); // 4 <-- 1 + 3
plusOne( 41 ); // 42 <-- 1 + 41
plusTen( 13 ); // 23 <-- 10 + 13
// When we call makeAdder(1), we get back a reference to its inner add(..) that remembers x as 1. We call this function reference plusOne(..).
// When we call makeAdder(10), we get back another reference to its inner add(..) that remembers x as 10. We call this function reference plusTen(..).
// When we call plusOne(3), it adds 3 (its inner y) to the 1 (remembered by x), and we get 4 as the result.
// When we call plusTen(13), it adds 13 (its inner y) to the 10 (remembered by x), and we get 23 as the result.
//Closure with module
function User(){
var username, password;
function doLogin(user,pw) {
username = user;
password = pw;
// do the rest of the login work
}
var publicAPI = {
login: doLogin
};
return publicAPI;
}
// create a `User` module instance
var fred = User();
fred.login( "fred", "12Battery34!" );
//This identifier
//It's important to realize that this does not refer to the function itself
function foo() {
console.log( this.bar );
}
var bar = "global";
var obj1 = {
bar: "obj1",
foo: foo
};
var obj2 = {
bar: "obj2"
};
// --------
foo(); // "global"
obj1.foo(); // "obj1"
foo.call( obj2 ); // "obj2"
new foo(); // undefined
// 1) foo() ends up setting this to the global object in non-strict mode -- in strict mode, this would be undefined and you'd get an error in accessing the bar property -- so "global" is the value found for this.bar.
// 2) obj1.foo() sets this to the obj1 object.
// 3) foo.call(obj2) sets this to the obj2 object.
// 4) new foo() sets this to a brand new empty object.
//Prototypes
// When you reference a property on an object,
// if that property doesn't exist, JavaScript will automatically
// use that object's internal prototype reference to find
// another object to look for the property on.
var foo = {
a: 42
};
// create `bar` and link it to `foo`
var bar = Object.create( foo );
bar.b = "hello world";
bar.b; // "hello world"
bar.a; // 42 <-- delegated to `foo`
// The a property doesn't actually exist on the bar object,
// but because bar is prototype-linked to foo,
// JavaScript automatically falls back to looking for a on the foo object,
// where it's found.
//Polyfilling
if (!Number.isNaN) {
Number.isNaN = function isNaN(x) {
return x !== x;
};
}
//Transpiling
function foo(a = 2) {//New enviroments
console.log( a );
}
foo(); // 2
foo( 42 ); // 42
function foo() {//Old enviroments
var a = arguments[0] !== (void 0) ? arguments[0] : 2;
console.log( a );
}
//Non JS
//The document variable exists as a global variable when your code is running in a browser.
//It's not provided by the JS engine, nor is it particularly controlled by the JavaScript specification
//It's a special object, often called a "host object.". It's provided by DOM API
var el = document.getElementById( "foo" );
//alert(..) is provided to your JS program by the browser, not by the JS engine itself.
//The same goes with console.log(..)
//Scopes
//It's not enough to have anecdotal fuzzy beliefs about scope.
//The JS engine compiles your code right before (and sometimes during!) execution.
//this & Object Prototypes
// The "this" keyword is dynamically bound based on how the function
// in question is executed, and it turns out there are four simple
// rules to understand and fully determine this binding.
//Async and Performance
// callbacks as the primary method of enabling asynchrony.
// Generators introduce a new mode of execution for JS functions,
// whereby the generator can be paused at yield points and be resumed asynchronously later.