Skip to content

Instantly share code, notes, and snippets.

@catc
Created February 7, 2019 03:33
Show Gist options
  • Save catc/e5a2f95569cd8b47f4bfecc9280d1ce3 to your computer and use it in GitHub Desktop.
Save catc/e5a2f95569cd8b47f4bfecc9280d1ce3 to your computer and use it in GitHub Desktop.
airbnb technical screen
console.clear()
class Model {
constructor(props = {}){
this.data = props
this.silent = {}
this.subs = {
change: {
},
handleChangeAll: []
}
}
get(key){
return this.data[key]
}
set(key, val, opts = {}){
const oldVal = this.data[key]
// store silent
if (opts.silent){
this.silent[key] = true
}
// trigger event
this._trigger(key, oldVal, val)
return this.data[key] = val
}
has(key){
return this.data.hasOwnProperty(key)
}
unset(key){
const oldVal = this.data[key]
this._trigger(key, oldVal, undefined)
return delete this.data[key]
}
_trigger(key, oldVal, newVal){
if (!this.silent[key]){
// trigger all
this.subs.handleChangeAll.forEach(sub => sub(key, oldVal, newVal))
// trigger specific keya
if (this.subs.change[key] && this.subs.change[key].length){
this.subs.change[key].forEach(sub => sub(oldVal, newVal))
}
}
}
on(event, fn){
let [eventName, key] = event.split(':')
if (key){
const subs = this.subs[eventName][key]
if (!subs){
this.subs[eventName][key] = []
}
this.subs[eventName][key].push(fn)
} else {
// catch all
this.subs.handleChangeAll.push(fn)
}
}
}
const person = new Model({ name: 'auster', age: 27 });
console.log(person.get('name')); // auster
console.log(person.get('age')); // 27
person.set('job', 'engineer');
// console.log(person.get('job')); // engineer
const dog = new Model();
dog.set('name', 'ruffy');
console.log(dog.get('name')); // ruffy
console.log(dog.has('age')); // false
dog.set('age', 10, { silent: true });
console.log(dog.has('age')); // true
dog.unset('name');
console.log(dog.has('name')); // false
console.log('---------')
person.on('change', function (attr, oldValue, newValue) {
console.log(`${attr} has changed from ${oldValue} to ${newValue}`);
});
person.on('change', function (attr, oldValue, newValue) {
console.log(`${attr} has changed from ${oldValue} to ${newValue}`);
});
person.on('change:name', function(oldValue, newValue) {
console.log(`specifically name changed from ${oldValue} to ${newValue}`);
});
person.set('name', 'kevin');
// name has changed from auster to kevin
// name has changed from auster to kevin
// specifically name has changed from auster to kevin
person.set('height', 10);
// height has changed from undefined to 10
// height has changed from undefined to 10
dog.on('change:age', function() {
throw new Error('this code should not run');
});
dog.set('age', 20);
person.unset('name');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment