Holayn / knowledge

A place to collect notes on my learning / knowledge
0 stars 0 forks source link

JS #2

Open Holayn opened 4 years ago

Holayn commented 4 years ago
Holayn commented 4 years ago

Data types

undefined is a special value that indicates that the variable hasn't been set. The JS engine is saying the variable isn't set in memory.

undefined takes up memory space, as it is a special type of value.

null is a lack of existence - this variable has no value.

Built-in function constructors

Number and String

Holayn commented 4 years ago
Holayn commented 4 years ago

Event queue

Event loop

Event loop blocking

Holayn commented 4 years ago

Scope and scope chain

Functions

var c = {  
  log: function() {
    console.log(this); // c
  },
  log2: function() {
    var d = function() { console.log(this) }
    d(); // context where c.log2() is called
  },
  log3: function() {
    var self = this;
    console.log(self);
    var d = function() { console.log(self) }
    d(); 
  }
}

If statements

They don't create new scope

if (true) {
  // this if statement doesn't create a new scope
  // so varInIf is available in the global scope
  var varInIf = 'inside an if statement';
}
console.log(varInIf);  // logs 'inside an if statement'

let is block scoped so won't run into this problem var is only scoped to functions

Holayn commented 4 years ago

Namespacing

resource: https://javascriptweblog.wordpress.com/2010/12/07/namespacing-in-javascript/

module pattern:

var myApp = (function() {

  var id= 0;

  return {
      next: function() {
          return id++;    
      },

      reset: function() {
          id = 0;     
      }
    };  
})();   

The logic is shielded from the global scope by a function wrapper (usually self-invoking) which returns an object representing the module’s public interface.

By immediately invoking the function and assigning the result to a namespace variable, we lock up the module’s API in the namespace. Additionally any variables not included in the return value will remain forever private, visible only to the public functions that reference them.

other less ideal approaches:

direct assignment:

var myApp = {}

myApp.id = 0;

myApp.next = function() {
  return myApp.id++;  
}

myApp.reset = function() {
  myApp.id = 0;   
}

Object Literal Notation:

var myApp = {

  id: 0,

  next: function() {
      return this.id++;   
  },

  reset: function() {
      this.id = 0;    
  }
}
Holayn commented 4 years ago

Functions

When a function is called...

resources: link

`function foo() {
    console.log( this.a );
}

var obj = {
    a: 2,
    foo: foo
};

obj.foo(); // 2
function foo() {
    console.log( this.a );
}

var obj = {
    a: 2,
    foo: foo
};

var bar = obj.foo; // function reference/alias!

var a = "oops, global"; // `a` also property on global object

bar(); // "oops, global"
function foo() {
    console.log( this.a );
}

function doFoo(fn) {
    // `fn` is just another reference to `foo`

    fn(); // <-- call-site!
}

var obj = {
    a: 2,
    foo: foo
};

var a = "oops, global"; // `a` also property on global object

doFoo( obj.foo ); // "oops, global"

IIFEs

call(), apply(), bind()

Holayn commented 4 years ago

Closures

Functions will always have access to the variables it's supposed to have access to

image

You will have closures whenever having function declarations. "Closing" over variables so that have access to them when calling the function.

Useful for:

Holayn commented 4 years ago

Prototype

JS has prototypal inheritance involving a prototype chain

Everything is an object (except primitives) and they all have a prototype (except the ultimate JS base Object which is the bottom of the proto-chain.

instanceof goes up the __proto__ chain to see if in it

This is different from the scope chain!

prototype vs proto

Former is property of class constructor, latter is property of class instance

__proto__ is an object in every class instance that points to the prototype it was created from.

iPhone.prototype provides a blueprint for building an iPhone, newPhone.__proto__ affirms that the iPhone has indeed been built according to that specific blueprint

source

Constructors have a special property whose unfortunate name is prototype. The value of the property becomes the prototype of the instances created by that constructor.

function Foo() {}
console.log(Object.getPrototypeOf(new Foo()) === Foo.prototype); // true

var obj = new MyConstructorFunction();
obj.__proto__ === MyConstructorFunction.prototype // true

source

Note: __proto__ is a recent addition to the language (ES6). [[Prototype]] is what's referenced in the spec.

Object.defineProperty( Object.prototype, "__proto__", {
    get: function() {
        return Object.getPrototypeOf( this );
    },
    set: function(o) {
        // setPrototypeOf(..) as of ES6
        Object.setPrototypeOf( this, o );
        return o;
    }
} );

Side notes:

good tldr

Holayn commented 4 years ago

Building objects

Use the new keyword/operator when invoking a function to construct an object. Known as a "function constructor", a replacement for classes

.prototype()

When object is created by a "function constructor", its prototype chain (__proto__) points to the function's prototype property. Setting properties on the "function constructor"'s prototype will make them available to the objects created from that function constructor, since the newly created objects prototype chain points to the function's prototype property

Object.create()

Creates a new empty object, with its __proto__ pointing to whatever object that was passed into create() (vs normally where __proto__ points to the function constructor's prototype)

var person = {
  name: 'kai'
}
var wendy = Object.create(person);
wendy.name = 'wendy';
Holayn commented 4 years ago

ES6 Classes

class B extends A - prototype of class B points to A

Holayn commented 4 years ago

strict mode

Tells the parser to be stricter, clean errors instead of hiding them

Changes this behavior inside of functions - see here

a whole host of other things!

Makes it impossible to accidentally create global variables. Makes assignments which would otherwise silently fail to throw an exception. Makes attempts to delete undeletable properties throw (where before the attempt would simply have no effect). Requires that function parameter names be unique. this is undefined in the global context. It catches some common coding bloopers, throwing exceptions. It disables features that are confusing or poorly thought out.

Holayn commented 4 years ago

Hoisting

The execution context has two phases: the creation phase and the execution phase.

Creation phase

Execution phase

Example case of seeing this happening:

var text = 'outside';
function logIt(){
    console.log(text);
    var text = 'inside';
};
logIt(); // logs undefined since variable DECLARATIONS are hoisted

// really looks like this:
var text;
console.log(text);
text = 'inside'

Function declarations are hoisted over variable declarations but not over variable assignments

Readings: link

Variable assignment over function declaration

var double = 22;

function double(num) {
  return (num*2);
}

console.log(typeof double); // Output: number

Function declarations over variable declarations

var double;

function double(num) {
  return (num*2);
}

console.log(typeof double); // Output: function

BASICALLY

Holayn commented 4 years ago

Static

Static methods

Methods can be assigned to the class function itself, not to its prototype.

This is the same thing as assigning things to a class itself.

Used to implement functions that belong to the class but not to any particular object of that class.

class Article {
  constructor(title, date) {
    this.title = title;
    this.date = date;
  }

  static compare(articleA, articleB) {
    return articleA.date - articleB.date;
  }
}

resources: link1 link2

Holayn commented 4 years ago

Arrow functions

They don't have their own this pointing to their execution context

Uses lexical scope to resolve this - i.e. the this of wherever the function was defined. "The value of this inside an arrow function is always inherited from the enclosing scope." Bound to the same this context of where it was created.

Useful for accessing the this of the current env, i.e. in callbacks (map).

Practically equivalent:

function () {
  return this;
}.bind(this);

() => {
  return this;
};

The this binding can never be overriden!

resources: link1 link2 link3

Holayn commented 4 years ago

Immutability

Related to functional programming.

Not mutating objects, instead create new copies of them. Less complicated programs (since don't have to worry about objects mutating)

Naive implementations of immutable data structures and its operations can result in extremely poor performance because new objects are created each time. It is recommended to use libraries for efficient immutable data structures and operations that leverage on structural sharing.

Reads:

Holayn commented 3 years ago

TIL: https://stackoverflow.com/questions/7744611/pass-variables-by-reference-in-javascript another reason why modifying params is a bad idea