jsPerf.app is an online JavaScript performance benchmark test runner & jsperf.com mirror. It is a complete rewrite in homage to the once excellent jsperf.com now with hopefully a more modern & maintainable codebase.
jsperf.com URLs are mirrored at the same path, e.g:
https://jsperf.com/negative-modulo/2
Can be accessed at:
https://jsperf.app/negative-modulo/2
Various techniques for observing changes in objects.
var observedSubject = {
name:'Someone'
};
var deliveredSubject = {
name:'Someone'
};
var checkedSubject = {
name:'Someone'
};
var definedSubject = {
name:'Someone'
};
var unobservedSubject = {
name: 'Someone'
};
function noop(newValue, oldValue){ }
function handleChanges(changes){
var updates = {},
i = changes.length;
while(i--) {
var change = changes[i],
name = change.name;
if(!(name in updates)){
updates[name] = true;
noop(change.object[name], change.oldValue);
}
}
}
var changeRecordHead = {
isDirty:function(){
return false;
},
nextChangeRecord:{
obj:checkedSubject,
currentValue:checkedSubject.name,
callbacks: [noop],
getter:function(obj){
return obj.name;
},
isDirty: function(){
var newValue = this.getter(this.obj);
if(this.currentValue != newValue){
this.oldValue = this.currentValue;
this.currentValue = newValue;
return true;
}
},
invoke:function(){
var callbacks = this.callbacks,
i = callbacks.length,
newValue = this.currentValue,
oldValue = this.oldValue;
while(i--) {
callbacks[i](newValue, oldValue);
}
},
nextChangeRecord:{
isDirty:function(){
return false;
}
}
}
};
function digest(){
var changeRecord = changeRecordHead;
var currentDirty = dirtyHead = { invoke:function(){}};
while(changeRecord){
if(changeRecord.isDirty()){
currentDirty = currentDirty.nextDirty = changeRecord;
}
changeRecord = changeRecord.nextChangeRecord;
}
currentDirty = dirtyHead;
while(currentDirty){
currentDirty.invoke();
currentDirty = currentDirty.nextDirty;
}
}
function PropertyObserver(obj, propertyName){
this.obj = obj;
this.propertyName = propertyName;
this.currentValue = obj[propertyName];
this.callbacks = [];
}
PropertyObserver.prototype.getValue = function(){
return this.currentValue;
}
PropertyObserver.prototype.setValue = function(newValue){
var oldValue = this.currentValue;
if(oldValue != newValue){
this.currentValue = newValue;
var callbacks = this.callbacks,
i = callbacks.length;
while(i--) {
callbacks[i](newValue, oldValue);
}
}
}
PropertyObserver.prototype.subscribe = function(callback){
var callbacks = this.callbacks;
callbacks.push(callback);
return {
dispose:function(){
callbacks.splice(callbacks.indexOf(callback), 1);
}
};
}
function createObserver(obj, propertyName){
var observer = new PropertyObserver(obj, propertyName);
Object.defineProperty(obj, propertyName, {
configurable: true,
enumerable: true,
get: observer.getValue.bind(observer),
set: observer.setValue.bind(observer)
});
return observer;
}
Object.observe(observedSubject, handleChanges, ['update']);
Object.observe(deliveredSubject, noop, ['update']);
var subscription = createObserver(definedSubject, 'name').subscribe(noop);
Object.unobserve(observedSubject, handleChanges);
Object.unobserve(deliveredSubject, noop);
subscription.dispose();
Ready to run.
Test | Ops/sec | |
---|---|---|
Object.observe |
| ready |
Object.deliverChangeRecords |
| ready |
Dirty Checking |
| ready |
Getter/Setter |
| ready |
You can edit these tests or add more tests to this page by appending /edit to the URL.