I have a JavaScript object. Is there a built-in or accepted best practice way to get the length of this object?
const myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
Updated answer
Here's an update as of 2016 and widespread deployment of ES5 and beyond. For IE9+ and all other modern ES5+ capable browsers, you can use Object.keys() so the above code just becomes:
var size = Object.keys(myObj).length;
This doesn't have to modify any existing prototype since Object.keys() is now built-in.
Edit: Objects can have symbolic properties that can not be returned via Object.key method. So the answer would be incomplete without mentioning them.
Symbol type was added to the language to create unique identifiers for object properties. The main benefit of the Symbol type is the prevention of overwrites.
Object.keys or Object.getOwnPropertyNames does not work for symbolic properties. To return them you need to use Object.getOwnPropertySymbols.
var person = {
[Symbol('name')]: 'John Doe',
[Symbol('age')]: 33,
"occupation": "Programmer"
};
const propOwn = Object.getOwnPropertyNames(person);
console.log(propOwn.length); // 1
let propSymb = Object.getOwnPropertySymbols(person);
console.log(propSymb.length); // 2
Older answer
The most robust answer (i.e. that captures the intent of what you're trying to do while causing the fewest bugs) would be:
Object.size = function(obj) {
var size = 0,
key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
};
// Get the size of an object
const myObj = {}
var size = Object.size(myObj);
There's a sort of convention in JavaScript that you don't add things to Object.prototype, because it can break enumerations in various libraries. Adding methods to Object is usually safe, though.
If you know you don't have to worry about hasOwnProperty checks, you can use the Object.keys() method in this way:
Object.keys(myArray).length
Updated: If you're using Underscore.js (recommended, it's lightweight!), then you can just do
_.size({one : 1, two : 2, three : 3});
=> 3
If not, and you don't want to mess around with Object properties for whatever reason, and are already using jQuery, a plugin is equally accessible:
$.assocArraySize = function(obj) {
// http://stackoverflow.com/a/6700/11236
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
};
Here's the most cross-browser solution.
This is better than the accepted answer because it uses native Object.keys if exists.
Thus, it is the fastest for all modern browsers.
if (!Object.keys) {
Object.keys = function (obj) {
var arr = [],
key;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
arr.push(key);
}
}
return arr;
};
}
Object.keys(obj).length;
Simply use this to get the length:
Object.keys(myObject).length
I'm not a JavaScript expert, but it looks like you would have to loop through the elements and count them since Object doesn't have a length method:
var element_count = 0;
for (e in myArray) { if (myArray.hasOwnProperty(e)) element_count++; }
#palmsey: In fairness to the OP, the JavaScript documentation actually explicitly refer to using variables of type Object in this manner as "associative arrays".
This method gets all your object's property names in an array, so you can get the length of that array which is equal to your object's keys' length.
Object.getOwnPropertyNames({"hi":"Hi","msg":"Message"}).length; // => 2
To not mess with the prototype or other code, you could build and extend your own object:
function Hash(){
var length=0;
this.add = function(key, val){
if(this[key] == undefined)
{
length++;
}
this[key]=val;
};
this.length = function(){
return length;
};
}
myArray = new Hash();
myArray.add("lastname", "Simpson");
myArray.add("age", 21);
alert(myArray.length()); // will alert 2
If you always use the add method, the length property will be correct. If you're worried that you or others forget about using it, you could add the property counter which the others have posted to the length method, too.
Of course, you could always overwrite the methods. But even if you do, your code would probably fail noticeably, making it easy to debug. ;)
We can find the length of Object by using:
const myObject = {};
console.log(Object.values(myObject).length);
Here's how and don't forget to check that the property is not on the prototype chain:
var element_count = 0;
for(var e in myArray)
if(myArray.hasOwnProperty(e))
element_count++;
Here is a completely different solution that will only work in more modern browsers (Internet Explorer 9+, Chrome, Firefox 4+, Opera 11.60+, and Safari 5.1+)
See this jsFiddle.
Setup your associative array class
/**
* #constructor
*/
AssociativeArray = function () {};
// Make the length property work
Object.defineProperty(AssociativeArray.prototype, "length", {
get: function () {
var count = 0;
for (var key in this) {
if (this.hasOwnProperty(key))
count++;
}
return count;
}
});
Now you can use this code as follows...
var a1 = new AssociativeArray();
a1["prop1"] = "test";
a1["prop2"] = 1234;
a1["prop3"] = "something else";
alert("Length of array is " + a1.length);
If you need an associative data structure that exposes its size, better use a map instead of an object.
const myMap = new Map();
myMap.set("firstname", "Gareth");
myMap.set("lastname", "Simpson");
myMap.set("age", 21);
console.log(myMap.size); // 3
Use Object.keys(myObject).length to get the length of object/array
var myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
console.log(Object.keys(myObject).length); //3
Use:
var myArray = new Object();
myArray["firstname"] = "Gareth";
myArray["lastname"] = "Simpson";
myArray["age"] = 21;
obj = Object.keys(myArray).length;
console.log(obj)
<script>
myObj = {"key1" : "Hello", "key2" : "Goodbye"};
var size = Object.keys(myObj).length;
console.log(size);
</script>
<p id="myObj">The number of <b>keys</b> in <b>myObj</b> are: <script>document.write(size)</script></p>
This works for me:
var size = Object.keys(myObj).length;
For some cases it is better to just store the size in a separate variable. Especially, if you're adding to the array by one element in one place and can easily increment the size. It would obviously work much faster if you need to check the size often.
The simplest way is like this:
Object.keys(myobject).length
Where myobject is the object of what you want the length of.
#palmsey: In fairness to the OP, the JavaScript documentation actually explicitly refer to using variables of type Object in this manner as "associative arrays".
And in fairness to #palmsey he was quite correct. They aren't associative arrays; they're definitely objects :) - doing the job of an associative array. But as regards to the wider point, you definitely seem to have the right of it according to this rather fine article I found:
JavaScript “Associative Arrays” Considered Harmful
But according to all this, the accepted answer itself is bad practice?
Specify a prototype size() function for Object
If anything else has been added to Object .prototype, then the suggested code will fail:
<script type="text/javascript">
Object.prototype.size = function () {
var len = this.length ? --this.length : -1;
for (var k in this)
len++;
return len;
}
Object.prototype.size2 = function () {
var len = this.length ? --this.length : -1;
for (var k in this)
len++;
return len;
}
var myArray = new Object();
myArray["firstname"] = "Gareth";
myArray["lastname"] = "Simpson";
myArray["age"] = 21;
alert("age is " + myArray["age"]);
alert("length is " + myArray.size());
</script>
I don't think that answer should be the accepted one as it can't be trusted to work if you have any other code running in the same execution context. To do it in a robust fashion, surely you would need to define the size method within myArray and check for the type of the members as you iterate through them.
If we have the hash
hash = {"a" : "b", "c": "d"};
we can get the length using the length of the keys which is the length of the hash:
keys(hash).length
Using the Object.entries method to get length is one way of achieving it
const objectLength = obj => Object.entries(obj).length;
const person = {
id: 1,
name: 'John',
age: 30
}
const car = {
type: 2,
color: 'red',
}
console.log(objectLength(person)); // 3
console.log(objectLength(car)); // 2
var myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
Object.values(myObject).length
Object.entries(myObject).length
Object.keys(myObject).length
What about something like this --
function keyValuePairs() {
this.length = 0;
function add(key, value) { this[key] = value; this.length++; }
function remove(key) { if (this.hasOwnProperty(key)) { delete this[key]; this.length--; }}
}
If you are using AngularJS 1.x you can do things the AngularJS way by creating a filter and using the code from any of the other examples such as the following:
// Count the elements in an object
app.filter('lengthOfObject', function() {
return function( obj ) {
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
}
})
Usage
In your controller:
$scope.filterResult = $filter('lengthOfObject')($scope.object)
Or in your view:
<any ng-expression="object | lengthOfObject"></any>
const myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
console.log(Object.keys(myObject).length)
// o/p 3
A variation on some of the above is:
var objLength = function(obj){
var key,len=0;
for(key in obj){
len += Number( obj.hasOwnProperty(key) );
}
return len;
};
It is a bit more elegant way to integrate hasOwnProp.
If you don't care about supporting Internet Explorer 8 or lower, you can easily get the number of properties in an object by applying the following two steps:
Run either Object.keys() to get an array that contains the names of only those properties that are enumerable or Object.getOwnPropertyNames() if you want to also include the names of properties that are not enumerable.
Get the .length property of that array.
If you need to do this more than once, you could wrap this logic in a function:
function size(obj, enumerablesOnly) {
return enumerablesOnly === false ?
Object.getOwnPropertyNames(obj).length :
Object.keys(obj).length;
}
How to use this particular function:
var myObj = Object.create({}, {
getFoo: {},
setFoo: {}
});
myObj.Foo = 12;
var myArr = [1,2,5,4,8,15];
console.log(size(myObj)); // Output : 1
console.log(size(myObj, true)); // Output : 1
console.log(size(myObj, false)); // Output : 3
console.log(size(myArr)); // Output : 6
console.log(size(myArr, true)); // Output : 6
console.log(size(myArr, false)); // Output : 7
See also this Fiddle for a demo.
Here's a different version of James Cogan's answer. Instead of passing an argument, just prototype out the Object class and make the code cleaner.
Object.prototype.size = function () {
var size = 0,
key;
for (key in this) {
if (this.hasOwnProperty(key)) size++;
}
return size;
};
var x = {
one: 1,
two: 2,
three: 3
};
x.size() === 3;
jsfiddle example: http://jsfiddle.net/qar4j/1/
You can always do Object.getOwnPropertyNames(myObject).length to get the same result as [].length would give for normal array.
You can simply use Object.keys(obj).length on any object to get its length. Object.keys returns an array containing all of the object keys (properties) which can come in handy for finding the length of that object using the length of the corresponding array. You can even write a function for this. Let's get creative and write a method for it as well (along with a more convienient getter property):
function objLength(obj)
{
return Object.keys(obj).length;
}
console.log(objLength({a:1, b:"summit", c:"nonsense"}));
// Works perfectly fine
var obj = new Object();
obj['fish'] = 30;
obj['nullified content'] = null;
console.log(objLength(obj));
// It also works your way, which is creating it using the Object constructor
Object.prototype.getLength = function() {
return Object.keys(this).length;
}
console.log(obj.getLength());
// You can also write it as a method, which is more efficient as done so above
Object.defineProperty(Object.prototype, "length", {get:function(){
return Object.keys(this).length;
}});
console.log(obj.length);
// probably the most effictive approach is done so and demonstrated above which sets a getter property called "length" for objects which returns the equivalent value of getLength(this) or this.getLength()
A nice way to achieve this (Internet Explorer 9+ only) is to define a magic getter on the length property:
Object.defineProperty(Object.prototype, "length", {
get: function () {
return Object.keys(this).length;
}
});
And you can just use it like so:
var myObj = { 'key': 'value' };
myObj.length;
It would give 1.
I have an object in javaScript:
var stuffObject = {
stuffArray1 : [object1, object2, object3],
stuffArray2 : [object4, object5, object6]
}
object1 to 6 look like this:
object1 = {
dataStuff : {
stuffId: "foobar"
}
}
My question: given the key "foobar", how do I retrieve object1 from the stuffObject using jQuery? The key "stuffId" always has a unique value.
You won't get around iterating over the set to find the object you are looking for. jQuery can't really help with that. Its purpose is DOM manipulation. If you want functionality to deal with objects, sets, lists, etc., check out lodash.
I wrote a function to deal with the problem. I hope it's understandable.
var stuffObject = {
stuffArray1 : [{dataStuff: {stuffId: 'foobar'}}, {dataStuff: {stuffId: 'foo'}}, {}],
stuffArray2 : [{}, {dataStuff: {stuffId: 'bar'}}, {}]
}
function getObjByStuffId(stuffObject, stuffId) {
var key, arr, i, obj;
// Iterate over all the arrays in the object
for(key in stuffObject) {
if(stuffObject.hasOwnProperty(key)) {
arr = stuffObject[key];
// Iterate over all the values in the array
for(i = 0; i < arr.length; i++) {
obj = arr[i];
// And if it has the value we are looking for
if(typeof obj.dataStuff === 'object'
&& obj.dataStuff.stuffId === stuffId) {
// Stop searching and return the object.
return obj;
}
}
}
}
}
console.log('foobar?', getObjByStuffId(stuffObject, 'foobar') );
console.log('foo?', getObjByStuffId(stuffObject, 'foo') );
console.log('bar?', getObjByStuffId(stuffObject, 'bar') );
Thanks for the help guys, using the input of other people I have solved it myself:
getStuffById: function(id){
for (stuffArray in stuffObject) {
for (stuff in stuffObject[stuffArray]) {
if (stuffObject[stuffArray][stuff].dataStuff.stuffId == id) {
return stuffObject[stuffArray][stuff];
}
}
}
return null;
}
This also works better than the (now deleted) answer that uses .grep(), as this function terminates as soon as it finds the correct object.
Question:
As soon as I add the below code to my html page, I get:
Line: 4
Error: Object doesn't support the property or method "exec".
This is the prototype that causes the bug:
Object.prototype.allKeys = function () {
var keys = [];
for (var key in this)
{
// Very important to check for dictionary.hasOwnProperty(key)
// otherwise you may end up with methods from the prototype chain..
if (this.hasOwnProperty(key))
{
keys.push(key);
//alert(key);
} // End if (dict.hasOwnProperty(key))
} // Next key
keys.sort();
return keys;
}; // End Extension Function allKeys
And this is the minimum code required to reproduce the error (Browser in question: IE9):
<!DOCTYPE html>
<html>
<head>
<title>TestPage</title>
<script type="text/javascript" src="jquery-1.9.1.min.js"></script>
<script type="text/javascript">
/*
Object.prototype.getName111 = function () {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec((this).constructor.toString());
return (results && results.length > 1) ? results[1] : "";
}; // End Function getName
*/
Object.prototype.allKeys = function () {
var keys = [];
for (var key in this)
{
// Very important to check for dictionary.hasOwnProperty(key)
// otherwise you may end up with methods from the prototype chain..
if (this.hasOwnProperty(key))
{
keys.push(key);
//alert(key);
} // End if (dict.hasOwnProperty(key))
} // Next key
keys.sort();
return keys;
}; // End Extension Function allKeys
</script>
</head>
<body>
<select id="selLayers" name="myddl">
<option value="1">One</option>
<option value="2">Twooo</option>
<option value="3">Three</option>
<option value="4">Text1</option>
<option value="5">Text2</option>
</select>
<script type="text/javascript">
//var dict = { "de": { "Text1": "Ersetzung 1", "Text2": "Ersetzung 2" }, "fr": { "Text1": "Replacement 1", "Text2": "Réplacement 2" }, "it": { "Text1": "Replacemente 1", "Text2": "Replacemente 2" }, "en": { "Text1": "Replacement 1", "Text2": "Replacement 2"} };
/*
var languages = dict.allKeys();
for (var j = 0; j < languages.length; ++j)
{
var strCurrentLanguage = languages[j];
var dictReplacements = dict[strCurrentLanguage]
var keys = dictReplacements.allKeys();
//alert(JSON.stringify(dictReplacements));
//alert(JSON.stringify(keys));
for (var i = 0; i < keys.length; ++i) {
var strKey = keys[i];
var strReplacement = dictReplacements[strKey];
alert(strKey + " ==> " + strReplacement);
//alert('#selLayers option:contains("' + strKey + '")');
//$('#selLayers option:contains("' + strKey + '")').html(strReplacement);
//$('#selLayers option:contains("Text1")').html("foobar");
}
}
*/
$('#selLayers option:contains("Twooo")').text('Fish');
//alert(dict.allKeys());
//alert(dict["de"]["abc"]);
/*
$('#selLayers option[value=2]').text('Fish');
$('#selLayers option:contains("Twooo")').text('Fish');
$('#selLayers option:contains("Twooo")').html('Étage');
// http://stackoverflow.com/questions/7344220/jquery-selector-contains-to-equals
$("#list option[value=2]").text();
$("#list option:selected").each(function () {
alert($(this).text());
});
$("#list").change(function() {
alert($(this).find("option:selected").text()+' clicked!');
});
*/
</script>
</body>
</html>
I tried renaming the prototype function, just in case it conflicts with any jquery prototype, but that doesn't help at all.
Because this is going to add an enumerable item to every single object. Sizzle (which jQuery uses) uses object literals to configure their selector parsing. When it loops these config objects to get all tokens, it doesn't expect your function. In this case, it's probably trying to use your function as a RegExp.
Imagine this scenario:
var obj = { a: 1, b: 2, c: 3 };
var result = 0;
for (var prop in obj) {
// On one of these iterations, `prop` will be "allKeys".
// In this case, `obj[prop]` will be a function instead of a number.
result += obj[prop] * 2;
}
console.log(result);
If you have added anything to Object's prototype that can't be used as a number, you will get NaN for your result.
A good solution to this problem is to add the allKeys function to Object instead of Object.prototype. This mimics Object.keys:
Object.allKeys = function (obj) {
var keys = [];
for (var key in obj)
{
// Very important to check for dictionary.hasOwnProperty(key)
// otherwise you may end up with methods from the prototype chain..
if (obj.hasOwnProperty(key))
{
keys.push(key);
//alert(key);
} // End if (dict.hasOwnProperty(key))
} // Next key
keys.sort();
return keys;
}; // End Extension Function allKeys
You may be able to overcome this side-effect by using defineProperty which allows for setting descriptors.
Object.defineProperty(Object.prototype, 'propName', {value: 'your value', enumerable: false});
Because jQuery doesn't bog down its code with checks for .hasOwnProperty() when enumerating objects.
To do so, is to place guards against bad coding practices. Rather than weigh down their code to accommodate such practices, they require that their users adhere to good practices, like never putting enumerable properties on Object.prototype.
In other words... Don't add enumerable properties to Object.prototype unless you want all your code to run guards against those properties, and you never want to enumerate inherited properties.
FWIW, if you really want to call methods on plain objects, just make a constructor so that you have an intermediate prototype object that can be safely extended.
function O(o) {
if (!(this instanceof O))
return new O(o)
for (var p in o)
this[p] = o[p]
}
O.prototype.allKeys = function() {
// ...
};
Now you create your objects like this:
var foo = O({
foo: "foo",
bar: "bar",
baz: "baz"
});
...and the Object.prototype remains untouched, so plain objects are still safe. You'll just need to use the .hasOwnProperty() guard when enumerating your O objects.
for (var p in foo) {
if (foo.hasOwnProperty(p)) {
// do stuff
}
}
And with respect to JSON data being parsed, you can use a reviver function to swap out the plain objects with your O object.
var parsed = JSON.parse(jsondata, function(k, v) {
if (v && typeof v === "object" && !(v instanceof Array)) {
return O(v)
}
return v
});
I am currently breaking my head about transforming this object hash:
"food": {
"healthy": {
"fruits": ['apples', 'bananas', 'oranges'],
"vegetables": ['salad', 'onions']
},
"unhealthy": {
"fastFood": ['burgers', 'chicken', 'pizza']
}
}
to something like this:
food:healthy:fruits:apples
food:healthy:fruits:bananas
food:healthy:fruits:oranges
food:healthy:vegetables:salad
food:healthy:vegetables:onions
food:unhealthy:fastFood:burgers
food:unhealthy:fastFood:chicken
food:unhealthy:fastFood:pizza
In theory it actually is just looping through the object while keeping track of the path and the end result.
Unfortunately I do not know how I could loop down till I have done all nested.
var path;
var pointer;
function loop(obj) {
for (var propertyName in obj) {
path = propertyName;
pointer = obj[propertyName];
if (pointer typeof === 'object') {
loop(pointer);
} else {
break;
}
}
};
function parse(object) {
var collection = [];
};
There are two issues which play each out:
If I use recurse programming it looses the state of the properties which are already parsed.
If I do not use it I cannot parse infinite.
Is there some idea how to handle this?
Regards
The reason your recursive function doesn't work is you're storing the state outside it. You want the state inside it, so that each invocation tracks its state.
Something like this:
var obj = /* ... the object ... */;
var lines = loop([], "", obj);
function loop(lines, prefix, obj) {
var key, sawOne = false;
// Is it an array?
if (Object.prototype.toString.call(obj) === "[object Array]") {
// Yes, in your example these are all just strings to put
// at the end, so do that
for (key = 0; key < obj.length; ++key) {
lines.push(prefix + ":" + obj[key]);
}
}
else {
// No, it's an object. Recurse for each property, adding the
// property to the prefix we use on each line
for (key in obj) {
loop(lines, prefix ? (prefix + ":" + key) : key, obj[key]);
}
}
return lines;
}
Completely off-the-cuff and untested, but you get the idea.
Edit: But apparently it works, as Michael Jasper was kind enough to make a live demo (source) which I've tweaked slightly.
is there a way to iterate an object properties and methods. i need to write a utility function like so:
function iterate(obj)
{
//print all obj properties
//print all obj methods
}
so running this function:
iterate(String);
will print:
property: lenght
function: charAt
function: concat...
any ideas?
Should be as simple as this:
function iterate(obj) {
for (p in obj) {
console.log(typeof(obj[p]), p);
}
}
Note: The console.log function is assuming you are using firebug. At this point, the following:
obj = {
p1: 1,
p2: "two",
m1: function() {}
};
iterate(obj);
would return:
number p1
string p2
function m1
See my answer in this other question, but you can't read built-in properties like that.
This only works in modern browsers (Chrome, Firefox 4+, IE9+), but in ECMAScript 5, you can get all the properties of an object with Object.getOwnPropertyNames. It just takes a little extra code to get the inherited properties from the prototype.
// Put all the properties of an object (including inherited properties) into
// an object so they can be iterated over
function getProperties(obj, properties) {
properties = properties || {};
// Get the prototype's properties
var prototype = Object.getPrototypeOf(obj);
if (prototype !== null) {
getProperties(prototype, properties);
}
// Get obj's own properties
var names = Object.getOwnPropertyNames(obj);
for (var i = 0; i < names.length; i++) {
var name = names[i];
properties[name] = obj[name];
}
return properties;
}
function iterate(obj) {
obj = Object(obj);
var properties = getProperties(obj);
for (var name in properties) {
if (typeof properties[name] !== "function") {
console.log("property: " + name);
}
}
for (var name in properties) {
if (typeof properties[name] === "function") {
console.log("function: " + name);
}
}
}
You can use the for loop to iterate an object's properties.
Here is a simple example
var o ={'test':'test', 'blah':'blah'};
for(var p in o)
alert(p);