Slide navigation: Forward with space bar, →, or PgDn. Backwards with ← or PgUp.
let harry = { name: 'Harry Smith', salary: 90000 }
harry = {
name: 'Harry Smith',
salary: 90000,
raiseSalary: function(percent) {
this.salary *= 1 + percent / 100
}
}harry.raiseSalary(10)
this is set to harry in the call.harry = {
...
raiseSalary(percent) {
this.salary *= 1 + percent / 100
}
}function createEmployee(name, salary) {
return {
name,
salary,
raiseSalary: function(percent) {
this.salary *= 1 + percent / 100
}
}
}raiseSalary property.

const employeePrototype = {
raiseSalary: function(percent) {
this.salary *= 1 + percent / 100
}
}function createEmployee(name, salary) {
const result = { name, salary }
Object.setPrototypeOf(result, employeePrototype)
return result
}
harry.raiseSalary(5)
harry.raiseSalary = function(rate) { this.salary = Number.MAX_VALUE }new operator.function Employee(name, salary) {
this.name = name
this.salary = salary
}Employee.prototype.raiseSalary = function(percent) {
this.salary *= 1 + percent / 100
}const harry = new Employee('Harry Smith', 90000)new operator:
.prototypethis
Employee isn't a class—it's a function.class Employee {
constructor(name, salary) {
this.name = name
this.salary = salary
}
raiseSalary(percent) {
this.salary *= 1 + percent / 100
}
}Employee still isn't a class—it's a function.constructorget:
class Person {
constructor(last, first) { this.last = last; this.first = first }
get fullName() { return `${this.last}, ${this.first}` }
}const harry = new Person('Smith', 'Harry')
const harrysName = harry.fullName // 'Smith, Harry'set:
class Person {
...
set fullName(value) {
const parts = value.split(/,\s*/)
this.last = parts[0]
this.first = parts[1]
}
}
harry.fullName = 'Smith, Harold'
class BankAccount {
balance = 0
deposit(amount) { this.balance += amount }
...
}#
class BankAccount {
#balance = 0
deposit(amount) { this.#balance += amount }
...
}#.class BankAccount {
...
static percentOf(amount, rate) { return amount * rate / 100 }
...
addInterest(rate) {
this.balance += BankAccount.percentOf(this.balance, rate)
}
}BankAccount.percentOf = function(amount, rate) { return amount * rate / 100 }
class BankAccount {
static OVERDRAFT_FEE = 30
...
withdraw(amount) {
if (this.balance < amount) {
this.balance -= BankAccount.OVERDRAFT_FEE
}
...
}
}BankAccount.OVERDRAFT_FEE = 30
class BankAccount {
...
static get OVERDRAFT_FEE() {
if (this.overdraftFee === undefined)
this.overdraftFee = 10
return this.overdraftFee // this is the constructor
}
static set OVERDRAFT_FEE(newValue) {
if (newValue > this.overdraftFee) {
this.overdraftFee = newValue
}
}
class Employee {
constructor(name, salary) { ... }
raiseSalary(percent) { ... }
...
}
class Manager extends Employee {
getSalary() { return this.salary + this.bonus }
...
}
const boss = new Manager(...)
boss.raiseSalary(10) // Calls Employee.prototype.raiseSalary
class Employee {
...
getSalary() { return this.salary }
}
class Manager extends Employee {
...
getSalary() { return this.salary + this.bonus }
}
const empl = ... const salary = empl.getSalary()
class Manager {
...
getSalary() { return super.getSalary() + this.bonus }
}super starts lookup with the parent of the prototype object in which the method was defined. getSalary defined in Manager.prototypeEmployee.prototypeclass Manager extends Employee {
...
get salary() { return super.salary + this.bonus }
}class Manager extends Employee {
constructor(name, salary, bonus) {
super(name, salary)
this.bonus = bonus
}
...
}this is valid after call to superclass Manager extends Employee {
// No constructor
getSalary() { ... }
}
const boss = new Manager('Mary Lee', 180000)
// Calls Employee('Mary Lee', 180000)
const Employee = class {
constructor(name, salary) { ... }
raiseSalary(percent) { ... }
}function withToString(base) {
return class extends base {
toString() {
let result = '{'
for (const key in this) {
if (result !== '{') result += ', '
result += `${key}=${this[key]}`
}
return result + '}'
}
}
}const BetterEmployee = withToString(Employee)
e = new BetterEmployee('Mad Hatter', 90000)
console.log(e.toString())
// Prints {name=Mad Hatter, salary=90000}, not [object Object]this Referencenew ClassName sets this to the new object.object.method(arguments) sets this to the object on which the method is invoked.new
class syntax.this is undefined with old-style constructor.Number('3')/new Number('3')new
const harrysAccount = new BankAccount()
const action = harrysAccount.deposit
action(1000) // Error—this doesn't point to any bank accountthis Referenceclass BankAccount {
...
spreadTheWealth(accounts) {
accounts.forEach(function(account) {
account.deposit(this.balance / accounts.length)
// Error—this undefined inside nested function
})
this.balance = 0
}
}this is statically captured in arrow function.
spreadTheWealth(accounts) {
accounts.forEach(account => {
account.deposit(this.balance / accounts.length) // this correctly bound
})
this.balance = 0
}
this Referencethis Referenceconst observers = []
function notifyObservers() {
for (let i = 0; i < observers.length; i++) {
observers[i]()
}
}
class BankAccount {
constructor() { this.balance = 0 }
deposit(amount) {
this.balance += amount
notifyObservers()
}
...
}obj.method(args) is the same as obj['method'](args)obj[index](args), this is objthis Referencethis is the array of observers!
class UserInterface {
log(message) { ... }
start() {
const acct = new BankAccount()
observers.push(function() { this.log('More money!') })
acct.deposit(1000)
}
}
this is problematic.