From 627d708efb96d250141d2d2f33ef890c5bc73676 Mon Sep 17 00:00:00 2001 From: Philippe Mimms Date: Mon, 19 Oct 2015 00:17:27 -0400 Subject: [PATCH] Replaced for-in loops in DataSet.js and DataView.js with Object-key iteration of cached length for greater computational performance. --- lib/DataSet.js | 260 ++++++++++++++++++++++++++---------------------- lib/DataView.js | 29 +++--- 2 files changed, 151 insertions(+), 138 deletions(-) diff --git a/lib/DataSet.js b/lib/DataSet.js index e8d1c973..b87ddcd7 100644 --- a/lib/DataSet.js +++ b/lib/DataSet.js @@ -60,15 +60,15 @@ function DataSet (data, options) { // all variants of a Date are internally stored as Date, so we can convert // from everything to everything (also from ISODate to Number for example) if (this._options.type) { - for (var field in this._options.type) { - if (this._options.type.hasOwnProperty(field)) { - var value = this._options.type[field]; - if (value == 'Date' || value == 'ISODate' || value == 'ASPDate') { - this._type[field] = 'Date'; - } - else { - this._type[field] = value; - } + var fields = Object.keys(this._options.type); + for (var i = 0, len = fields.length; i < len; i++) { + var field = fields[i]; + var value = this._options.type[field]; + if (value == 'Date' || value == 'ISODate' || value == 'ASPDate') { + this._type[field] = 'Date'; + } + else { + this._type[field] = value; } } } @@ -184,7 +184,7 @@ DataSet.prototype._trigger = function (event, params, senderId) { subscribers = subscribers.concat(this._subscribers['*']); } - for (var i = 0; i < subscribers.length; i++) { + for (var i = 0, len = subscribers.length; i < len; i++) { var subscriber = subscribers[i]; if (subscriber.callback) { subscriber.callback(event, params, senderId || null); @@ -340,7 +340,7 @@ DataSet.prototype.get = function (args) { // build options var type = options && options.type || this._options.type; var filter = options && options.filter; - var items = [], item, itemId, i, len; + var items = [], item, itemIds, itemId, i, len; // convert items if (id != undefined) { @@ -361,12 +361,12 @@ DataSet.prototype.get = function (args) { } else { // return all items - for (itemId in this._data) { - if (this._data.hasOwnProperty(itemId)) { - item = me._getItem(itemId, type); - if (!filter || filter(item)) { - items.push(item); - } + itemIds = Object.keys(this._data); + for (i = 0, len = itemIds.length; i < len; i++) { + itemId = itemIds[i]; + item = me._getItem(itemId, type); + if (!filter || filter(item)) { + items.push(item); } } } @@ -391,9 +391,11 @@ DataSet.prototype.get = function (args) { // return the results if (returnType == 'Object') { - var result = {}; - for (i = 0; i < items.length; i++) { - result[items[i].id] = items[i]; + var result = {}, + resultant; + for (i = 0, len = items.length; i < len; i++) { + resultant = items[i]; + result[resultant.id] = resultant; } return result; } @@ -422,6 +424,7 @@ DataSet.prototype.getIds = function (options) { filter = options && options.filter, order = options && options.order, type = options && options.type || this._options.type, + itemIds = Object.keys(data), i, len, id, @@ -434,29 +437,27 @@ DataSet.prototype.getIds = function (options) { if (order) { // create ordered list items = []; - for (id in data) { - if (data.hasOwnProperty(id)) { - item = this._getItem(id, type); - if (filter(item)) { - items.push(item); - } + for (i = 0, len = itemIds.length; i < len; i++) { + id = itemIds[i]; + item = this._getItem(id, type); + if (filter(item)) { + items.push(item); } } this._sort(items, order); for (i = 0, len = items.length; i < len; i++) { - ids[i] = items[i][this._fieldId]; + ids.push(items[i][this._fieldId]); } } else { // create unordered list - for (id in data) { - if (data.hasOwnProperty(id)) { - item = this._getItem(id, type); - if (filter(item)) { - ids.push(item[this._fieldId]); - } + for (i = 0, len = itemIds.length; i < len; i++) { + id = itemIds[i]; + item = this._getItem(id, type); + if (filter(item)) { + ids.push(item[this._fieldId]); } } } @@ -466,25 +467,23 @@ DataSet.prototype.getIds = function (options) { if (order) { // create an ordered list items = []; - for (id in data) { - if (data.hasOwnProperty(id)) { - items.push(data[id]); - } + for (i = 0, len = itemIds.length; i < len; i++) { + id = itemIds[i]; + items.push(data[id]); } this._sort(items, order); for (i = 0, len = items.length; i < len; i++) { - ids[i] = items[i][this._fieldId]; + ids.push(items[i][this._fieldId]); } } else { // create unordered list - for (id in data) { - if (data.hasOwnProperty(id)) { - item = data[id]; - ids.push(item[this._fieldId]); - } + for (i = 0, len = itemIds.length; i < len; i++) { + id = itemIds[i]; + item = data[id]; + ids.push(item[this._fieldId]); } } } @@ -514,6 +513,9 @@ DataSet.prototype.forEach = function (callback, options) { var filter = options && options.filter, type = options && options.type || this._options.type, data = this._data, + itemIds = Object.key(data), + i, + len, item, id; @@ -521,7 +523,7 @@ DataSet.prototype.forEach = function (callback, options) { // execute forEach on ordered list var items = this.get(options); - for (var i = 0, len = items.length; i < len; i++) { + for (i = 0, len = items.length; i < len; i++) { item = items[i]; id = item[this._fieldId]; callback(item, id); @@ -529,12 +531,11 @@ DataSet.prototype.forEach = function (callback, options) { } else { // unordered - for (id in data) { - if (data.hasOwnProperty(id)) { - item = this._getItem(id, type); - if (!filter || filter(item)) { - callback(item, id); - } + for (i = 0, len = itemIds.length; i < len; i++) { + id = itemIds[i]; + item = this._getItem(id, type); + if (!filter || filter(item)) { + callback(item, id); } } } @@ -556,15 +557,18 @@ DataSet.prototype.map = function (callback, options) { type = options && options.type || this._options.type, mappedItems = [], data = this._data, + itemIds = Object.keys(data), + i, + len, + id, item; // convert and filter items - for (var id in data) { - if (data.hasOwnProperty(id)) { - item = this._getItem(id, type); - if (!filter || filter(item)) { - mappedItems.push(callback(item, id)); - } + for (i = 0, len = itemIds.length; i < len; i++) { + id = itemIds[i]; + item = this._getItem(id, type); + if (!filter || filter(item)) { + mappedItems.push(callback(item, id)); } } @@ -588,17 +592,23 @@ DataSet.prototype._filterFields = function (item, fields) { return item; } - var filteredItem = {}; + var filteredItem = {}, + itemFields = Object.keys(item), + len = itemFields.length, + i, + field; if(Array.isArray(fields)){ - for (var field in item) { - if (item.hasOwnProperty(field) && (fields.indexOf(field) != -1)) { + for (i = 0; i < len; i++) { + field = itemFields[i]; + if (fields.indexOf(field) != -1) { filteredItem[field] = item[field]; } } }else{ - for (var field in item) { - if (item.hasOwnProperty(field) && fields.hasOwnProperty(field)) { + for (i = 0; i < len; i++) { + field = itemFields[i]; + if (fields.hasOwnProperty(field)) { filteredItem[fields[field]] = item[field]; } } @@ -715,17 +725,19 @@ DataSet.prototype.clear = function (senderId) { */ DataSet.prototype.max = function (field) { var data = this._data, + itemIds = Object.keys(data), max = null, - maxField = null; - - for (var id in data) { - if (data.hasOwnProperty(id)) { - var item = data[id]; - var itemField = item[field]; - if (itemField != null && (!max || itemField > maxField)) { - max = item; - maxField = itemField; - } + maxField = null, + i, + len; + + for (i = 0, len = itemIds.length; i < len; i++) { + var id = itemIds[i]; + var item = data[id]; + var itemField = item[field]; + if (itemField != null && (!max || itemField > maxField)) { + max = item; + maxField = itemField; } } @@ -739,17 +751,19 @@ DataSet.prototype.max = function (field) { */ DataSet.prototype.min = function (field) { var data = this._data, + itemIds = Object.keys(data), min = null, - minField = null; - - for (var id in data) { - if (data.hasOwnProperty(id)) { - var item = data[id]; - var itemField = item[field]; - if (itemField != null && (!min || itemField < minField)) { - min = item; - minField = itemField; - } + minField = null, + i, + len; + + for (i = 0, len = itemIds.length; i < len; i++) { + var id = itemIds[i]; + var item = data[id]; + var itemField = item[field]; + if (itemField != null && (!min || itemField < minField)) { + min = item; + minField = itemField; } } @@ -765,31 +779,33 @@ DataSet.prototype.min = function (field) { */ DataSet.prototype.distinct = function (field) { var data = this._data; + var itemIds = Object.keys(data); var values = []; var fieldType = this._options.type && this._options.type[field] || null; var count = 0; - var i; - - for (var prop in data) { - if (data.hasOwnProperty(prop)) { - var item = data[prop]; - var value = item[field]; - var exists = false; - for (i = 0; i < count; i++) { - if (values[i] == value) { - exists = true; - break; - } - } - if (!exists && (value !== undefined)) { - values[count] = value; - count++; + var i, + j, + len; + + for (i = 0, len = itemIds.length; i < len; i++) { + var id = itemIds[i]; + var item = data[id]; + var value = item[field]; + var exists = false; + for (j = 0; j < count; j++) { + if (values[j] == value) { + exists = true; + break; } } + if (!exists && (value !== undefined)) { + values[count] = value; + count++; + } } if (fieldType) { - for (i = 0; i < values.length; i++) { + for (i = 0, len = values.length; i < len; i++) { values[i] = util.convert(values[i], fieldType); } } @@ -819,12 +835,14 @@ DataSet.prototype._addItem = function (item) { item[this._fieldId] = id; } - var d = {}; - for (var field in item) { - if (item.hasOwnProperty(field)) { - var fieldType = this._type[field]; // type may be undefined - d[field] = util.convert(item[field], fieldType); - } + var d = {}, + fields = Object.keys(item), + i, + len; + for (i = 0, len = fields.length; i < len; i++) { + var field = fields[i]; + var fieldType = this._type[field]; // type may be undefined + d[field] = util.convert(item[field], fieldType); } this._data[id] = d; this.length++; @@ -840,7 +858,7 @@ DataSet.prototype._addItem = function (item) { * @private */ DataSet.prototype._getItem = function (id, types) { - var field, value; + var field, value, i, len; // get the item from the dataset var raw = this._data[id]; @@ -849,22 +867,22 @@ DataSet.prototype._getItem = function (id, types) { } // convert the items field types - var converted = {}; + var converted = {}, + fields = Object.keys(raw); + if (types) { - for (field in raw) { - if (raw.hasOwnProperty(field)) { - value = raw[field]; - converted[field] = util.convert(value, types[field]); - } + for (i = 0, len = fields.length; i < len; i++) { + field = fields[i]; + value = raw[field]; + converted[field] = util.convert(value, types[field]); } } else { // no field types specified, no converting needed - for (field in raw) { - if (raw.hasOwnProperty(field)) { - value = raw[field]; - converted[field] = value; - } + for (i = 0, len = fields.length; i < len; i++) { + field = fields[i]; + value = raw[field]; + converted[field] = value; } } return converted; @@ -890,11 +908,11 @@ DataSet.prototype._updateItem = function (item) { } // merge with current item - for (var field in item) { - if (item.hasOwnProperty(field)) { - var fieldType = this._type[field]; // type may be undefined - d[field] = util.convert(item[field], fieldType); - } + var fields = Object.keys(item); + for (var i = 0, len = fields.length; i < len; i++) { + var field = fields[i]; + var fieldType = this._type[field]; // type may be undefined + d[field] = util.convert(item[field], fieldType); } return id; diff --git a/lib/DataView.js b/lib/DataView.js index 39da84ab..7d5b2316 100644 --- a/lib/DataView.js +++ b/lib/DataView.js @@ -35,7 +35,7 @@ function DataView (data, options) { * @param {DataSet | DataView} data */ DataView.prototype.setData = function (data) { - var ids, i, len; + var ids, id, i, len; if (this._data) { // unsubscribe from current dataset @@ -44,12 +44,7 @@ DataView.prototype.setData = function (data) { } // trigger a remove of all items in memory - ids = []; - for (var id in this._ids) { - if (this._ids.hasOwnProperty(id)) { - ids.push(id); - } - } + ids = Object.keys(this._ids); this._ids = {}; this.length = 0; this._trigger('remove', {items: ids}); @@ -84,34 +79,34 @@ DataView.prototype.setData = function (data) { * containing a variable parameter. */ DataView.prototype.refresh = function () { - var id; + var id, i, len; var ids = this._data.getIds({filter: this._options && this._options.filter}); + var oldIds = Object.keys(this._ids); var newIds = {}; var added = []; var removed = []; // check for additions - for (var i = 0; i < ids.length; i++) { + for (i = 0, len = ids.length; i < len; i++) { id = ids[i]; newIds[id] = true; if (!this._ids[id]) { added.push(id); this._ids[id] = true; - this.length++; } } // check for removals - for (id in this._ids) { - if (this._ids.hasOwnProperty(id)) { - if (!newIds[id]) { - removed.push(id); - delete this._ids[id]; - this.length--; - } + for (i = 0, len = oldIds.length; i < len; i++) { + id = oldIds[i]; + if (!newIds[id]) { + removed.push(id); + delete this._ids[id]; } } + this.length += added.length - removed.length; + // trigger events if (added.length) { this._trigger('add', {items: added});