JavaScript - ryantc94/Knights-of-Arthur GitHub Wiki

Table Of Contents

Basics
Arrays
Functions
Variables: Scope, Environment, and Closure
Objects and Inheritance
ES6 Classes JS
Composition over Inheritance
Async JavaScript

Basics

http://speakingjs.com/es5/ch01.html#_functions

JS Expression vs. Statement

  • JS Expressions: Expressions produce values. They are function arguments, the right side of an assignment, etc
    3 * 7
    
  • JS Statements: Statements “do things.” A program is a sequence of statements. An expression can be used wherever a statement can be use, this is called an expression statement. Here is an example of a statement, which declares (creates) a variable foo
    var foo;
    
  • Expression Statements are not allowed to begin with { or 'function' key word.

Eval

?????

IIFE

( function (){ return 'foo' } () ) <-- IIFE ... how does the first pair of () work...
function (){ return 'foo' }() <-- returns an error because JS sees a function declarations which must have a name
function bar(){ return 'foo' } () <-- returns an error because function declarations can't be immediately invoked, whatever follows a function declaration must be a legal statement

Semicolons

  • Normally statements are terminated except for those with paranthesis

JS Types

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures

  1. Boolean
  2. null
  3. undefined
  4. Number
  5. String
  6. Symbol <- ??? new es6 type
  7. Object

JS Statements

do... while

do {
 statement
} while(expression);

Built-In Functions

Math.random(): returns a floating-point, pseudo-random number between 0 (inclusive) and 1 (exclusive).

String Templates Literals

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals

Arrays

map, reduce, filter (Array Methods)

  1. Map: returns a new array with the results of applying a callback to each element in original array
  2. Reduce: applies a callback on an accumulator and each element in array and returns single value, the accumulator should be in callback parameters i.e (accumulator, nextElement)
  • ^If no initial value is supplied, the first element in the array will be used^
  1. Filter: returns a new array with the elements in the original array that pass the callback

Functions

  • All functions are objects, instances of Function and get their methods from Function.Prototype

Defining Function

  1. Function expression: when not given a name it is referred to as Anonymous Functions, versus when it is given a name and used for recursion.
var myFunction = function [name]([param1[, param2[, ..., paramN]]]) {
  statements
};
  1. Function declaration: declarations are hoisted and require a name.
function name([param,[, param,[..., param]]]) {
  [statements]
}
  1. Function constructor
new Function ([arg1[, arg2[, ...argN]],] functionBody)

Calling a Function

  1. Normally
myfunction();
  1. 'new' Operator: function becomes a constructor and creates a new object
new myfunction();
  1. Method Call
obj.x();
  1. Method Chaining
obj.function1().function2()
new obj.function1().function2()

Function Arity

  • When extra args are supplied there are no side effects however they can be retrieved through the arguments object
    function(x) {
      x = arguments[0]
    }
    
  • By default arguments are 'undefined'

Pass-By-Value

https://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language

Named Parameters ???

  • When calling a function in a programming language, there are two ways to map arguments and parameters.
  1. Positional parameters are mapped by position. The first actual parameter is mapped to the first formal parameter, the second actual to the second formal, and so on.
  2. Named parameters use names (labels) to perform the mapping. Names are associated with formal parameters in a function definition and label actual parameters in a function call. It does not matter in which order named parameters appear, as long as they are correctly labeled.
  • Mimicked by using an object literal (Stack Overflow)

  • es6 object shorthand instantiating... (functional components)

  • es6 default param

ES6 Arrow Functions

  • ES6 arrow function is short hand for writing a function expression.
  • ES6 arrow functions do not have an 'arguments object'.
  • ES6 'this' context refers the value of 'this' where it is defined.
// 1 
(p1, p2, p3, ...) => { statements }
// 2 (single expression)
(p1, p2, p3, ...) => statement
// 3 (single parameter)
param => { statements }
// 4 (no parameter)
() => { statements }

Reference: (SpeakingJS)

Variables: Scope, Environment, and Closure

...

Objects and Inheritance

  • A key/value entry in an object is referred to as a property, where the key can only be a string but the value can be anything.

Types of Property

  1. Properties: mapping from string to value.
  2. Accessors: accessors allow you to compute the values of properties i.e Getter Setter
  3. Internal Properties

Object Literals

  • Object literals allow you to create direct instances of Object.prototype
  • 'Dot Operator' allows you to get and set properties from objects as well as call methods
  • 'Bracket Operator' allows you to get access properties via expressions and keys that are not identifiers.
const obj = {
   x: "x",
   func: function(){}
}

obj.x //get
obj.func() //method
obj.y = 1 //sets y and if y doesn't exists adds y
delete obj.y //removes y from obj, it returns false if cannot be done and true if can
obj.['js'+'expression'] = 'jsExpression'

'this' Key Word

  • All functions have properties, when a function executes it gets the 'this' property.

Scenarios of 'this'

  1. Methods
  • 'this' property is a variable with the value of the object that invokes the method where 'this' is used.
  • 'this' always refers to an object, the object that invokes the method that uses this.
  • When methods are called without the dot operator, as function calls the 'this' context becomes global as it does when its a function.
  1. Function
  • When code is executed on browser all functions and variables are defined on 'window' object, so when 'this' is used in a global function it refers to window.
  • When we use strict mode, 'this' holds the value of undefined in global functions and in anonymous functions that are not bound to any object.
  1. Function Methods
**Bind**: creates a new function but has its 'this' property set to a particular object (so it sets this before it is called)
**Call**: calls a function with a given 'this' property and arguments.
**Apply**: calls a function with a given 'this' property and argument as an array.
  1. 'new' Operator: Please review Constructors for more information

Reference: (StackOverflow)

Inheritance (Prototype Based)

  • When it comes to inheritance, JavaScript only has one construct: objects. Each object has a private property which holds a link to another object called its prototype.
  • Every object can have another object as its prototype, and inherits all its prototype's properties (inherits them from the X.prototype property)
  • An object can specify its prototype by the internal Prototype property, however this is not something we have access to.
  • Another way is to use proto, however this is not supported in ECMA5 and its use is not suggested.
  • Object.create(prototype, object) will create a new object with specified prototype and properties.
var PersonProto = {
    describe: function () {
        return 'Person named '+this.name;
    }
};
var jane = Object.create(PersonProto, {
    name: { value: 'Jane', writable: true }
});

//Or you can do ...
var jane = Object.create(PersonProto);
jane.name = 'Jane';

Inheritance Ladder

  • When you access a property on an object, it'll first look for it in the object and if not found will climb the prototype ladder all the way up to Object.prototype, which has a prototype of null. However, Setting & Deleting don't climb the ladder it affects only its own properties.
  • A method is Overridden in the chain if an earlier object has the method.
  • Object.getPrototypeOf(obj)
  • Object.isPrototypeOf(obj)

Listing keys:

// 1. All Properties
for («variable» in «object»)
    «statement»

// 2. Own Properties
Object.getOwnPropertyNames(obj)

// 3. Own Properties & Enumerable
Object.keys(obj)

// 4. Checks if property exists
propKey in obj

// 5. Checks if property exists
Object.prototype.hasOwnProperty(propKey)

Accessors

var obj = {
    get foo() {
        return 'getter';
    },
    set foo(value) {
        console.log('setter: '+value);
    }
};

Property Attribute and Property Descriptor

  • A properties state (data and metadata) are stored in its Attribute.
  • Attribute keys are usually written within .
  • Attributes specific to properties are Value <- default undefined its data & Writable <- default false (is it modifiable).
  • Accessors Set <- default undefined Get <- default undefined
  • All properties have attributes Enumerable <- default false & Configurable <- default false (controls the writability of a property’s metadata)
  • Property Descriptors is a way to work with attributes, and are used for 2 kinds of operations
  1. Getting Descriptors: all attributes of a property are returned as decriptors
  2. Defining a Property: Object.defineProperty()
// Uses default values
var obj = {};
Object.defineProperty(obj, 'foo', { configurable: true });
Object.getOwnPropertyDescriptor(obj, 'foo')
{ value: undefined,
  writable: false,
  enumerable: false,
  configurable: true 
// Doesn't change attributes that are not specified
Object.defineProperty(obj, 'foo', { writable: true });
Object.getOwnPropertyDescriptor(obj, 'foo')
{ value: undefined,
  writable: true,
  enumerable: false,
  configurable: true }
// Object.getOwnPropertyDescriptor(obj, propKey)
// Object.defineProperty(obj, propKey, propDesc)
// Object.defineProperties(obj, propDescObj) <- The batch version of Object.defineProperty()
// Object.create(proto, propDescObj?)
  • To copy an object it must:
  1. The copy must have the same prototype (see Layer 2: The Prototype Relationship Between Objects) as the original.
  2. The copy must have the same properties, with the same attributes as the original.

Defining vs Assigning (=):

Defining a property means creating a new own property or updating the attributes of an existing own property. In both cases, the prototype chain is completely ignored. Assigning to a property prop means changing an existing property. If the property is not-writable then assigning won't work and will throw error in strict mode.

Enumerability

The only operations affected by enumerability are: The for-in loop Object.keys() (Listing Own Property Keys) JSON.stringify() (JSON.stringify(value, replacer?, space?))

Protecting an Object

  1. Preventing Extensions:
Object.preventExtensions(obj) //prevents object from being added to but properties can still be deleted
Object.isExtensible(obj) //checks
  1. Sealing:
Object.seal(obj) // prevents extensions and unconfigurable (attributes can't be changed)
Object.isSealed(obj) //checks
  1. Freezing:
Object.freeze(obj) //all properties are ready only and sealed
  • Protection is shallow since properties with mutable object can still be changed as well as the objects prototype.

Constructors - Factories for Instances

  • It's important to remember that constructors just return objects.

Functions designed to be used with 'new' syntax are called Constructors, a function called with 'new' operator will have 'this' context pointing to new object (unless the constructor explicitly returns a different object) and and will return 'this' by default.

  • Constructors create objects that are called instances, and is invoked using the 'new' operator.
  • All objects have a constructor property in their prototype.
  1. Data is instance-specific and stored in the own properties of the instance objects.
  2. Behavior is shared by all instances—they have a common prototype object with methods.
  • 'new' operator create a new object with the proptype of the Object and sets up data (...)
  • For example:

Terminology of Prototype

  1. Prototype Definition 1 (prototype relationship): An object can be the prototype of another object
  2. Prototype Definition 2 (prototype property): Each constructor C has a prototype property that refers to an object. That object becomes the prototype of all instances of C.
  • Because of ambiguity Prototype Definition 2 can be also called instance prototype.

instanceof Operator

  • By default constructor C will have prototype of C.prototype which will in turn have constructor of C (C.prototype.constructor).
  • instanceOf: determines whether value has been created by the constructor Constr or a subconstructor.
value instanceof Constr

Data in 'prototype' Property

...

Private Data

...

Constructor Inheritance

Sub should inherit from Super: it should have all of Super’s prototype properties and all of Super’s instance properties in addition to its own. Note that methodB overrides Super’s methodB.

Inheriting Instance Properties

  • Instance properties are set up in the constructor, so in order to get parents properties we must use call() to access parent's constructor.
function Sub(prop1, prop2, prop3, prop4) {
    //Remember Super is a function/constructor
    Super.call(this, prop1, prop2);  // (1)
    this.prop3 = prop3;  // (2)
    this.prop4 = prop4;  // (3)
}

Inheriting Prototype Properties

  • Shared properties such as methods are kept in the instance prototype.
Sub.prototype = Object.create(Super.prototype);
Sub.prototype.constructor = Sub;
Sub.prototype.methodB = ...;
Sub.prototype.methodC = ...;

Ensuring instanceof Works

  • “Ensuring that instanceof works” means that every instance of Sub must also be an instance of Super.

Making a 'Super' call on methods for Overidding

  • Home Object is the object that owns a method.
  1. Super.prototype: Start your search in Super.prototype, the prototype of Sub.prototype (the home object of the current method Sub.prototype.methodB).
  2. methodB: Look for a method with the name methodB.
  3. call(this, ...): Call the method found in the previous step, and maintain the current this.

Methods of All Objects

...

Reference: (SpeakingJS) (MDN)

ES6 Classes JS

https://medium.com/@dan_abramov/how-to-use-classes-and-sleep-at-night-9af8de78ccb4 https://medium.freecodecamp.org/elegant-patterns-in-modern-javascript-ice-factory-4161859a0eee

  • Classes are not hoisted

2 ways to define a class

  1. Class expression:
                    //[this name is optional]
const MyClass = class mine{};```
2. Class declaration: 
```javascript
class MyClass {}

Class Body

  • Can only contain methods, not data
  • 3 types of methods
class foo {
// 1. The constructor: defines the function that represents the class
    constructor(){}
// 2. Static: static properties (or class properties) are properties of the class itself, Static method calls are made directly on the class and are not callable on instances of the class.
    static staticMethod(){}
// 3. Prototype method: are properties of the class prototype and are usually methods and inherited by instances of the class
    protoTypeMethod(){}
    // some method names can be special like iterable (look it up) also look up generator methods
    ['dynamicName'](){}
// 4. get and set methods
    get getter(){}
    set setter(value){}
}
  • Static data properties are not supported yet, so instead you can do it by putting the data on 'this'
class Point {
    constructor(x, y) {
        //In a constructor function this does not have a value. It is a substitute for the new object. The value of 'this' will become the new object when a new object is created.        
        this.x = x;
        this.y = y;
    }
}
Point.ZERO = new Point(0, 0);

//or a static getter
class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    static get ZERO() {
        return new Point(0, 0);
    }
}

Subclassing

  • 'extends' keyword lets you create a subclass of an existing constructor

  • Base class: is a class without extends (like a parent class)

  • Derived class: is a class with extends

  • 'super' can be used in 2 ways:

  1. in a constructor to make the super-constructor call
  2. inside method definitions in order to reference super-properties
  • Static methods are inherited and can be called with super

  • In a derived class super() must come before this in a constructor and the constructor must have a super()

  • http://exploringjs.com/es6/ch_classes.html#_overriding-the-result-of-a-constructor (i dont see the use case for this)

  • If you don't specify a constructor, then in a non derived class the constructor will be empty and in a derived class the constructor will grabs super args

  • In es6 you can now subclass build-in classes, such as Error, Array, ...etc

Private Data in Classes

  • To Be Continued...

Classes Under the Hood

Composition over Inheritance

https://medium.com/javascript-scene/composing-software-an-introduction-27b72500d6ea https://medium.com/javascript-scene/why-composition-is-harder-with-classes-c3e627dcd0aa

JS Event Loop

Runtime Concepts

Call Stack (LIFO): function calls form a stack of frames. Heap: Objects are allocated in a heap which is just a name to denote a large mostly unstructured region of memory Event Queue (FIFO): JS runtime uses a message (i.e functions) queue (a list of messages to be processed). Each message has a function that gets called for the message to be handled.

Event Loop

Async JavaScript

Callback Functions + Async

Promises

Async Await

Memory Management

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management