To understand what’s happening under the hood of modern JS frameworks (like Vue.js) let’s focus on how to make an object property observable.

Let’s define our task. We have this object

const dog = {
 name: 'Sparky',
 isSleeping: false
}

We would like to be notified, whenever our dog is hungry. How to do that?

Object.defineProperty() to the rescue!

We can make a wrapper for this object, keep value (thanks to closures) and notify everytime something happens.

function Dog (name) {
  let isSleeping = false
  Object.defineProperty(this, 'isSleeping', {
    get () {
      console.log(`checking if ${name} is sleeping`)
      return isSleeping
    },
    set (newVal) {
      console.log(`${name} is${newVal ? '' : ' not'} sleeping`)
      isSleeping = newVal
    }
  })
}

const dog = new Dog('Sparky')

console.log(dog.isSleeping) 
dog.isSleeping = true
console.log(dog.isSleeping)
dog.isSleeping = false

Thanks to access to get/set hooks, we can do everything we want to track changes. But this wrapper requires to use new keyword. But could we tackle this problem without changing the initial API of dog?

We would like to track the change of isHungry property. Let’s try to write a function that will take an object and key as a parameter

const dog = {
  name: 'Sparky',
  isSleeping: false
}

function observe (obj, key, callback) {
  let observedValue = obj[key]

  Object.defineProperty(obj, key, {
    get () {
      return observedValue
    },
    set (newVal) {
      callback(newVal)
      observedValue = newVal
      return observedValue
    }
  })
}

observe(dog, 'isSleeping', (key) => {
  console.log(`isSleeping value changed to ${key}`)
})

dog.isSleeping = true
dog.isSleeping = false

Our function’s callback will be triggered everytime the value of property changes, and we do not have to change initial API!


resources


Karol Świeca

My thougths on JavaScript, AWS Cloud and other aspects of being Software Engineer