Automatic Knockout model persistence (offline) with Amplify

Demo code for http://keestalkstech.com/2014/02/automatic-knockout-model-persistence-offline-with-amplify/

by Kees C. Bakker

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js"></script>
<label>Message:</label>
<input data-bind="value: message" />
<br/>
<label>Subject:</label>
<input data-bind="value: subject" />
<br/>
<button data-bind="click: function(){ window.alert(text()); }">Alert</button>|
<button onclick="window.location.reload(false); ">Reload</button>
<br/>
<br/>Check for more info:
<br/> <a href="http://keestalkstech.com/2014/02/automatic-knockout-model-persistence-offline-with-amplify/">http://keestalkstech.com/2014/02/automatic-knockout-model-persistence-offline-with-amplify/</a>

CSS

label {
    width:100px;
    display:inline-block;
}
body {
    font-family:arial;
    font-size:12px;
    line-height:1.5em;
}

JavaScript

init();

//model specification
function SimpleModel() {
  var _this = this;

  this.message = ko.observable('Hello');
  this.subject = ko.observable('World');
  this.text = ko.computed(function() {
    return _this.message() + ' ' + _this.subject() + '!';
  });
}

//new it up
var vm = new SimpleModel();
var options = {
  storage: sessionStorage
};

//bind to interface
ko.applyBindings(vm);

//persist it
ko.persistChanges(vm, 'vm-', options);

//alert 1 - should be 'Hello World!'
//at leaste the first time ;-)
alert('vm: ' + vm.text());

//change it
vm.message('Bye');

//alert 2 - should be 'Bye World!'
alert('vm: ' + vm.text());

//load a new one up to check
var vm2 = new SimpleModel();
ko.persistChanges(vm2, 'vm-', options);

//alert 3 - should be 'Bye World!'
alert('vm2: ' + vm2.text());


function init() {
  ko.trackChange = (store, observable, key) => {
    //initialize from stored value, or if no value is stored yet,
    //use the current value
    const value = store.get(key) || observable()

    //restore current value
    observable(value)

    //track the changes
    observable.subscribe(newValue => store.set(key, newValue))
  }

  const defaultOptions = Object.freeze({
    storage: localStorage,
    traverseNonObservableProperties: true,
  })

  ko.persistChanges = (model, prefix = "model-", options = defaultOptions) => {
    options = Object.assign({}, defaultOptions, options)

    console.log(options)

    const storageWrapper = {
      set: (key, value) => options.storage.setItem(key, JSON.stringify(value)),
      get: key => JSON.parse(options.storage.getItem(key)),
    }

    for (let n in model) {
      const observable = model[n]
      const key = prefix + n

      if (!ko.isObservable(observable)) {
        if (options.traverseNonObservableProperties) {
          ko.persistChanges(observable, key + "-", options)
        }
      } else if (!ko.isComputed(observable)) {
        //track change of observable
        ko.trackChange(storageWrapper,...