creating javascript objects with unique names depending on counter in loop - javascript

I'm new enough to Javascript, and I have a small query about formulating variable names :
function createObjects(int length) {
var count;
for(count=0; count<length; count++;) {
var personObj + "" + count;
}
}
here I want to formulate a different personObj for each iteration of the for loop, is this the correct procedure? will this give me :
var personObj1
var personObj2
etc
Thanks!
Matt

If you want to have several instances of the same underlying data structure / logic you could use an approach like this:
Create a constructor function that generates an Object with the properties (also methods) that you need. For example:
function PersonObj(name, age) {
this.name = name;
this.age = age;
}
This enables you to create a new instance of PersonObj by using var n = new PersonObj('Fred',32);. Now you can use an Array to store multiple instancesof these objects:
var persons = []; // creates a new Array
for (var i = 1; i < 13; i++){
persons.push(new PersonObj('Alfred', i));
}
persons will now contain twelve Alfreds of age 1 to 12.
If you want to alter Alfred No. 3's age you could do:
persons[2].age = 99;
See a live demo

Don't. Dynamically generating variables is never a good idea. Use an object or an array instead. They are designed to structure groups of related data.
function createObjects(length) {
var count, people = [];
for(count=0; count<length; count++;) {
people.push('something');
}
return people;
}

Why not use an array for this instead?

if needs must, you can alwvays add a named property to the window object:
function createObjects(int length) {
var count;
for(count=0; count<length; count++;) {
window[personObj + "" + count] = new SomeObject();
}
}

Create the objects, add properties to objects and store the objects in an array.
var al = new Array();
function createObjects(int length) {
var o = new Object();
for(var count=0; count<length; count++;) {
o.count = 'some value';
}
al.push(o);
}

Related

Declare Multi Dimensional Array in Package.json [duplicate]

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.

How to create multiple instances of objects in Javascript

I have a constructor object in my code which is:
function Employee(){
this.name = names[Math.floor(Math.random() * names.length)];
this.age=1;
this.level=1;
this.production=400;
this.totalprod=0;
}
So when I create a new Employee I just say:
var employee1 = new Employee();
So then I can manipulate this instance of the object. Now, I want this objects to be created dynamically with the variable names: employee1, employee2, employee3 and so on.. Is there a way to achieve this or is it impossible?
And the other question that I have, say that I want to change the age of all instances at the same time, is there a way to do this? Thanks in advance and sorry if the question in silly, I'm learning!
EDIT: This is not the same as the other question as I'm using a constructor Object, not a literal Object, and, apart from that, I ask another question which is how to change a property of all instances at the same time, thanks!
This isn't really possible without the use of something like eval, which is bad practice.
Instead if you knew how many employees you wanted to make in advance you could do something like this.
Example: https://jsfiddle.net/dbyw7p9x/
function makeEmployees(n) {
var employees = new Array(n)
for (var i = 0; i < n; ++i) {
employees[i] = new Employee()
}
return employees
}
alternatively you could make also make it return an object which interestingly, while not exactly the same as the array, would be accessed in the same way as an array using numbers inside square brackets obj[0], obj[1], obj[2], obj[3] etc.
function makeEmployeesObj(n) {
var employees = {}
for (var i = 0; i < n; ++i) {
employees[i] = new Employee()
}
return employees
}
To change a property for each approach you can do:
// Array
for (var i = 0; i < e1.length; ++i) {
e1[i].age = 2
}
// Object
Object.keys(e2).forEach(function(key) {
e2[key].age = 2
})
Here is one way to do it, using an array, we push to new Employees to it, and return that array:
To add a specific value, in this case age, I recommend passing it in as a parameter to your Employee constructor, you can do this with all of the this parameters if you like:
Notice in the JsBin that all the ages are different, they are actually the value of n:
Working example: JSBin
function Employee(age){
this.name = 'something';
this.age= age;
this.level=1;
this.production=400;
this.totalprod=0;
}
function maker(n) {
var arr = [];
while (n > 0) {
arr.push(new Employee(n));
n--;
}
return arr;
}

How to define new object of variable type of array object?

jQuery has made my life easier but I'm still very beginner to JavaScript. So, may be, I'm asking a very stupid question here:
var t = {
rows: 3,
columns: 5,
getCellCount: function () {
return this.rows * this.columns;
}
};
var tn = t;
tn.rows = 6;
document.write(tn.rows + " , " + t.rows); // returns 6 , 6
I also tried var tn = new t(); // but seems wrong
So, How to retrieve old intrinsic value from object so that it results 6 , 3
tn and t are both pointing to the same object, that's why when you change tn.rows it also changes t.rows. There is no such thing as old intrinsic value.
You must copy the object in order to keep the old value. There are two: shallow copy and deep copy.
Copying the key-value pairs is pretty easy with Object.create.
var newObj = Object.create(oldObj);
Now if you change the values in newObj, it will not change the original one:
var a = {a:1}, b = Object.create(a);
b.a = 2;
console.log(a.a, b.a); //1,2
However, to perform a complete copy is really complicated. See more: How do I correctly clone a JavaScript object?
PS: The new keyword you mentioned is for creating an object as in classes.
function Car(n, y){ //This is called a "constructor"
var name = n, year = y; //Private variables
return {
getName: function(){ return name; }, //Getters
getYear: function(){ return year; }
};
}
var myNewCar = new Car("Toyota", 2010);
myNewCar.getName(); //"Toyota"
myNewCar.getYear(); //2010
(This is also how you create objects in Java, if you have taken those CS courses you would recognize this pattern.)
var tn = t;
simply makes both tn and t to point to the same object in memory. So, change in one object will reflect in other as well. You can clone the object, like this
function copyObject(sourceObject) {
var result = {};
for (var key in sourceObject) {
if (sourceObject.hasOwnProperty(key)) {
result[key] = sourceObject[key];
}
}
return result;
}
var tn = copyObject(t);
You are asking to clone a JSON object.
var tn={};
for (key in t) tn[key]=t[key];
There may be other "prettier" ways, but this guarantees the clone.
The = operator in javascript just changes what the object points to, so it will not create a copy of the original object. You can take a look here to see possible ways to create a clone of the object.
If you want to create a Javascript object, the conventional way is to create a function:
// Use capitalized names for Object-creating functions.
// I guessed that you wanted a matrix of some sort.
function Matrix(rows, columns) {
this.rows = rows;
this.columns = columns;
this.cellCount = function() {
return this.rows * this.columns;
}
this.dimensions = function() {
return this.rows, + ", " + this.columns;
}
this.copy = function() {
return new Matrix(this.rows, this.columns);
}
}
var t = new Matrix(6, 3);
There are more sophisticated ways to do this, using Object.create. Look at Javascript: The Good Parts.

How do i create variable names using contents of an array using javascript

i have created an array,
var myBuildingName=['A1','A2','A3','A4'];
where A1,A2,A3 and A4 are the names obtained through user input.
i now want to create arrays that have names A1,A2,A3 and A4.
i have tried using
for(var i=0;i<myBuildingName.length;i++)
{
var myBuildingName[i]=[];
}
but it does not work...
please help.
You create a master parent object and use the array values as keys into the object where you can store an array for each.
var myBuildingName=['A1','A2','A3','A4'];
var master = {};
for (var i = 0; i < myBuildingName.length; i++) {
master[myBuildingName[i]] = [];
}
Then, you can access the data like:
var a1Array = master['A1'];
or
var firstA1Item = master['A1'][0];
If you actually wanto create variables with those names (which I won't recommend), you'd have to eval() them. So:
for(var i=0;i<myBuildingName.length;i++)
{
eval("var " + myBuildingName[i] + " = [] "); // This creates Array variables called A1, A2 etc.
}
Again, the above method is NOT recommended. You should assign the names as keys to an object literal, like:
var myStuff = {};
for(var i=0;i<myBuildingName.length;i++)
{
var myStuff[myBuildingName[i]] = [];
}
You can't access the local variable object (except in global code), so you can't add properties other than by variable declaration. For global code in the global context you could do:
var global = this;
for ( ...) {
global[myBuildingName[i]] = []
}
but you can't do that for function code in function context. See jfriend00's answer.
Here's a demo
var myBuildingName = ['A1', 'A2', 'A3', 'A4'];
function arrayFromNames(arr) {
var store = {}; //storage for the arrays
for (var i = 0; i < arr.length; i++) { //for each in the passed names
store[arr[i]] = []; //add to the storage an array with the corresponding name
}
return store; //return the storage
}
var nameArrays = arrayFromNames(myBuildingName); //build using your array
console.log(nameArrays);​
//you now have:
//nameArrays.A1, nameArrays.A2,...
//or
//nameArrays['A1'], nameArrays['A2'],...
You have received a lot of great answers, if one of them serves your need, you should accept that answer. The fact that this is still open makes us think no-one has quite answered your question the way you had hoped.
If that is the case, I can only assume that you wanted to use those variables in a global scope.
var myBuildingName=['A1','A2','A3','A4'];
for (var i = 0; i < myBuildingName.length; i++) {
window[myBuildingName[i]] = [];
}
Now you can access your variables 'normally'.
A1.push('test');
Note: this is horrible practice, since you should never pollute the global space.

Hash/associative array using several objects as key

Is there a way of making an associative array where each key is a hash of several objects? I'm not interested in inspecting each object's state, but rather the object's identity.
var myarray = {};
var a = new A();
var b = new B();
var c = new C();
// + is not right, but illustrates the hashing I'm after.
myarray[a + b + c] = 42;
The + operator is not right. In java I would arithmetically combine the System.identityHashCode() for each of these three instances and use the result to make my new hash key. Is there some similar mechanic in javascript?
Overriding the .toString() method in A, B and C is not an option since I'm interested in object identity, not state.
Actually impossible since Object keys in this language only can be strings and there's no equivalent of java's object identity.
:o)
You could overwrite the toString() method of the prototypes to create a unique hash for each instance. E.g.
A.prototype.toString = function() {
return /* something instance specific here */;
};
Even a + b + c would work then.
Update: Afaik, you cannot get an instance unique id (whatever that is) in JavaScript. You could however assign each instance some identifier.
This only works if you are creating the objects.
E.g.
var addIdentityTracker = (function() {
var pad = "0000000000",
id = 1;
function generateId() {
var i = (id++).toString();
return pad.substr(0, 10 - i.length) + i;
}
return function(Constr) {
var new_constr = function() {
this.___uid = generateId();
Constr.apply(this, arguments);
};
new_constr.prototype = Constr.prototype;
new_constr.prototype.toString = function() {
return this.___uid;
};
return new_constr;
};
}());
and then do:
A = addIdentityTracker(A);
var a = new A();
I'd suggest just assigning a unique ID to each object. Javascript doesn't come with a built-in unique ID mechanism, but you can assign a unique ID to any object you want and then use it as such. For example, you could do this:
// getUniqueID is a function that returns a unique ID for any javascript object.
// If no uniqueID is already present on the object, it coins one using a global
// counter and then stores it on the object.
// So that the uniqueID can be combined with other uniqueIDs easily and still
// create a unique union, the uniqueID here is a unique 10 character string.
// There is no randomness in the IDs as they are only required to be unique
// within the page, not random or unique in the universe. The monotomically
// increasing counter guarantees uniqueness within the page.
// Two globals we need for generating the unique ID
var idCntr = 0;
var controlStr = "0000000000"; // 10 digits long
function getUniqueID(o) {
if (!o.uniqueID) {
var base = idCntr++ + ""; // get string version of idCntr
o.uniqueID = controlStr.slice(0, controlStr.length - base.length) + base; // zero pad
}
return(o.uniqueID);
}
var myobj = {};
var a = new A();
var b = new B();
var c = new C();
myobj[getUniqueID(a) + getUniqueID(b) + getUniqueID(c)] = 42;
For you to fetch the same object back in the future, you'd have to combine the objects in the proper order again. If that wasn't easy, then you could make sure and always combine them in numeric order with the lowest numbers first so you always got a consistent order.

Categories

Resources