We have been using javascript "hashes" a lot lately, and we've been looking for a universal way to count the items contained in both arrays and hashes without having to "know" which we're dealing with except in the count method. As everyone knows .length is useless since it only returns the value of the highest index in the array. What we have below does not work because hashes test true for Array, but the length value returned is crap for hashes. We originally replaced .length all over our project with Object.keys().length, but this isn't supported in IE8 and lower.
This is such a stupid simple thing and we can't seem to get it working. Help me, Obi Wan. You're my only hope!
function isNullOrUndefined(aObject) {
"use strict";
return (typeof aObject === 'undefined' || aObject === null);
}
function count(aList) {
"use strict";
var lKey = null,
lResult = 0;
if (!isNullOrUndefined(aList)) {
if (aList.constructor == Array) {
lResult = aList.length;
} else if (!isNullOrUndefined(Object.keys)) {
lResult = Object.keys(aList).length;
} else {
for (lKey in aList) {
if (aList.hasOwnProperty(lKey)) {
lResult++;
}
}
}
}
return lResult;
}
Despise the answer from Raynos that is completely valid please consider performance
This is how my hash object look like
function Hash(){
this.values = [];
this.keys = {};
}
Hash.prototype.set = function(key, val){
if(this.keys[key]){
this.values[this.keys[key]] = value
}else{
this.keys[key] = (this.values.push(val)-1)
}
}
Hash.prototype.length = function(){
return this.values.length
}
Why I do this is simple performance looping through an object to count the properties length will be really inefficient the solution above give you direct access all the time.
length
operator is faster, but your memory usage increased and your set
operator is significantly slower. You need real benchmarking to figure out where your bottlenecks are. This also hurts readability and introduces unncessary complexity. Object.keys
isn't that slo - Raynos 2012-04-05 19:43
Object.keys
polyfill copied verbatim from the ES5-shim
// ES5 15.2.3.14
// http://es5.github.com/#x15.2.3.14
if (!Object.keys) {
// http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
var hasDontEnumBug = true,
dontEnums = [
"toString",
"toLocaleString",
"valueOf",
"hasOwnProperty",
"isPrototypeOf",
"propertyIsEnumerable",
"constructor"
],
dontEnumsLength = dontEnums.length;
for (var key in {"toString": null}) {
hasDontEnumBug = false;
}
Object.keys = function keys(object) {
if ((typeof object != "object" && typeof object != "function") || object === null) {
throw new TypeError("Object.keys called on a non-object");
}
var keys = [];
for (var name in object) {
if (owns(object, name)) {
keys.push(name);
}
}
if (hasDontEnumBug) {
for (var i = 0, ii = dontEnumsLength; i < ii; i++) {
var dontEnum = dontEnums[i];
if (owns(object, dontEnum)) {
keys.push(dontEnum);
}
}
}
return keys;
};
}
Object.keys
work in IE8 - Alex Turpin 2012-04-05 16:19