- 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']
- dot notation:
- Both can be extended for nested objects.
- 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
const myobject = { }; // or
const myObject = new Object();
Simply specify property name and give it a value. We can also add methods (i.e. functions) to objects!
`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.
`object['method']();`
// or
`object.method();`
`Object.keys(objectName);`
// and
`Object.values(objectName);`
- If desired, an argument can be passed inside the brackets.
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
this
is whatever is left of the dot at invocation (i.e. the object). - When invoked as a regular function, the value of
this
is the globalwindow
object.- Every
var
(notlet
andconst
!) declaration made at the global level, i.e. outside of a function, becomes a property on thewindow
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!
- Every
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:
-
forEach()
takes in a callback function and invokes that functoin for each element in the array,array.forEach(callbackFunc);
-
map()
does the same, but returns a new array based on what's returned from the callback function, andarray.map(function(arrayitem) { return arrayitem.length; });
-
filter()
does the same asmap()
, 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).
The process of a function retaining access to its scope. Every function has closure.
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 are categories of objects.
- Object: properties and methods
- Class: blueprint for an object
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
.
call()
apply()
bind()
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);
}
};
- Objects own properties and methods ˅
- Constructor prototype ˅
- Object() object (top level parent) ˅
- Still not found?
Undefined
hasOwnProperty();
isPrototypeOf();
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
).
To set up the prototype of an object ourselves, we use Object.create()
. This is a clean method to establish prototypal inheritance.