Categories: Books
Tags: JavaScript
I just finished this book series about JavaScript, and it gave me a lot of great information and a fresh perspective on topics in JS that I already kinda-sorta knew, but not really in-depth.
I want to take some time to jot down some notes to help clarify (just for my own sake) the major concepts I learned from reading the books. In simple one-sentence definitions and some examples, I think the most important and relevant concepts I learned are:
try...catch: marks a block of statements to try, and specifies a response, should an exception be thrown
    finally block which will execute directly after try and catch but before any subsequent statements. finally executes whether or not an exception was thrown or caught.
        try...catchtry...catch...finallytry...finallyObject.create(proto[, propertiesObject]): creates a new object with the specified prototype object (1st argument) and properties (optional second argument)Object.keys(): returns an array of all enumerable propertiesObject.getOwnPropertyNames(..): returns an array of all properties, enumerable or not.Array.forEach(): iterates over all values in the array, and ignores any callback return valuesArray.every(): keeps going until the end or the callback returns a false (or “falsy”) valueArray.some(): keeps going until the end or the callback returns a true (or “truthy”) valuethrow keyword: stops execution of current function and transfers control to nearest catch block in the call stack (and terminates if there is no catch block)this keyword: refers to the dynamic scope (where the function was called from), following
four rules, in order of precedence:
    new? If so, this is the newly constructed object
var bar = new foo()call or apply, even hidden inside a bind hard binding? If so, this is the explicitly specified object
var bar = foo.call( obj2 )var bar = obj1.foo()undefined; otherwise the global object
var bar = foo()this exhibits dynamic scope behaviorvar foo = (function myModule(){..})();returned but private variables/functions are not directly accessible    function CoolModule() {
    	var something = [1, 2, 3];
    	function doSomething() {
    		console.log( something.join( " ! " ) );
    	}
    	return {
    		doSomething: doSomething
    	};
    }
    var foo = CoolModule();
    foo.doSomething(); // cool
    foo.doAnother(); // 1 ! 2 ! 3
  let declarations: create block-scoped variables (not “hoisted”)
    for loops, the variables declared with let will be declared for each iteration and be initialized with the value from the end of the previous iterationlet helps resolve closure and block-scoping issues in for loops like below  for (var i=1; i<=5; i++) {
    setTimeout( function timer(){
      console.log( i );
    }, i*1000 );
  } // "6" is printed 5 times at 1-second intervals -- probably NOT what was intended
  // this occurs because all 5 functions reference the same global "i"
  for (let j=1; j<=5; j++) {
    setTimeout( function timer(){
      console.log( j );
    }, j*1000 );
  } // "1" through "5" is printed out in 1-second intervals -- SUCCESS :)
  // this occurs because "j" (via let) is declared for each iteration and thus
  // each function captures its own unique value of "j"
  const declarations: create constants that are set once and cannot be changedclass keyword:yield keyword: used inside generators to signal a pause point, sends out a value
when pausing the generator, and receives (is replaced by) the eventual resumption value
    yield is essentially asking: “What value should I use here? I’ll wait to hear back.”yield *: Called yield delegation, requires an iterable whose iterator it invokes
and then delegates its own host generator’s control to that iterator until it’s exhaustedObject.assign(..): Shallow copies a target object (the first parameter) into one or more source objects (subsequent parameters). It iterates over all the enumerable, owned keys (immediately present) on the source object(s) and copies them (via = assignment only) to target. It also, helpfully, returns target  function anotherFunction() { .. }
  var anotherObject = {
  	c: true
  };
  var anotherArray = [];
  var myObject = {
  	a: 2,
  	b: anotherObject,	// reference, not a copy!
  	c: anotherArray,	// another reference!
  	d: anotherFunction
  };
  anotherArray.push( anotherObject, myObject );
  // ES6 method:
  var newObj = Object.assign( {}, myObject );
  newObj.a;						// 2
  newObj.b === anotherObject;		// true
  newObj.c === anotherArray;		// true
  newObj.d === anotherFunction;	// true
  // Old way to copy (for JSON-safe objects):
  var newObj = JSON.parse( JSON.stringify( someObj ) );... (Spread/rest operator): gathers together or spreads out    var a = [1,2,3,4,5];
    var b = [ 0, ...a, 6 ];
    b;	// [0,1,2,3,4,5,6]
      var [ a, b, c, ...d ] = foo();
    var { x, y, z } = bar();
  var { x: { y: { z: w } } } = foo;  function foo( [ x, y ], {a: foo, b: bar} ) {
	   console.log( x, y );
  }
    function foo(x = 11, y = foo(x)) {
  	console.log( x + y );
  }
      var foo = {
      bar() { console.log("hello world!") }
    }
      var prefix = "user_";
    var o = {
    	a: something
    };
    o[ prefix + "foo" ] = function(..){ .. };
  for .. of loops: loops over a set of values produced by an iterator
        var a = ["a","b","c","d","e"];
    for (var idx in a) { // iterates over indices/keys (need to use [] or . to access values)
      console.log( idx ); // 0 1 2 3 4
      console.log( a[idx] ); // "a" "b" "c" "d" "e"
    }
    for (var val of a) { // iterates over values
      console.log( val ); // "a" "b" "c" "d" "e"
    }
      var name = "Kyle";
    var greeting = `Hello ${name}!`;
    console.log( greeting );	// "Hello Kyle!"
  ${..}, and you can nest the interpolated expressions like so:    function upper(s) {
  	   return s.toUpperCase();
    }
    var who = "reader";
    var text =
      `A very ${upper( "warm" )} welcome
      to all of you ${upper( `${who}s` )}!`;
    console.log( text ); // A very WARM welcome to all of you READERS!
      function foo(strings, ...values) {
    	console.log( strings );
    	console.log( values );
    }
    var desc = "awesome";
    foo`Everything is ${desc}!`;
    // [ "Everything is ", "!"]
    // [ "awesome" ]
  (x) => {..}): Anonymous function expressions that resolves this-binding to be lexical (instead of dynamic)
    var self = this hack (but can mess you up if replacing a function already using dynamically-scoped this)this, arguments, and super are all lexically-bound with arrow functions    var controller = {
    	makeRequest: function(..){
    		btn.addEventListener( "click", () => {
    			// ..
    			this.makeRequest(..);
    		}, false );
    	}
    };
  import and export that bind a reference to that thing (variable, function, etc) like a pointer
    default which sets a particular exported binding to be the default when importing the modulereturn foo(x+1) instead of return 1 + foo(x)) are optimized in ES6 so that the extra stack frame allocation is unnecessary, which means there’s practically no limit to how deep the call stack can be
    Promise.resolve(..): creates a promise that is resolved to the value passed inPromise.reject(..): creates an immediately rejected promisePromise.all(..): accepts an array of one or more values (immediate values, promises, thenables) and returns a promise that will be fulfilled if all the values fulfill, or reject immediately once the first of any of them rejectsPromise.race(..): accepts an array of one or more values and waits only for either the first fulfillment or rejection.then() method on it    var arr = [1,2,3];
    var it = arr[Symbol.iterator]();
    it.next();		// { value: 1, done: false }
    it.next();		// { value: 2, done: false }
    it.next();		// { value: 3, done: false }
    it.next();		// { value: undefined, done: true }