Advanced JS
Execution context
- Global context is created first
- Global object
window
in browser
global
in node
this
variable created and points to global object
- 2 Phases
- Creation
- Create global object
- Create pointer called this which points to the context object
- Set up memory for variables and functions
- Assign variable declarations a default value of undefined while placing function declarations in memory
- Execution
- The process of assigning the default value of undefined during creation is called hoisting
- Function execution context
- When a function is invoked
- Like above but create an arguments object instead of a global
- Any argument you pass in is added as a local variable as well
- Execution stack
- New function contexts pushed to stack
- Popped off on return (except closures are kept around)
- Scopes
- If a variable is not found in the current execution context then previous contexts on the stack are checked
- Any variable in the global execution context will be added as a property on the global object
this, apply, bind
- This changes based on how function is invoked
- Implicit binding
- Look at the left of the dot when the function is invoked
user.greet()
- User is this
user.mother.greet()
- Mother is this
- Explicit binding
- Explicitly setting
user
as this
greet.call(user, arg1, arg2, ...)
- Args passed as an array
greet.apply(user, [arg1, arg2, ...])
- Bind returns a function with the binding which can be invoked later
greet.bind(user)()
- New binding
new
creates a bound new object for you and calls the constructor with it
- Lexical binding
- Determined lexically, normal lookup rules
- Arrow functions don't create a
this
- Window binding
- No other rules are met,
this
is the window
object
- Strict mode will make it undefined
Event loop
- When a Web or C++ API is finished it pushes a callback function into the task queue
- When the JS call stack is empty the JS engine will look ath the task queue to find something to run
- Promise callbacks go in the job queue which has a higher priority than the task queue
Prototype chain
function Dog(name, energy, breed) {
Animal.call(this, name, energy);
this.breed = breed;
}
const charlie = new Dog("Charlie", 10, "Goldendoodle");
- Gives the child parent fields
- The parent constructor assigns them on the context passed in by
new
- Won't add methods because we haven't set the prototype to resolve to Animal
Dog.prototype = Object.create(Animal.prototype);
- Overwrote Dog's prototype with Animal's
.constructor
will give Animal's constructor
Dog.prototype.constructor = Dog;
- ES6
class Dog extends Animal {
...
constructor(name, energy, breed) {
super(name, energy);
this.breed = breed;
}
}
Composition vs inheritance
- Inheritance
- Want to share some behaviours between separate groups of classes
- Could put all behaviour on a parent
- God object
- Composition
- Make object based on behaviour
const barker = (state) => ({
bark() {
console.log('woof woof');
state.energy -= .1;
}
})
- Returns an object with a
bark
method
- Merge object with the behaviour object
Object.assign(dog, barker(dog));