Javascript Definitive Guide notes


Javascript Definitive Guide - possibly the most comprehensive programming book ever written imo.
Here's my notes

Chapter 6 Objects


Objects in js:
    •    an object is an unordered collection of properties, each of which has a name and a value. Name is string, value can be primitive or object
    •    inherits properties of another object, known as its prototype
    •    in js an object is any value that is not: string, number, true, false, null, undefined
    •    manipulated and passed by reference
    •    "own property" is a property defined directly on the object
    •    "inherited property" defined and inherited from prototype object 


Built in object properties:
    ◦    prototype reference to another object to inherit from (prototypal inheritence)
    ◦    class a string e.g. "Object", "Function" accessible by Object.prototpe.toString.call(o)
    ◦    writeable
    ◦    enumerable
    ◦    configurable
    ◦    extensible ES5 only


Create objects as follows
    ◦    with object literal e.g. var o = {}; which is creates new every time evaluated
    ◦    using new e.g. var o = new Object();
    ◦    ES5 introduces Object.create(), another way to create objects from others e.g. var o = Object.create({a:1});


Prototype: 

every js object has a 2nd js object associated with it called the prototype; an object inherits properties from its prototype
    ◦    objects created using {} get the same prototype object as their prototype referred to as Object.prototype
    ◦    objects created using the new keyword and a constructor invocation set their prototype to the value of the prototype property of their constructor fn e.g. new Array() uses Array.prototype as its prototype
    ◦    "protoype chain" refers to prototypes referring to prototypes e.g. a new date object refers to Date.prototype which in turn refers to Object.prototype
 

Access/read a property;
    ◦    when accessing a property on an object, the object is checked if present then returned, otherwise the prototype is checked, if present on prototype then return, otherwise go up the prototype chain until found or no more prototype in which case undefined is returned
    ◦    myObj.prototype ----> {Object}
 

Assign/set a property
    ◦    if property exists on the object its just set
    ◦    but if not exists then a new property is added to that object and then set to that value (previously inherited properties of same name are hidden by this new property)
 

Delete property 
    ◦    using delete e.g. var o = {x:1}; delete o.x; will remove x from o
    ◦    delete will not work on inherited properties; you must directly delete from the prototype object
 

Testing presence of properties
    ◦    in: returns true if object has own or inherited property e.g. var o = {x:1}; "x" in o; //true
    ◦    hasOwnProperty(): returns true only if object has own (no inherited) e.g. o.hasOwnProperty("x"); // true
    ◦    propertyIsEumerable(): hasOwnProperty() is true and its "enumerable" attribute is true
    ◦    for/in returns each own or inherited enumerable property e.g. for (prop in o) { console.log(prop); }
    ◦    typically use o.x !== undefined; to check for presence, but "in" will return true even if x is on o but undefined




Chapter 8 Javascript functions

    •    are objects and so a function can have methods and properties
    •    return undefined if no explicit return
    •    if called with fewer parameters than declared then those not assigned are undefined
    •    "variadic" / "varargs" functions take variable number of arguments
    •    has no type checking of params, so if necessary check param types yourself



Built in methods:
    ◦    call e.g. myFn.cal(objForThis, p1, p2)
    ◦    apply (args as array) e.g. myFn.apply(objForThis, [p1,p2])
    ◦    toString typically returns source code
    ◦    bind binds object to fn
    ◦    Function constructor; creates a new fn every time invoked
          ▪    last argument is always the code e.g. myFn = new Function("p1", "p2", "return p1 * p2";)
          ▪    uses top level scoping i.e. as if defined as global fn
          ▪    like eval and therefore avoid


Built in properties:
    ◦    prototype,
    ◦    length expected num args (arity)
    ◦    within fn invocation: has arguments array like object that
    ◦    has all the arguments passed accessible like an array
    ◦    has a length property
    ◦    has caller and callee properties but ES5 strict are inaccessible
    ◦    do not modify arguments, disallowed in ES5
    custom: you can add custom properties and methods; a function property is basically a static var for that fn
 

Nested function
    •    function within a fn...nested has access to outer fn
    •    but nested functions have a this of the either the global object or the object they're called on
    •    nested functions do not inherit the this, thus must set to self = this; and use self in the inner
code inside fn is not executed when defined, only when invoked

4 ways to invoke fns
    1.    as functions; e.g. myFunc(p1)
      ◦    the invocation context (this) is the global object (in strict ECMS5 its undefined)
    2.    as methods on objects; e.g. e.g. o.methodName(p1) OR o[methodName](p1)
      ◦    when property of object or element of array
      ◦    invocation context (this) is the object
    3.    as constructors e.g. var o = new Object();
      ◦    if preceded by new then its a constructor invocation
      ◦    creates a new empty object that inherits from the prototype property of the constructor
    4.    as call and apply myFunc.call(o, p1)
      ◦    you can invoke any function as a method of an object using call/apply and passing as 1st param
 

Scoping
Javascript uses "lexical scoping" which means functions are executed using the variable scope (chain) in effect when they were defined, not when invoked.
Lexical resolution is determined at compile time (aka early binding). Dynamic resolution is generally determined at runtime (aka late binding). Lexical is also called static scoping because you can tell scope from looking at the code.
Lexical scoping in js means fn variables are in effect within that fn but not if another fn is called...unless that other fn was declared within same scope i.e. innner fn
Dynamic scope means a variable is in scope while the fn and other called fns are executing. Bash uses dynamic scoping.

scoping continued...
Scope of a variable is the region of the program in which its defined and can be used. e.g. global scope, function scope Javascript does not have block scope, only function scope...or global


"scope chain" is a list or chain of objects that defines the variables that are "in scope" for that code
    •    every chunk of js code (global or function) has a scope chain associated with it
    •    variable resolution (lookups) are resolved up the scope chain, starting at the first object, then next and so on until the variable is found or not (ReferenceError)
 

Closure
A closure is a combination of function object and a scope (set of variable bindings) (scope in js is a chain of objects)
Technically all javascript functions are closures because they are objects and they have a scope chain.
Javascript
    •    variable declaration is hoisted but not initialization
    •    function declaration and initialization both hoisted
Javascript is not a functional programming language, but because functions are first order objects then such techniques can be applied.


Useful Library code 


var isFunction = function(fn) { 
   return Object.prototype.toString === "[object Function]"; 
}
 

var isArray = Function.isArray || function(o) { 
   return typeof o === "object" && Object.prototype.toString.call(o) === "[object Array]"; 
}
 

/* returns classname e.g. classof("astring") is "String" */ 
var classof = function(o) { 
   if (o === null) return "Null"; 
   if (o === undefined) return "Undefined"; 
   return Object.prototype.toString.call(o).slice(8, -1); 
}

/* better to use Crockfords instead page 119 */ 

var inherit = Object.create(p) || function(p) { 
   if (p === null) throw TypeError("cannot be null");
   var t = typeof p;
   if (t !== "object" && t !== function") throw TypeError("must be object");
   function f() {};
   f.prototype = p;
   return new f();
}


/* set in o all properties in p */ 

var extend = function(o, p) { for (prop in p) { o[prop] = p[prop]; } return o; }
 

/* add to o proprties in p not in o */ 
var merge(o, p) { for (prop in p) { 
    if (! o.hasOwnProperty(prop) { 
      o[prop] = p[prop]; }
    } 
    return o; 
}
 

/* copy all enumerable object property names into an array */ 
var o = {a:1, b:2}, res = [], i = 0; 
for (res[i++] in o) ; `


Chapter 9 Classes and Modules
In javascript a "class" is a set of objects that inherit properties from the same prototype object
 

A Constructor
    •    is a function designed for the initialization of new objects
    •    is invoked using the new keyword
    •    when invoked with new it automatically creates a new object, so ctor just needs to initialize
    •    automatically returns the new object
    •    critical: prototype property of the constructor fn is used as the prototype of the new object. Means all objects created with the same constructor share the same prototype and are members of the same "class"
    •    any js function can be used as a constructor function, just a convention to capitalize
    •    every js function has a prototype property, the value is an object,
        ◦    that object has a property named "constructor" which points back to the class 

                 i.e. F.prototype.constructor == F; // true
        ◦    every instance of F has a constructor which points to F 

                 var f = new F(); f.constructor === F; // true
        ◦    "the constructor specifies the class"
        ◦    you can add more methods and properties to the prototype object which all instances share
   

Constructor fn Prototype Instances


Range() <----- constructor <-- range1 prototype ------> <-- range2


// Range is a Construct fn
var Range = function(from, to) { 
   this.from = from; 
   this.to = to; 
}


// this is the same as setting a new object on Range prototype below 
//
Range.prototype.foreach= function() {} 
Range.prototype.toString= function() { 
   return "Range " + this.from + " " + this.to
}, 
Range.prototype.includes = function() {}


// alternative; same as setting Range.prototype values above, just sets to new object 
//replacing previous prototype object
//
Range.prototype = { 
   constructor: Range, foreach: function() {}, 
   toString: function() {return "Range " + this.from + " " + this.to}, 
  includes : function() {} 
}

instanceof checks if two objects point to the same prototype object
    ◦    e.g. r instanceof Range is true if r inherits from Range.prototype


js prototypal based inheritance is dynamic, changes to prototype become available to all instances
    ◦    don't add to Object.prototype since all objects get it and it will be enumerable
 

Java style:
    •    Constructor fn (an object): properties, such as variables, added to this are class fields, same with methods static methods typically do not use "this"
    •    Prototype object: properties such as methods and variables added to prototype object are inherited by all instances methods can use the this
    •    Instance object: each instance can have own properties variables and methods



Chapter 15 - Document Object Model
These are my notes from:
    •    Javascript Definitive Guide (chapter 15)
    •    DOM Enlightenment - Cody Lindy
 

The accompanying example code is dom.html in this folder.
 

HTML is a hierarchy expressed as a tree. When a typical browser loads an HTML doc it parses the hierarchy to create a tree of node objects. This is the document object. The document object is part of a greater API known as the Document Object Model (dom)

The purpose of the DOM is to provide a programming api for scripting (add, remove, change, event) the live document using javascript.


The document object is realized as a tree data structure consisting of nodes and there are different node types e.g. Document_node, Element_node, Text_node etc.


There are javascript constructor functions which are used to construct the DOM node objects e.g. Node, Document, Element, Text etc.


Each Node object inherits properties and methods from Node or subclasses e.g. Object < Node < Element < HTMLElement < (e.g., HTML*Element)


Node is just a js constructor function whose prototype is Object

nodeType
Every node has a nodeType code which indicates the type of ndoe it is, here are some of the most common
    •    Node.DOCUMENT_TYPE_NODE = 10
    •    Node.DOCUMENT_NODE = 9
    •    Node.DOCUMENT_FRAGMENT_NODE = 11
    •    Node.ELEMENT_NODE === 1
    •    Node.TEXT_NODE === 3
A nodes nodeValue property returns a value for Text and Comment (null for all other nodes)
You can set text using nodeValue e.g. document.body.firstElementChild.nodeValue = 'hi'

Creating
You can create elements with document.createElement('div') pass a string for what to create.
But you can also use javascript strings and Dom Node properties to do same:
    •    innerHTML - note: innerHTML invokes a heavy and expensive HTML parser, so use sparingly
    •    outerHTML
    •    textContent - cheap operation
    •    innerText
    •    outerText
    •    document.write - can create and append to dom but best avoided because stalls parsing
e.g. document.getElementById('C').innerHTML = ''
dude
''; // sets innerHTML value
The above DOM properties can also be used to extract the values from the DOM.
e.g. document.getElementById('C').innerHTML; // returns the innerHTML value

Comments

Popular posts from this blog

deep dive into Material UI TextField built by mui

angular js protractor e2e cheatsheet

react-router v6.4+ loaders, actions, forms and more