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
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://cdn.rawgit.com/jdarling/Object.observe/master/Object.observe.poly.js"></script>
<script src="http://cdn.rawgit.com/Polymer/observe-js/master/src/observe.js"></script>
<script>
var funcNameRegex = /function (.{1,})\(/;
function getClass(object) {
var results = (funcNameRegex).exec((object).constructor.toString());
return (results && results.length > 1) ? results[1] : "";
}
function Observable(body) {
this._observers = {};
this._trackChanging = false;
if (body) {
for (var key in body) {
this[key] = body[key];
}
}
this._updatingProperty = false;
this.on = this.addEventListener = this.addObserver;
this.off = this.removeEventListener = this.removeObserver;
}
Object.defineProperty(Observable.prototype, "typeName", {
get: function () {
return getClass(this);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Observable.prototype, "updatingProperty", {
get: function () {
return this._updatingProperty;
},
enumerable: true,
configurable: true
});
Observable.prototype.addObserver = function (eventNames, callback, position) {
var _this = this;
Observable.verifyCallback(callback);
var events = eventNames.split(",");
events.forEach(function (event) {
var list = _this.getEventList(event.trim(), true);
if ("undefined" !== typeof position) {
if ((0 > position) || (list.length < position)) {
throw new Error("Invalid observer position: " + position);
}
list.splice(position, 0, callback);
} else {
list.push(callback);
}
});
};
Observable.prototype.removeObserver = function (eventNames, callback) {
var _this = this;
var events = eventNames.split(",");
events.forEach(function (event) {
if (callback) {
var list = _this.getEventList(event.trim(), false);
if (list) {
var index = list.indexOf(callback);
if (index >= 0) {
list.splice(index, 1);
}
}
} else {
_this._observers[event.trim()] = undefined;
}
});
};
Observable.prototype.on = function (eventNames, callback, position) {
this.addObserver(eventNames, callback);
};
Observable.prototype.off = function (eventNames, callback) {
this.removeObserver(eventNames, callback);
};
Observable.prototype.addEventListener = function (eventNames, callback, position) {
this.addObserver(eventNames, callback);
};
Observable.prototype.removeEventListener = function (eventNames, callback) {
this.removeObserver(eventNames, callback);
};
Observable.prototype.setProperty = function (name, value) {
if (this._updatingProperty || this[name] === value) {
return;
}
this._updatingProperty = true;
var data = this.createPropertyChangeData(name, value);
if (this.hasObservers(Observable.propertyChangeEvent) && this._trackChanging) {
data.phase = 0 /* Changing */;
this.notify(data);
if (data.cancel) {
this._updatingProperty = false;
return;
}
}
data.phase = 1 /* Changed */;
this.setPropertyCore(data);
this.notify(data);
this._updatingProperty = false;
};
Observable.prototype.getProperty = function (name) {
return this[name];
};
Observable.prototype.setPropertyCore = function (data) {
this[data.propertyName] = data.value;
};
Observable.prototype.notify = function (data) {
var observers = this.getEventList(data.eventName);
if (!observers) {
return;
}
var i, j, callback;
var value = data.value;
for (i = 0; i < observers.length; i++) {
callback = observers[i];
callback(data);
if (value !== data.value) {
for (j = 0; j < i; j++) {
callback = observers[j];
callback(data);
}
value = data.value;
}
}
};
Observable.prototype.hasObservers = function (eventName) {
return eventName in this._observers;
};
Observable.prototype.createPropertyChangeData = function (name, value) {
return {
eventName: Observable.propertyChangeEvent,
propertyName: name,
sender: this,
value: value,
cancel: false
};
};
Observable.prototype.getEventList = function (eventName, createIfNeeded) {
if (!eventName) {
throw new TypeError("EventName must be valid string.");
}
var list = this._observers[eventName];
if (!list && createIfNeeded) {
list = [];
this._observers[eventName] = list;
}
return list;
};
Observable.verifyCallback = function (callback) {
if (!callback || typeof callback !== "function") {
throw new TypeError("Callback must be a valid function.");
}
};
Observable.prototype.emit = function (eventNames) {
var _this = this;
var events = eventNames.split(",");
events.forEach(function (event) {
_this.notify({ eventName: event.trim(), sender: _this });
});
};
Observable.propertyChangeEvent = "propertyChange";
</script>
var foo = {
bar: "hello"
}
var changes = [];
Object.observe(foo, function(changes) {
changes.push(changes)
}, [ "update" ]);
changes = [];
var observer = new ObjectObserver(foo);
observer.open(function(added) {
changes.push(added);
}, foo);
changes = [];
var ourObservable = new Observable();
ourObservable.on("propertyChange", function(args){
changes.push(args);
});
Ready to run.
Test | Ops/sec | |
---|---|---|
Object.observe |
| ready |
Polymer |
| ready |
Our Observable |
| ready |
You can edit these tests or add more tests to this page by appending /edit to the URL.