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.
Related
I have a bunch of object attributes coming in as dot-delimited strings like "availability_meta.supplier.price", and I need to assign a corresponding value to record['availability_meta']['supplier']['price'] and so on.
Not everything is 3 levels deep: many are only 1 level deep and many are deeper than 3 levels.
Is there a good way to assign this programmatically in Javascript? For example, I need:
["foo.bar.baz", 1] // --> record.foo.bar.baz = 1
["qux.qaz", "abc"] // --> record.qux.qaz = "abc"
["foshizzle", 200] // --> record.foshizzle = 200
I imagine I could hack something together, but I don't have any good algorithm in mind so would appreciate suggestions. I'm using lodash if that's helpful, and open to other libraries that may make quick work of this.
EDIT this is on the backend and run infrequently, so not necessary to optimize for size, speed, etc. In fact code readability would be a plus here for future devs.
EDIT 2 This is NOT the same as the referenced duplicate. Namely, I need to be able to do this assignment multiple times for the same object, and the "duplicate" answer will simply overwrite sub-keys each time. Please reopen!
You mentioned lodash in your question, so I thought I should add their easy object set() and get() functions. Just do something like:
_.set(record, 'availability_meta.supplier.price', 99);
You can read more about it here: https://lodash.com/docs#set
These functions let you do more complex things too, like specify array indexes, etc :)
Something to get you started:
function assignProperty(obj, path, value) {
var props = path.split(".")
, i = 0
, prop;
for(; i < props.length - 1; i++) {
prop = props[i];
obj = obj[prop];
}
obj[props[i]] = value;
}
Assuming:
var arr = ["foo.bar.baz", 1];
You'd call it using:
assignProperty(record, arr[0], arr[1]);
Example: http://jsfiddle.net/x49g5w8L/
What about this?
function convertDotPathToNestedObject(path, value) {
const [last, ...paths] = path.split('.').reverse();
return paths.reduce((acc, el) => ({ [el]: acc }), { [last]: value });
}
convertDotPathToNestedObject('foo.bar.x', 'FooBar')
// { foo: { bar: { x: 'FooBar' } } }
Just do
record['foo.bar.baz'] = 99;
But how would this work? It's strictly for the adventurous with a V8 environment (Chrome or Node harmony), using Object.observe. We observe the the object and capture the addition of new properties. When the "property" foo.bar.baz is added (via an assignment), we detect that this is a dotted property, and transform it into an assignment to record['foo']['bar.baz'] (creating record['foo'] if it does not exist), which in turn is transformed into an assignment to record['foo']['bar']['baz']. It goes like this:
function enable_dot_assignments(changes) {
// Iterate over changes
changes.forEach(function(change) {
// Deconstruct change record.
var object = change.object;
var type = change.type;
var name = change.name;
// Handle only 'add' type changes
if (type !== 'add') return;
// Break the property into segments, and get first one.
var segments = name.split('.');
var first_segment = segments.shift();
// Skip non-dotted property.
if (!segments.length) return;
// If the property doesn't exist, create it as object.
if (!(first_segment in object)) object[first_segment] = {};
var subobject = object[first_segment];
// Ensure subobject also enables dot assignments.
Object.observe(subobject, enable_dot_assignments);
// Set value on subobject using remainder of dot path.
subobject[segments.join('.')] = object[name];
// Make subobject assignments synchronous.
Object.deliverChangeRecords(enable_dot_assignments);
// We don't need the 'a.b' property on the object.
delete object[name];
});
}
Now you can just do
Object.observe(record, enable_dot_assignments);
record['foo.bar.baz'] = 99;
Beware, however, that such assignments will be asynchronous, which may or may not work for you. To solve this, call Object.deliverChangeRecords immediately after the assignment. Or, although not as syntactically pleasing, you could write a helper function, also setting up the observer:
function dot_assignment(object, path, value) {
Object.observe(object, enable_dot_assignments);
object[path] = value;
Object.deliverChangeRecords(enable_dot_assignments);
}
dot_assignment(record, 'foo.bar.baz', 99);
Something like this example perhaps. It will extend a supplied object or create one if it no object is supplied. It is destructive in nature, if you supply keys that already exist in the object, but you can change that if that is not what you want. Uses ECMA5.
/*global console */
/*members split, pop, reduce, trim, forEach, log, stringify */
(function () {
'use strict';
function isObject(arg) {
return arg && typeof arg === 'object';
}
function convertExtend(arr, obj) {
if (!isObject(obj)) {
obj = {};
}
var str = arr[0],
last = obj,
props,
valProp;
if (typeof str === 'string') {
props = str.split('.');
valProp = props.pop();
props.reduce(function (nest, prop) {
prop = prop.trim();
last = nest[prop];
if (!isObject(last)) {
nest[prop] = last = {};
}
return last;
}, obj);
last[valProp] = arr[1];
}
return obj;
}
var x = ['fum'],
y = [
['foo.bar.baz', 1],
['foo.bar.fum', new Date()],
['qux.qaz', 'abc'],
['foshizzle', 200]
],
z = ['qux.qux', null],
record = convertExtend(x);
y.forEach(function (yi) {
convertExtend(yi, record);
});
convertExtend(z, record);
document.body.textContent = JSON.stringify(record, function (key, value, Undefined) {
/*jslint unparam:true */
/*jshint unused:false */
if (value === Undefined) {
value = String(value);
}
return value;
});
}());
it's an old question, but if anyone still looking for a solution can try this
function restructureObject(object){
let result = {};
for(let key in object){
const splittedKeys = key.split('.');
if(splittedKeys.length === 1){
result[key] = object[key];
}
else if(splittedKeys.length > 2){
result = {...result, ...{[splittedKeys.splice(0,1)]: {}} ,...restructureObject({[splittedKeys.join('.')]: object[key]})}
}else{
result[splittedKeys[0]] = {[splittedKeys[1]]: object[key]}
}
}
return result
}
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.
Based on my understanding of the docs (here and here) one would need a reference to the memory address for it to work:
const foo = {};
const map = new Map();
map.set(foo,'123'); // Can only be done if memory address of `foo` is known. Any other shimming would require stringification of foo
This is because JavaScript object {} keys can only be strings (at least in ES5).
Yet I see Map shim being available : https://github.com/zloirock/core-js#map. I tried reading the source but its too neatly abstracted (internally uses strong collection which then imports 10 more files)
Question
Answer any of the following please
Is there a simple trick to it and can it truly even be done (without stringification)?
Perhaps it mutates foo to store some string on it and then uses that as the key?
Something else and maybe I am reading the docs wrong?
There are two ways that come to mind. First, obviously, you can have an array of keys, and search it linearly:
Map1 = {
keys: [],
values: [],
};
Map1.set = function(key, val) {
var k = this.keys.indexOf(key);
if(k < 0)
this.keys[k = this.keys.length] = key;
this.values[k] = val;
};
Map1.get = function(key) {
return this.values[this.keys.indexOf(key)];
};
foo = {};
bar = {};
Map1.set(foo, 'xxx');
Map1.set(bar, 'yyy');
document.write(Map1.get(foo) + Map1.get(bar) + "<br>")
The second option is to add a special "key" marker to an object which is used as a key:
Map2 = {
uid: 0,
values: {}
};
Map2.set = function(key, val) {
key = typeof key === 'object'
? (key.__uid = key.__uid || ++this.uid)
: String(key);
this.values[key] = val;
};
Map2.get = function(key) {
key = typeof key === 'object'
? key.__uid
: String(key);
return this.values[key];
};
foo = {};
bar = {};
Map2.set(foo, 'xxx');
Map2.set(bar, 'yyy');
document.write(Map2.get(foo) + Map2.get(bar) + "<br>")
Unlike the 1st option, the second one is O(1). It can be done more accurately by making uid non-writable/enumerable. Also, each Map should have its own "uid" name (this can be easily set up in the Map constructor).
The trick is to store in an array and perform the lookup in O(n) time by iterating and using strict comparison—instead of using a true hash function which would be O(1) lookup. For example consider this:
var myObj = {};
var someArray = [{}, {}, myObj, {}];
console.log(someArray.indexOf(myObj)); // returns 2
Here is my implementation from another answer: Javascript HashTable use Object key
function Map() {
var keys = [], values = [];
return {
put: function (key, value) {
var index = keys.indexOf(key);
if(index == -1) {
keys.push(key);
values.push(value);
}
else {
values[index] = value;
}
},
get: function (key) {
return values[keys.indexOf(key)];
}
};
}
Have a look at my polyfill here. I am not advertising my polyfill, rather all I am saying is that it is the simplest and most straightforward I have yet to find, and thus it is the most suitable for learning and educational analysis. Basically, how it works is it uses a lookup table for the keys and a corresponding value table as visualized below.
var k = {}, j = [], m = document, z = NaN;
var m = new Map([
[k, "foobar"], [j, -0xf], [m, true], [z, function(){}]
]);
Index Key Value
##### ################ ################
0. k ({}) "foobar"
1. j ([]) -15
2. m (Document) true
3. z (NaN) function(){}
Internally, each item is stored at a different index, or at least that is the way I like to do it. This is also similar to the way the browser implements it internally. Unfortunately, I have seen some other polyfills that attempt to instead store the key on the object itself, and mess with all the internal methods to hide it, resulting in the entire webpage running 10000% slower and the maps being so slow that it takes nearly a full millisecond just to set and get new properties. Plus, I cannot fathom how many countless hours they waisted just trying to monkey-patch all the internal methods such as hasOwnProperty.
As for how and why my polyfill works, javascript objects are stored at a different place in memory. That is why [] !== [] and indexOf on an array of javascript objects works properly. It is because they are not the same array.
This question already has answers here:
How do I check if an array includes a value in JavaScript?
(60 answers)
Closed 29 days ago.
I need to determine if an object already exists in an array in javascript.
eg (dummycode):
var carBrands = [];
var car1 = {name:'ford'};
var car2 = {name:'lexus'};
var car3 = {name:'maserati'};
var car4 = {name:'ford'};
carBrands.push(car1);
carBrands.push(car2);
carBrands.push(car3);
carBrands.push(car4);
now the "carBrands" array contains all instances.
I'm now looking a fast solution to check if an instance of car1, car2, car3 or car4 is already in the carBrands array.
eg:
var contains = carBrands.Contains(car1); //<--- returns bool.
car1 and car4 contain the same data but are different instances they should be tested as not equal.
Do I have add something like a hash to the objects on creation? Or is there a faster way to do this in Javascript.
I am looking for the fastest solution here, if dirty, so it has to be ;) In my app it has to deal with around 10000 instances.
no jquery
Use something like this:
function containsObject(obj, list) {
var i;
for (i = 0; i < list.length; i++) {
if (list[i] === obj) {
return true;
}
}
return false;
}
In this case, containsObject(car4, carBrands) is true. Remove the carBrands.push(car4); call and it will return false instead. If you later expand to using objects to store these other car objects instead of using arrays, you could use something like this instead:
function containsObject(obj, list) {
var x;
for (x in list) {
if (list.hasOwnProperty(x) && list[x] === obj) {
return true;
}
}
return false;
}
This approach will work for arrays too, but when used on arrays it will be a tad slower than the first option.
Why don't you use the indexOf method of javascript arrays?
Check this out: MDN indexOf Arrays
Simply do:
carBrands.indexOf(car1);
It will return you the index (position in the array) of car1. It will return -1 if car1 was not found in the array.
http://jsfiddle.net/Fraximus/r154cd9o
Edit: Note that in the question, the requirements are to check for the same object referenced in the array, and NOT a new object. Even if the new object is identical in content to the object in the array, it is still a different object.
As mentioned in the comments, objects are passed by reference in JS and the same object can exist multiple times in multiple structures.
If you want to create a new object and check if the array contains objects identical to your new one, this answer won't work (Julien's fiddle below), if you want to check for that same object's existence in the array, then this answer will work. Check out the fiddles here and in the comments.
Having been recently bitten by the FP bug reading many wonderful accounts of how neatly the functional paradigm fits with Javascript
I replicate the code for completeness sake and suggest two ways this can be done functionally.
var carBrands = [];
var car1 = {name:'ford'};
var car2 = {name:'lexus'};
var car3 = {name:'maserati'};
var car4 = {name:'ford'};
var car5 = {name:'toyota'};
carBrands.push(car1);
carBrands.push(car2);
carBrands.push(car3);
carBrands.push(car4);
// ES6 approach which uses the includes method (Chrome47+, Firefox43+)
carBrands.includes(car1) // -> true
carBrands.includes(car5) // -> false
If you need to support older browsers use the polyfill, it seems IE9+ and Edge do NOT support it. Located in polyfill section of MSDN page
Alternatively I would like to propose an updated answer to cdhowie
// ES2015 syntax
function containsObject(obj, list) {
return list.some(function(elem) {
return elem === obj
})
}
// or ES6+ syntax with cool fat arrows
function containsObject(obj, list) {
return list.some(elem => elem === obj)
}
try Array.prototype.some()
MDN Array.prototype.some
function isBiggerThan10(element, index, array) {
return element > 10;
}
[2, 5, 8, 1, 4].some(isBiggerThan10); // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true
You could use jQuery's grep method:
$.grep(carBrands, function(obj) { return obj.name == "ford"; });
But as you specify no jQuery, you could just make a derivative of the function. From the source code:
function grepArray( elems, callback, inv ) {
var ret = [];
// Go through the array, only saving the items
// that pass the validator function
for ( var i = 0, length = elems.length; i < length; i++ ) {
if ( !inv !== !callback( elems[ i ], i ) ) {
ret.push( elems[ i ] );
}
}
return ret;
}
grepArray(carBrands, function(obj) { return obj.name == "ford"; });
I used underscore javascript library to tweak this issue.
function containsObject(obj, list) {
var res = _.find(list, function(val){ return _.isEqual(obj, val)});
return (_.isObject(res))? true:false;
}
please refer to underscore.js documentation for the underscore functions used in the above example.
note: This is not a pure javascript solution. Shared for educational purposes.
You can just use the equality operator: ==. Objects are checked by reference by default, so you don't even need to use the === operator.
try this, just make sure you're using the correct variable reference in the place of car1:
var i, car, l = cars.length;
for (i = 0; i < l; i++)
{
if ((car = cars[i]) == car1)
{
break;
}
else car = null;
}
Edit to add:
An array extension was mentioned, so here's the code for it:
Array.prototype.contains = Array.prototype.contains || function(obj)
{
var i, l = this.length;
for (i = 0; i < l; i++)
{
if (this[i] == obj) return true;
}
return false;
};
Note that I'm caching the length value, as the Array's length property is actually an accessor, which is marginally slower than an internal variable.
I would use a generic iterator of property/value over the array. No jQuery required.
arr = [{prop1: 'val1', prop2: 'val2'}, {prop1: 'val3', prop2: 'val4'}];
objectPropInArray(arr, 'prop1', 'val3'); // <-- returns true
function objectPropInArray(list, prop, val) {
if (list.length > 0 ) {
for (i in list) {
if (list[i][prop] === val) {
return true;
}
}
}
return false;
}
You could try sorting the array based on a property, like so:
carBrands = carBrands.sort(function(x,y){
return (x == y) ? 0 : (x > y) ? 1 : -1;
});
Then you can use an iterative routine to check whether
carBrands[Math.floor(carBrands.length/2)]
// change carBrands.length to a var that keeps
// getting divided by 2 until result is the target
// or no valid target exists
is greater or lesser than the target, and so on, which will let you go through the array quickly to find whether the object exists or not.
try this ,
You can use the JavaScript some() method to find out if a JavaScript array contains an object.
<script>
// An array of objects
var persons = [{name: "Harry"}, {name: "Alice"}, {name: "Peter"}];
// Find if the array contains an object by comparing the property value
if(persons.some(person => person.name === "Peter")){
alert("Object found inside the array.");
} else{
alert("Object not found.");
}
</script>
EDIT 05/18/2022
The most simple way using ES6:
const arrayContainsObject = <T extends Record<string, unknown>>(array: T[], object: T) => {
return array.some(item => Object.keys(item).every(key => item[key] === object[key]))
}
Use like so:
const arr = [{
prop1: 'value1',
prop2: 'value2'
}]
const obj1 = {
prop1: 'value1',
prop2: 'value2'
}
const obj2 = {
prop2: 'value2',
prop1: 'value1'
}
const obj3 = {
prop0: 'value0',
prop1: 'value1'
}
arrayContainsObject(arr, obj1) // true
arrayContainsObject(arr, obj2) // true, even when props are arranged in different order
arrayContainsObject(arr, obj3) // false
Previous answer, don't use (because the order of props in an object needs to be identical)
const arr = [{
prop: 'value'
}]
const obj = {
prop: 'value'
}
arr.some((e) => Object.entries(e).toString() === Object.entries(obj).toString()) // true
i know this is an old post, but i wanted to provide a JQuery plugin version and my code.
// Find the first occurrence of object in list, Similar to $.grep, but stops searching
function findFirst(a,b){
var i; for (i = 0; i < a.length; ++i) { if (b(a[i], i)) return a[i]; } return undefined;
}
usage:
var product = $.findFirst(arrProducts, function(p) { return p.id == 10 });
This function is to check for a unique field.
Arg 1: the array with selected data
Arg 2: key to check
Arg 3: value that must be "validated"
function objectUnique( array, field, value )
{
var unique = true;
array.forEach(function ( entry )
{
if ( entry[field] == value )
{
unique = false;
}
});
return unique;
}
you can use Array.find().
in your case is going to look like this
carBrands.find(function(car){
let result = car.name === 'ford'
if (result == null){
return false;
} else {
return true
}
});
if car is not null it will return the javaScript Object which contains the string 'ford'
The issue with many of the answers here is that they will NOT find an object in an array that is equal to another object. They will only search for an EXISTING object that has a pointer to it in an array.
Quick fix using lodash to see if ANY equal object is in an array:
import _ from 'lodash';
_.find(carBrands, car1); //returns object if true, undefined if false
Working Plunker using this method: https://plnkr.co/edit/y2YX9o7zkQa2r7lJ
if its possible to use es6
carBrands.filter(carBrand => carBrand.name === carX.name).length > 0
if it's true there is a similarity
You can convert both the JSON objects to string and simply check if the bigger json contains the smaller json.
console.log(JSON.stringify(carBrands).includes(JSON.stringify(car1))); // true
console.log(JSON.stringify(carBrands).includes(JSON.stringify(car5))); // false
You could also a the findIndex
var carBrands = [];
var car1 = {name:'ford'};
var car2 = {name:'lexus'};
carBrands.push(car1);
if (carBrands.findIndex(f => f.name === car1.name) === -1) {
console.log('not contain')
} else {
console.log('contain')
}
if (carBrands.findIndex(f => f.name === car2.name) === -1) {
console.log('not contain')
} else {
console.log('contain')
}
I know in JavaScript, objects double as hashes, but I have been unable to find a built-in function to get the keys:
var h = {a:'b', c:'d'};
I want something like
var k = h.keys() ; // k = ['a', 'c'];
It is simple to write a function myself to iterate over the items and add the keys to an array that I return, but is there a standard cleaner way to do that?
I keep feeling it must be a simple built in function that I missed but I can't find it!
There is function in modern JavaScript (ECMAScript 5) called Object.keys performing this operation:
var obj = { "a" : 1, "b" : 2, "c" : 3};
alert(Object.keys(obj)); // will output ["a", "b", "c"]
Compatibility details can be found here.
On the Mozilla site there is also a snippet for backward compatibility:
if(!Object.keys) Object.keys = function(o){
if (o !== Object(o))
throw new TypeError('Object.keys called on non-object');
var ret=[],p;
for(p in o) if(Object.prototype.hasOwnProperty.call(o,p)) ret.push(p);
return ret;
}
For production code requiring a large compatibility with client browsers I still suggest Ivan Nevostruev's answer with shim to ensure Object.keys in older browsers. However, it's possible to get the exact functionality requested using ECMA's new defineProperty feature.
As of ECMAScript 5 - Object.defineProperty
As of ECMA5 you can use Object.defineProperty() to define non-enumerable properties. The current compatibility still has much to be desired, but this should eventually become usable in all browsers. (Specifically note the current incompatibility with IE8!)
Object.defineProperty(Object.prototype, 'keys', {
value: function keys() {
var keys = [];
for(var i in this) if (this.hasOwnProperty(i)) {
keys.push(i);
}
return keys;
},
enumerable: false
});
var o = {
'a': 1,
'b': 2
}
for (var k in o) {
console.log(k, o[k])
}
console.log(o.keys())
# OUTPUT
# > a 1
# > b 2
# > ["a", "b"]
However, since ECMA5 already added Object.keys you might as well use:
Object.defineProperty(Object.prototype, 'keys', {
value: function keys() {
return Object.keys(this);
},
enumerable: false
});
Original answer
Object.prototype.keys = function ()
{
var keys = [];
for(var i in this) if (this.hasOwnProperty(i))
{
keys.push(i);
}
return keys;
}
Edit: Since this answer has been around for a while I'll leave the above untouched. Anyone reading this should also read Ivan Nevostruev's answer below.
There's no way of making prototype functions non-enumerable which leads to them always turning up in for-in loops that don't use hasOwnProperty. I still think this answer would be ideal if extending the prototype of Object wasn't so messy.
You can use Object.keys:
Object.keys(h)
You could use Underscore.js, which is a JavaScript utility library.
_.keys({one : 1, two : 2, three : 3});
// => ["one", "two", "three"]
This is the best you can do, as far as I know...
var keys = [];
for (var k in h)keys.push(k);
Using jQuery, you can get the keys like this:
var bobject = {primary:"red", bg:"maroon", hilite:"green"};
var keys = [];
$.each(bobject, function(key, val){ keys.push(key); });
console.log(keys); // ["primary", "bg", "hilite"]
Or:
var bobject = {primary:"red", bg:"maroon", hilite:"green"};
$.map(bobject, function(v, k){return k;});
Thanks to #pimlottc.
I believe you can loop through the properties of the object using for/in, so you could do something like this:
function getKeys(h) {
Array keys = new Array();
for (var key in h)
keys.push(key);
return keys;
}
I wanted to use AnnanFay's answer:
Object.prototype.keys = function () ...
However, when using it in conjunction with the Google Maps API v3, Google Maps is non-functional.
However,
for (var key in h) ...
works well.
If you are trying to get the elements only, but not the functions then this code can help you:
this.getKeys = function() {
var keys = new Array();
for (var key in this) {
if (typeof this[key] !== 'function') {
keys.push(key);
}
}
return keys;
}
This is part of my implementation of the HashMap and I only want the keys. this is the hashmap object that contains the keys.
In Javascript we can use
Object.keys(h)