JavaScript对字典对象有好处

分享于 

34分钟阅读

Web开发

  繁體 雙語

介绍

在我的最后一个项目中,我要创建一个浏览器客户端应用程序,可以读取 10s 行数据。 目标技术是 HTML 5,CSS 3和 sys 5 (。2013年月 中的现代浏览器)。 由于旧的浏览器兼容性并不重要,外部库只限于 D3 ( 没有 JQuery )。

我需要建立一个数据模型。 我在 C# 之前构建了一个,并依赖自定义字典对象来快速访问数据。组和聚合。 我多年没有使用 JavaScript,所以我开始搜索字典。 我发现JavaScript仍然没有 true 本地字典。 我发现了一些样例实现,但没有真正满足我的期望。 所以我建立了一个。

我已经提到过,多年来我一直没有用 JavaScript。 ( 或者可能只是信息的网络可用性)的进步相当惊人。 我以前的工作都使用基于类的语言,所以基于Prototype的语言花了一些时间来适应( 我还有很长的路要走)。

这个项目在开始之前就是这样的,因为我在基于基于原型的语言中学习了许多新的错误。 创建的字典是功能性的,但经过一段时间后,我实现了一些可以通过 LESS newbish。 这个项目在我没有时间重新编写词典之前没有资金了。 哦,我的位置同时失去了资金,( 神奇的是)。 所以我决定使用我所学到的词典来重新创建字典,并确定字典是否实际上改进了 array。

/** Dictionary Factory Object
* Holds common object functions. similar to V-Table
* this.New() used to create new dictionary objects
* Uses Object.defineProperties so won't work on older browsers.
* Browser Compatibility 
* (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties)
* Firefox (Gecko) 4.0 (2), Chrome 5, IE 9, Opera 11.60, Safari 5
*/function Dict() {
 /* * Create a new Dictionary
 */this.New = function () {
 returnnew dict();
 };
 /* * Return argument f if it is a function otherwise return undefined
 */function ensureF(f) {
 if (isFunct(f)) {
 return f;
 }
 }
 function isFunct(f) {
 return (typeof f == "function");
 }
 /* * Add a"_" as first character just to be sure valid property name
 */function makeKey(k) {
 return"_" + k;
 };
 /* * Key Value Pair object - held in array
 */function newkvp(key, value) {
 return {
 key: key,
 value: value,
 toString: function () { returnthis.key; },
 valueOf: function () { returnthis.key; }
 };
 };
 /* * Return the current set of keys. 
 */function keys(a) {
 // remove the leading"-" character from the keysreturn a.map(function (e) { return e.key.substr(1); });
 // Alternative: Requires Opera 12 vs. 11.60// -- Must pass the internal object instead of the array// -- Still need to remove the leading"-" to return user key values// Object.keys(o).map(function (e) { return e.key.substr(1); }); };
 /* * Return the current set of values. 
 */function values(a) {
 return a.map(function(e) { return e.value; } );
 };
 /* * Return the current set of key value pairs. 
 */function kvPs(a) {
 // remove the leading"-" character from the keysreturn a.map(function (e) { return newkvp(e.key.substr(1), e.value); });
 }
 /* * Returns true if key exists in the dictionary.
 * k - Key to check (with the leading"_" character) 
 */function exists(k, o) {
 return o.hasOwnProperty(k);
 }
 /* * Array Map implementation
 */function map(a, f) {
 if (!isFunct(f)) { return; }
 return a.map(function (e, i) { return f(e.value, i); });
 }
 /* * Array Every implementation
 */function every(a, f) {
 if (!isFunct(f)) { return; }
 return a.every(function (e, i) { return f(e.value, i) });
 }
 /* * Returns subset of"values" where function"f" returns true for the"value"
 */function filter(a, f) {
 if (!isFunct(f)) {return; }
 var ret = a.filter(function (e, i) { return f(e.value, i); });
 // if anything returned by array.filter, then get the"values" from the key value pairsif (ret && ret.length> 0) {
 ret = values(ret);
 }
 return ret;
 }
 /* * Array Reverse implementation
 */function reverse(a, o) {
 a.reverse();
 reindex(a, o, 0);
 }
 /**
 * Randomize array element order in-place.
 * Using Fisher-Yates shuffle algorithm.
 */function shuffle(a, o) {
 var j, t;
 for (var i = a.length - 1; i> 0; i--) {
 j = Math.floor(Math.random() * (i + 1));
 t = a[i];
 a[i] = a[j];
 a[j] = t;
 }
 reindex(a, o, 0);
 return a;
 }
 /* * Array Some implementation
 */function some(a, f) {
 if (!isFunct(f)) { return; }
 return a.some(function (e, i) { return f(e.value, i) });
 }
 /* * Sort the dictionary. Sorts the array and reindexes the object.
 * a - dictionary array
 * o - dictionary object
 * sf - dictionary default sort function (can be undefined)
 * f - sort method sort function argument (can be undefined)
 */function sort(a, o, sf, f) {
 var sf1 = f || sf; // sort function method used if not undefined// if there is a customer sort function, use itif (isFunct(sf1)) {
 a.sort(function (e1, e2) { return sf1(e1.value, e2.value); });
 }
 else {
 // sort by key values a.sort();
 }
 // reindex - adds O(n) to perf reindex(a, o, 0);
 // return sorted values (not entire array)// adds O(n) to perfreturn values(a);
 };
 /* * forEach iteration of"values"
 * uses"for" loop to allow exiting iteration when function returns true 
 */function forEach(a, f) {
 if (!isFunct(f)) { return; }
 // use for loop to allow exiting early and not iterating all itemsfor(var i = 0; i <a.length; i++) {
 if (f(a[i].value, i)) { break; }
 }
 };
 /* * forEachR iteration of"values" in reverse order
 * uses"for" loop to allow exiting iteration when function returns true 
 */function forEachR(a, f) {
 if (!isFunct(f)) { return; }
 // use for loop to allow exiting early and not iterating all itemsfor (var i = a.length - 1; i> -1; i--) {
 if (f(a[i].value, i)) { break; }
 }
 }
 /* * Add a new Key Value Pair, or update the value of an existing key value pair
 */function add(key, value, a, o, resort, sf) {
 var k = makeKey(key);
 // Update value if key existsif (exists(k, o)) {
 a[o[k]].value = value;
 }
 else {
 // Add a new Key value Pairvar kvp = newkvp(k, value);
 o[kvp.key] = a.length;
 a.push(kvp);
 }
 // resort if requestedif (resort) { sort(a, o, sf); }
 };
 /* * Removes an existing key value pair and returns the 
 *"value" If the key does not exists, returns undefined
 */function remove(key, a, o) {
 var k = makeKey(key);
 // return undefined if the key does not existif (!exists(k, o)) { return; }
 // get the array indexvar i = o[k];
 // get the key value pairvar ret = a[i];
 // remove the array element a.splice(i, 1);
 // remove the object propertydelete o[k];
 // reindex the object properties from the remove element to end of the array reindex(a, o, i);
 // return the removed valuereturn ret.value;
 };
 /* * Returns true if key exists in the dictionary.
 * k - Key to check (without the leading"_" character) 
 */function keyExists(k, o) {
 return exists(makeKey(k), o);
 };
 /* * Returns value assocated with"key". Returns undefined if key not found
 */function item(key, a, o) {
 var k = makeKey(key);
 if (exists(k, o)) {
 return a[o[k]].value;
 }
 }
 /* * changes index values held by object properties to match the array index location
 * Called after sorting or removing
 */function reindex(a, o, i){
 for (var j = i; j <a.length; j++) {
 o[a[j].key] = j;
 }
 }
 /* * The"real dictionary"
 */function dict() {
 var _a = [];
 var _o = {};
 var _sortF;
 Object.defineProperties(this, {
 "length": { get: function () { return _a.length; }, enumerable: true },
 "keys": { get: function() { return keys(_a); }, enumerable: true },
 "values": { get: function() { return values(_a); }, enumerable: true },
 "keyValuePairs": { get: function() { return kvPs(_a); }, enumerable: true},
 "sortFunction": { get: function() { return _sortF; }, 
 set: function(funct) { _sortF = ensureF(funct); }, enumerable: true }
 });
 // Array Methods - Only modification to not // pass the actual array to the callback functionthis.map = function(funct) { return map(_a, funct); };
 this.every = function(funct) { return every(_a, funct); };
 this.filter = function(funct) { return filter(_a, funct); };
 this.reverse = function() { reverse(_a, _o); };
 this.shuffle = function () { return shuffle(_a, _o); };
 this.some = function(funct) { return some(_a, funct); };
 this.sort = function(funct) { return sort(_a, _o, _sortF, funct); };
 // Array Methods - Modified aborts when funct returns true.this.forEach = function (funct) { forEach(_a, funct) };
 // forEach in reverse orderthis.forEachRev = function (funct) { forEachR(_a, funct) };
 // Dictionary Methodsthis.addOrUpdate = function(key, value, resort) 
 { return add(key, value, _a, _o, resort, _sortF); };
 this.remove = function(key) { return remove(key, _a, _o); };
 this.exists = function(key) { return keyExists(key, _o); };
 this.item = function(key) { return item(key, _a, _o); };
 this.get = function (index) 
 { if (index> -1 && index <_a.length) { return _a[index].value; } }, 
 this.clear = function() { _a = []; _o = {}; };
 returnthis;
 }
 returnthis;
}

epiphanies的Prototype对象是的一个例子是Prototype基本上是创建的对象的一个v 表,这是一个。 另外,外壳中的功能也可以像表条目。 随着项目的进步,我开始使用对象工厂,它的中顶级对象包含用于创建解决方案的" this.New(args)"方法。 这是我在字典里使用的样式。

字典的核心是 array。对象和 KeyValuePair 对象。 " addOrUpdate"方法获取一个键和一个值,并且:

  • 创建一个 KeyValuePair
  • 使用键作为属性 NAME 和 array 长度作为属性值,将新属性添加到对象
  • 向 array 添加 KeyValuePair,使对象的新属性值成为 array 中的索引

注意:我读取对象属性名可以"几乎任何"unicode字符开头。 项目将处理可以从"任意"unicode字符开始的客户数据。 为了确保字典没有有效的属性 NAME,我将下划线( _ ) 前置到键并在字典外部返回下划线。

要使字典正常运行,必须使内部 array 和对象保持同步。 为了确保这一点,array 和对象都不会在外部公开。 我想避免意外变化,例如," If"测试只有一个等号,左边有错误设置。

例子
If(dict.KeyObj["SomeKey"] = "oops") { alert("good luck tracing this down:-)"); } 

当 Bug ( 症状) 开始计算时可能会很难跟踪字典的典型错误,因此,属性将不能访问任何一个。 这种保护机制是我没有深入挖掘Prototype的原因之一。 当我们使用或者" apply"方法时,我会意识到内部对象,并且在以后不确定内部对象,因为我不确定是否需要暴露这个内部对象,而不是保护核心 array 和对象的目标。

我修正了我创建的第一个字典对象所犯的一些新手错误。

  • " Dict()"函数包含每个字典对象的大部分工作代码。 我用来确定是否应在实际字典对象中使用 vs 功能的标准:
    • 多行代码
    • 被其他封闭函数使用
    • 可能会随着我发现 Bug/问题而引起变化
  • 使用了 Array 方法和属性名称。 来自 C#,我做的事情使我的字典 LESS 可以使用" Count"而不是" length"或者" ForEach"来代替" ForEach"。 通过使用 Array 名称,字典现在可以在大多数情况下用作 Array。 但是,我无法找到创建括号访问器的方法( 比如。 val = dict[key] ),这可能是一个好东西。 当考虑它时,我很难确定 val = dict[12] 这样的事情是否正常工作。 数字 12 可以很容易地被用作一个关键,因这里我不能认识到这种调用的"意向"。
  • 完全封闭下划线前缀处理。 在我工作的项目中,我在各种数据模型对象中进行了扩展和重复。 was了 !

我已经改进了字典,这对性能有帮助? 为了回答这个问题,我创建了几个测试对象。 第一个测试对象使用 string 作为字典值。 为了保持简单,在键和值中都使用了相同的string

function DictPerf() {
 this.testPerf = function (dict, size) {
 var testData = makeTestData(size);
 dict.clear();
 dict.sortFunction = undefined;
 var arr = [];
 var results = [];
 results.push("Perf Testing: Count=" + size);
 results.push(loadTestingDict(dict, testData));
 results.push(loadTestingArr(arr, testData));
 results.push(accessTestingDict(dict, testData));
 results.push(accessTestingArr(arr, testData));
 results.push(mapTestingDict(dict, testData));
 results.push(mapTestingArr(arr, testData));
 results.push(forEachTestingDict(dict, testData));
 results.push(forEachTestingArr(arr, testData));
 results.push(reverseTestingDict(dict, testData));
 results.push(reverseTestingArr(arr, testData));
 results.push(sortTestingDict(dict, testData));
 results.push(sortTestingArr(arr, testData));
 results.push(sortTestingDictRevCmp(dict, testData));
 results.push(sortTestingArrRevCmp(arr, testData));
 results.push(sortTestingDictFwdCmp(dict, testData));
 results.push(sortTestingArrFwdCmp(arr, testData));
 return results;
 }
 function testResult(name, start, end) {
 return {
 Name: name,
 Start: start,
 End: end,
 toString: function () { returnthis.Name + 
 " milliseconds:" + (this.End - this.Start) }
 };
 }
 function loadTestingDict(dict, testData) {
 var name = "Dictionary Load Testing";
 var start = new Date();
 for (var i = 0; i <testData.length; i++) {
 dict.addOrUpdate(testData[i], testData[i]);
 };
 var end = new Date();
 return testResult(name, start, end);
 }
 function loadTestingArr(arr, testData) {
 var name = "Array Load Testing";
 var start = new Date();
 for (var i = 0; i <testData.length; i++) {
 arr.push(testData[i]);
 };
 var end = new Date();
 return testResult(name, start, end);
 }
 function accessTestingDict(dict, testData) {
 var name = "Dictionary Access Testing";
 var start = new Date();
 var val;
 for (var i = 0; i <testData.length; i++) {
 val = dict.item(testData[i]);
 if (val!= testData[i]) {
 thrownew Error("Dict: val!= testData[i]");
 }
 };
 var end = new Date();
 return testResult(name, start, end);
 }
 function accessTestingArr(arr, testData) {
 var name = "Array Access Testing";
 var start = new Date();
 var val;
 for (var i = 0; i <testData.length; i++) {
 val = arr[arr.indexOf(testData[i])];
 if (val!= testData[i]) {
 thrownew Error("Array: val!= testData[i]");
 }
 };
 var end = new Date();
 return testResult(name, start, end);
 }
 function forEachTestingDict(dict, testData) {
 var name = "Dict ForEach Testing";
 var start = new Date();
 var data = []
 dict.forEach(function(e) { data.push(e); });
 var end = new Date();
 return testResult(name, start, end);
 }
 function forEachTestingArr(arr, testData) {
 var name = "Array ForEach Testing";
 var start = new Date();
 var data = []
 arr.forEach(function(e) { data.push(e); });
 var end = new Date();
 return testResult(name, start, end);
 }
 function mapTestingDict(dict, testData) {
 var name = "Dict Map Testing";
 var start = new Date();
 var data = dict.map(function (e) { return e; });
 var end = new Date();
 return testResult(name, start, end);
 }
 function mapTestingArr(arr, testData) {
 var name = "Array Map Testing";
 var start = new Date();
 var data = arr.map(function (e) { return e; });
 var end = new Date();
 return testResult(name, start, end);
 }
 function reverseTestingDict(dict, testData) {
 var name = "Dict Reverse Testing";
 var start = new Date();
 dict.reverse();
 var end = new Date();
 return testResult(name, start, end);
 }
 function reverseTestingArr(arr, testData) {
 var name = "Array Reverse Testing";
 var start = new Date();
 arr.reverse();
 var end = new Date();
 return testResult(name, start, end);
 }
 function sortFwd(v1, v2) {
 if (v1> v2) {
 return1;
 }
 if (v1 <v2) {
 return -1;
 }
 return0;
 }
 function sortRev(v1, v2) {
 return -1 * sortFwd(v1, v2);
 }
 function sortTestingDict(dict, testData) {
 var name = "Dict Sort Testing";
 var start = new Date();
 dict.sort();
 var end = new Date();
 return testResult(name, start, end);
 }
 function sortTestingArr(arr, testData) {
 var name = "Array Sort Testing";
 var start = new Date();
 arr.sort();
 var end = new Date();
 return testResult(name, start, end);
 }
 function sortTestingDictRevCmp(dict, testData) {
 var name = "Dict Sort Reverse Comparer Testing";
 var start = new Date();
 dict.sort(sortRev);
 var end = new Date();
 return testResult(name, start, end);
 }
 function sortTestingArrRevCmp(arr, testData) {
 var name = "Array Sort Reverse Comparer Testing";
 var start = new Date();
 arr.sort(sortRev);
 var end = new Date();
 return testResult(name, start, end);
 }
 function sortTestingDictFwdCmp(dict, testData) {
 var name = "Dict Sort Forward Comparer Testing";
 var start = new Date();
 dict.sort(sortFwd);
 var end = new Date();
 return testResult(name, start, end);
 }
 function sortTestingArrFwdCmp(arr, testData) {
 var name = "Array Sort Forward Comparer Testing";
 var start = new Date();
 arr.sort(sortFwd);
 var end = new Date();
 return testResult(name, start, end);
 }
 function makeKvp(k, v) {
 return { key: k, value: v };
 };
 function makeTestData(size) {
 var arrData = [], val;
 for(var i = 0; i <size; i++) {
 val = "D" + zeroPad(i, 10);
 arrData.push(val);
 }
 shuffleArray(arrData);
 return arrData;
 }
 /**
 * Randomize array element order in-place.
 * Using Fisher-Yates shuffle algorithm.
 */function shuffleArray(array) {
 var j, temp;
 for (var i = array.length - 1; i> 0; i--) {
 j = Math.floor(Math.random() * (i + 1));
 temp = array[i];
 array[i] = array[j];
 array[j] = temp;
 }
 return array;
 }
 function zeroPad(num, size) {
 var n = Math.abs(num);
 var zeros = Math.max(0, size - Math.floor(n).toString().length );
 var zeroString = Math.pow(10, zeros).toString().substr(1);
 if( num <0 ) {
 zeroString = '-' + zeroString;
 }
 return zeroString+n;
 }
 returnthis;
}

运行测试并组装结果后,我决定创建一个第二个性能测试对象,该对象使用对象作为。 对于我工作的项目,数据模型对象是字典值,数组与对象的数组与对象的性能有差异。

function DictPerfObj() {
 this.testPerf = function (dict, size) {
 var testData = makeTestData(size);
 dict.clear();
 dict.sortFunction = undefined;
 var arr = [];
 var results = [];
 results.push("Perf Testing: Count=" + size);
 results.push(loadTestingDict(dict, testData));
 results.push(loadTestingArr(arr, testData));
 results.push(accessTestingDict(dict, testData));
 results.push(accessTestingArr(arr, testData));
 results.push(mapTestingDict(dict, testData));
 results.push(mapTestingArr(arr, testData));
 results.push(forEachTestingDict(dict, testData));
 results.push(forEachTestingArr(arr, testData));
 results.push(reverseTestingDict(dict, testData));
 results.push(reverseTestingArr(arr, testData));
 results.push(sortTestingDict(dict, testData));
 results.push(sortTestingArr(arr, testData));
 results.push(sortTestingDictRevCmp(dict, testData));
 results.push(sortTestingArrRevCmp(arr, testData));
 results.push(sortTestingDictFwdCmp(dict, testData));
 results.push(sortTestingArrFwdCmp(arr, testData));
 return results;
 }
 function testResult(name, start, end) {
 return {
 Name: name,
 Start: start,
 End: end,
 toString: function () { returnthis.Name + 
 " milliseconds:" + (this.End - this.Start) }
 };
 }
 function loadTestingDict(dict, testData) {
 var name = "Dictionary Load Testing";
 var start = new Date();
 for (var i = 0; i < testData.length; i++) {
 dict.addOrUpdate(testData[i].key, testData[i].value);
 };
 var end = new Date();
 return testResult(name, start, end);
 }
 function loadTestingArr(arr, testData) {
 var name = "Array Load Testing";
 var start = new Date();
 for (var i = 0; i < testData.length; i++) {
 arr.push(testData[i]);
 };
 var end = new Date();
 return testResult(name, start, end);
 }
 function accessTestingDict(dict, testData) {
 var name = "Dictionary Access Testing";
 var start = new Date();
 var val;
 for (var i = 0; i < testData.length; i++) {
 val = dict.item(testData[i].key);
 if (val!= testData[i]) {
 thrownew Error("Dict: val!= testData[i]");
 }
 };
 var end = new Date();
 return testResult(name, start, end);
 }
 function accessTestingArr(arr, testData) {
 var name = "Array Access Testing";
 var start = new Date();
 var val;
 for (var i = 0; i < testData.length; i++) {
 val = arr[arr.indexOf(testData[i])];
 if (val.value!= testData[i].value) {
 thrownew Error("Array: val!= testData[i]");
 }
 };
 var end = new Date();
 return testResult(name, start, end);
 }
 function forEachTestingDict(dict, testData) {
 var name = "Dict ForEach Testing";
 var start = new Date();
 var data = []
 dict.forEach(function(e) { data.push(e); });
 var end = new Date();
 return testResult(name, start, end);
 }
 function forEachTestingArr(arr, testData) {
 var name = "Array ForEach Testing";
 var start = new Date();
 var data = []
 arr.forEach(function(e) { data.push(e.value); });
 var end = new Date();
 return testResult(name, start, end);
 }
 function mapTestingDict(dict, testData) {
 var name = "Dict Map Testing";
 var start = new Date();
 var data = dict.map(function (e) { return e; });
 var end = new Date();
 return testResult(name, start, end);
 }
 function mapTestingArr(arr, testData) {
 var name = "Array Map Testing";
 var start = new Date();
 var data = arr.map(function (e) { return e.value; });
 var end = new Date();
 return testResult(name, start, end);
 }
 function reverseTestingDict(dict, testData) {
 var name = "Dict Reverse Testing";
 var start = new Date();
 dict.reverse();
 var end = new Date();
 return testResult(name, start, end);
 }
 function reverseTestingArr(arr, testData) {
 var name = "Array Reverse Testing";
 var start = new Date();
 arr.reverse();
 var end = new Date();
 return testResult(name, start, end);
 }
 function sortFwd(v1, v2) {
 if (v1 > v2) {
 return1;
 }
 if (v1 < v2) {
 return -1;
 }
 return0;
 }
 function sortFwdArr(v1, v2) {
 if (v1.value> v2.value) {
 return1;
 }
 if (v1.value< v2.value) {
 return -1;
 }
 return0;
 }
 function sortRevArr(v1, v2) {
 return -1 * sortFwdArr(v1, v2);
 }
 function sortRev(v1, v2) {
 return -1 * sortFwd(v1, v2);
 }
 function sortTestingDict(dict, testData) {
 var name = "Dict Sort Testing";
 var start = new Date();
 dict.sort();
 var end = new Date();
 return testResult(name, start, end);
 }
 function sortTestingArr(arr, testData) {
 var name = "Array Sort Testing";
 var start = new Date();
 arr.sort();
 var end = new Date();
 return testResult(name, start, end);
 }
 function sortTestingDictRevCmp(dict, testData) {
 var name = "Dict Sort Reverse Comparer Testing";
 var start = new Date();
 dict.sort(sortRev);
 var end = new Date();
 return testResult(name, start, end);
 }
 function sortTestingArrRevCmp(arr, testData) {
 var name = "Array Sort Reverse Comparer Testing";
 var start = new Date();
 arr.sort(sortRevArr);
 var end = new Date();
 return testResult(name, start, end);
 }
 function sortTestingDictFwdCmp(dict, testData) {
 var name = "Dict Sort Forward Comparer Testing";
 var start = new Date();
 dict.sort(sortFwd);
 var end = new Date();
 return testResult(name, start, end);
 }
 function sortTestingArrFwdCmp(arr, testData) {
 var name = "Array Sort Forward Comparer Testing";
 var start = new Date();
 arr.sort(sortFwdArr);
 var end = new Date();
 return testResult(name, start, end);
 }
 /* * Key Value Pair object - held in array
 */ function newkvp(key, value) {
 return {
 key: key,
 value: value,
 toString: function () { returnthis.key; },
 valueOf: function () { returnthis.key; }
 };
 };
 function makeTestData(size) {
 var arrData = [], val;
 for(var i = 0; i < size; i++) {
 val = "D" + zeroPad(i, 10);
 arrData.push(newkvp(val, val));
 }
 shuffleArray(arrData);
 return arrData;
 }
 /**
 * Randomize array element order in-place.
 * Using Fisher-Yates shuffle algorithm.
 */ function shuffleArray(array) {
 var j, temp;
 for (var i = array.length - 1; i >0; i--) {
 j = Math.floor(Math.random() * (i + 1));
 temp = array[i];
 array[i] = array[j];
 array[j] = temp;
 }
 return array;
 }
 function zeroPad(num, size) {
 var n = Math.abs(num);
 var zeros = Math.max(0, size - Math.floor(n).toString().length );
 var zeroString = Math.pow(10, zeros).toString().substr(1);
 if( num <0 ) {
 zeroString = '-' + zeroString;
 }
 return zeroString+n;
 }
 returnthis;
}

我使用 100.1000和 10,000元素运行了两组性能测试代码。 我在 Firefox。Chrome 和 IE 中运行了测试。

  • 100元素:对于所有密集目的,请考虑 0和 2之间的每个值。 我在每个浏览器中多次运行测试,0是最常见的,1,有时是 2显示。 我只是将最后一次测试中的值放入表 below 中。
  • 1000和 10,000元素:对于这些,我运行了测试 10时间,平均结果是。 我认为我不需要真正地运行更多的东西来了解性能的一般概念。
  • 对于 array 访问测试,我使用 array[array.indexOf("key"))。 这将是我找到一个" key"而不是一个索引的方法。
字符串值
 Firefox Chrome IE
Process Elements Dict Array Dict Array Dict Array
Loading 100 1 0 0 0 0 0
Access 100 1 2 0 0 0 1
Map Function 100 0 0 0 0 0 0
ForEach Function 100 0 0 0 0 0 0
Reverse Function 100 0 0 0 0 0 0
Sort 100 0 0 0 0 0 0
Sort Reverse Compare 100 0 0 0 0 0 0
Sort Forward Compare 100 0 0 0 0 0 0
Loading 1000 6.1 0.4 1.5 0 5.5 0.1
Access 1000 2.7 74.2 1.6 26.7 2 41.7
Map Function 1000 0 0.3 0 0 0 0
ForEach Function 1000 0.3 0 0 1.6 0 0.1
Reverse Function 1000 0.8 0.1 0 0 0.9 0
Sort 1000 1.8 0.8 1.5 0 1.2 0.9
Sort Reverse Compare 1000 2.3 1 0 3.1 2.1 1.9
Sort Forward Compare 1000 1.2 0.9 1.6 3.1 1.8 1.5
Loading 10000 25.5 0.9 29.8 0 25.7 0.3
Access 10000 12.8 8313.6 10.9 2436.8 12.8 4985.4
Map Function 10000 1.3 1.1 3.1 0 0.5 0.4
ForEach Function 10000 0.9 0.9 1.6 1.6 0.3 0.5
Reverse Function 10000 6.6 0.2 6.2 1.5 4.4 0
Sort 10000 23.7 16.9 48 21.8 24.8 11.1
Sort Reverse Compare 10000 33.6 16.9 33 13.7 33.2 18.5
Sort Forward Compare 10000 29.6 12.8 22 9.3 33.1 18
对象值
 Firefox Chrome IE
Process Elements Dict Array Dict Array Dict Array
Loading 100 1 0 0 0 0 0
Access 100 1 2 0 0 0 1
Map Function 100 0 0 0 0 0 0
ForEach Function 100 0 0 0 0 0 0
Reverse Function 100 0 0 0 0 0 0
Sort 100 0 0 0 0 0 0
Sort Reverse Compare 100 0 0 0 0 0 0
Sort Forward Compare 100 0 0 0 0 0 0
Loading 1000 7.4 0.4 9.2 0 5.2 0.1
Access 1000 4.9 54.3 0 6.3 3.7 28.9
Map Function 1000 0.5 0.1 0 0 0.3 0.4
ForEach Function 1000 0.1 0.4 0 0 0 0
Reverse Function 1000 0.4 0.1 3.1 0 0.4 0
Sort 1000 1.8 1.2 6.3 3.2 1.6 1
Sort Reverse Compare 1000 2.2 1.2 4.6 0 2.9 2.2
Sort Forward Compare 1000 1.6 0.8 1.6 3 2.7 1.7
Loading 10000 26.7 1 29.7 0 25.5 0.3
Access 10000 20.4 4870.8 15.7 563.1 18.8 3243.4
Map Function 10000 1.5 1.4 0 6.1 2.8 1.3
ForEach Function 10000 0.6 1.4 0 7.9 0.7 1.5
Reverse Function 10000 6.5 0.5 3.2 0 4.7 0
Sort 10000 23.6 15.4 48.4 43.7 39 15
Sort Reverse Compare 10000 33.9 19.5 25 15.5 33.6 20
Sort Forward Compare 10000 29.8 14.6 23.4 17.2 32.5 18.8

不出所料,字典负载比 array 加载要长得多,而且字典访问比 array 访问要快得多,。 我不期望的一件事是浏览器与 array 访问时序之间的巨大差异。 Chrome 明显更快,其次是 IE,然后是 Firefox。 让我惊讶的是,在这三种浏览器中,array 访问对象的速度比 array 访问字符串要快得多。 我其实期望相反的是 true。

要回答最初的问题: 当我需要快速访问大量数据点时,JavaScript会从字典对象中获益 definitely i 我必须说是 yes。 然而,与大多数工具一样,它将被使用在不应该使用的地方,从而导致性能更慢。 迭代短数组通常比字典查找快,并且消除了字典和 KeyValuePair 创建的开销。 请记住,我的字典和测试代码都是解释的JavaScript。 如果JavaScript本身有一个字典对象,它会运行在编译代码中,可以能消除了 array 类似的性能。

我在这里没有实现的一件事是 JSON。


JAVA  Javascript  对象  dict  词典  
相关文章