Skip to content

Latest commit

 

History

History
201 lines (144 loc) · 7.58 KB

Object-oriented programming in JavaScript.md

File metadata and controls

201 lines (144 loc) · 7.58 KB

Object-oriented programming in JavaScript

What is an object and how do I create it?

  • Array [ ]: ordered collection of elements, referenced by indexes
  • Object { }: unordered collection of key/value pairs, referenced explicitly
    • Accessing an object's properties is not entirely the same as in Python, as keys in Javascript don't need to be hashable (strings, numbers, floats). You access them either by
      • dot notation: object.key, or
      • bracket notation: object['key']
    • Both can be extended for nested objects.
Creating objects
const myobject = { }; // or
const myObject = new Object();
Adding or changing properties

Simply specify property name and give it a value. We can also add methods (i.e. functions) to objects!

Removing properties
`delete object['key'];` 
// or
`delete object.key;`

Primitives (string, number, boolean, float) are immutable, meaning they only change inside a function. Objects are reference-based and thus are mutable, meaning values change both inside and outside a function. Changes in a copy will thus also change the original. Thus, when comparing (===) objects, what matters is the reference.

Calling methods
`object['method']();` 
// or
`object.method();`
Returning keys and values in an array
`Object.keys(objectName);` 
// and
`Object.values(objectName);`
  • If desired, an argument can be passed inside the brackets.

The 'this' keyword

We use this to refer to the object at hand. How a function is invoked determines the value of this inside the function.

  • When invoked from a constructor function, the value of this is the newly created object (see 'Constructor functions').
  • When invoked as a method, the value of thisis whatever is left of the dot at invocation (i.e. the object).
  • When invoked as a regular function, the value of this is the global window object.
    • Every var (not let and const!) declaration made at the global level, i.e. outside of a function, becomes a property on the window object.
    • Likewise, every global function declaration becomes a method on the window object.
      • Global variables and functions are not ideal (tight coupling, name collisions), so only write them as a last resort!

Functions at runtime

JavaScript functions are first-class objects, and can be ...

  • stored in a variable,
  • passed in as an argument in another function (we call the passed-in argument the callback function),[*] and
  • returned from another function (the so-called higher-order function)
    • It can be called using double parentheses.

[*] Example array methods:

  1. forEach() takes in a callback function and invokes that functoin for each element in the array, array.forEach(callbackFunc);

  2. map() does the same, but returns a new array based on what's returned from the callback function, and

    array.map(function(arrayitem) {
        return arrayitem.length;
    });
    
  3. filter() does the same as map(), but is used as a test: only the items that pass are included in the new array.

    array.filter(function(arrayitem) {
        return arrayitem.length < 6;
    });
    

Note: Functions can be invoked by (), objects can NOT.

Besides global scope and function scope, there is runtime scope. This is the context of the function, i.e. the set of variables available for the function to use. A function has acces to: function's arguments, local variables, variables from parent function scope, and global variables.

const a = 'a'; // global variable
function parent() {
    const b = 'b'; // variable from parent scope
    function child() {
        const c = 'c'; // local variable within function
    }
};

CHILD > PARENT > GLOBAL SCOPE CHAIN: start sequence thoughts from innermost function and work outwards from there, building what innermost needs all the way to global window.

Functions will retain the scope chain plus access even if they're invoked somewhere else than where it was declared.

Note:_ if two variables have the same name, the one that is found 'first' by the JavaScript engine prevails (variable shadowing).

Closure

The process of a function retaining access to its scope. Every function has closure.

Immediately-Invoked Function Expressions (IIFEs)

Functions that are called immeciately after they're defined.

Type Code
Declaration function logger() {console.log('Hello!')};
Expression (function logger() {console.log('Hello!')});
IIFE (function logger(x) {console.log('Hello!')})();

IIFEs can also wrap around nested functions. They create a private scope that protects variables and methods from being used, because the function is called immediately and thus variables are called immediately. This prevents from unwanted mutations or side-effects because of external access. The returned functions are still publicly accessible, but the variables defined within them are not.

Classes

Classes are categories of objects.

  • Object: properties and methods
  • Class: blueprint for an object
Constructor functions

Start with a capital letter; Must be called with new; Has object created automatically

new SoftwareDev() {
    this.favLang = 'JS'; // this refers to SoftwareDev
}; // no return statement!

From here, you can create a new object (an instance) - as many as you like.

let developer = new SoftwareDeveloper();

Constructor functions accept arguments! We could update the previous as follows:

function SoftwareDeveloper (name) {
    this.favLang = 'JS';
    this.name = name;
    this.introduce = function() {
        console.log(`I'm ${this.name}!`);
    }
};

To instantiate a new object from here:

    let myself = new SoftwareDeveloper('Diana');

If we would then invoke myself.name, it would yield Diana.

So: Define:

new FuncName();

Add properties:

function FuncName(arg1, arg2) {
    this.arg1 = arg1;
    this.arg2 = arg2;
    this.prop3 = x;
    this.prop4 = function() {
        console.log(`Hello ${arg2}!`);
    };
};

Assign to variable to instantiate new object or start with 2. and then add:

const objName = new FuncName(arg1, arg2);

To check if objName was created with FuncName: objName instanceof FuncName.

Setting the value of this ourselves

  1. call()
  2. apply()
  3. bind()

Prototypal inheritance

We can add methods to the constructor function's prototype property. The prototype property is an object. All objects created by that construcor are linked to this prototype object.

Object.prototype.method = function() {
    if (this.canTalk) {
        console.log('Hi, I am ' + this.name);
    }
};
Prototype chain
  • Objects own properties and methods ˅
  • Constructor prototype ˅
  • Object() object (top level parent) ˅
  • Still not found? Undefined
Check where property comes from
  1. hasOwnProperty();
  2. isPrototypeOf();
  3. Object.getPrototypeOf();

Every time an object is created, a special property is assigned to it under the hood: constructor. It returns a reference to the constructor function that created that object (object.constructor).

Subclasses

To set up the prototype of an object ourselves, we use Object.create(). This is a clean method to establish prototypal inheritance.