Skip to content

Instantly share code, notes, and snippets.

@SaulDoesCode
Last active February 22, 2016 21:40
Show Gist options
  • Save SaulDoesCode/bcfd2092d42a8a7a1c33 to your computer and use it in GitHub Desktop.
Save SaulDoesCode/bcfd2092d42a8a7a1c33 to your computer and use it in GitHub Desktop.
Small Observable function for data-binding and stuff using Proxies or Object.observe if Proxies are unavailable.
"use strict";
((doc,root) => {
let isArraylike = o => typeof o['length'] !== "undefined",
isFunc = o => typeof o === 'function';
function omitFrom(Arr, ...values) {
if (values.length === 1) {
let temp = [],
string = is.String(Arr);
if (isArraylike(Arr)) Arr = toArr(Arr)
for (let i = 0, index = Arr.indexOf(values[0]); i < Arr.length; i++)
if (i !== index) temp.push(Arr[i]);
return string ? temp.join('') : temp;
}
values.forEach(val => Arr = omitFrom(Arr, val));
return Arr;
}
root.observable = obj => {
Object.defineProperty(obj,'listeners',{
value : [],
enumerable : false,
});
Object.defineProperty(obj,'removeListener',{
value : function(fn) {
if(isFunc(fn) && obj.listeners.includes(fn)) obj.listeners = omitFrom(obj.listeners,fn);
},
enumerable : false,
});
Object.defineProperty(obj,'listen',{
get : function () {
return obj.listeners[obj.listeners - 1];
},
set : function (func) {
if(isFunc(func)) obj.listeners.push(func);
},
enumerable : false,
});
try {
return new Proxy(obj,{
get : function(target,key,reciever) {
return target[key];
},
set : function(target,key,value,reciever) {
target.listeners.forEach(fn => fn(target,key,value));
return target[key] = value;
}
});
} catch(e) {
try {
Object.observe(obj,changes => changes.forEach(change => {
if(change.type === 'add' || change.type === 'update') obj.listeners.forEach(fn => fn(obj,change.name,obj[change.name]));
}));
return obj;
} catch (e2) {}
}
}
})(document,self);
@stephband
Copy link

Hi. If I've read this right,

target.listeners.forEach(fn => fn(target,key,value));

...will fail if one of the listeners removes itself from listeners. The following listener will be skipped. I think you need to clone listeners before calling .forEach on it.

target.listeners.slice().forEach(...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment