I am trying to be able to make a list of all instances of a Constructor, so I can check if all of these fit criteria in an IF statement
For Example:
function People() {
People.allInstances = [];
People.allInstances.push(this);
}
var Carry = new People();
var Gary = new People();
var Parry = new People();
console.log(People.allInstances);
However, I seem to lose all data except for the last instance I created. How can I make that list/array, and then use that array to test if any of them has a certain property?
The constructor runs every time an instance is constructed with it, but you only want to create an empty array once:
function People() {
People.allInstances.push(this);
}
People.allInstances = [];
Related
I want to create objects in a foreach loop:
I'm starting from this:
data.forEach(function (el) {
var dynamic_var = new Quill(el['editor']);
dynamic_var.on('text-change', logHtmlContent);})
But, dynamic_var is 'overwritten', and I want to remain unique.
I check some html elements, and for each one that I found I want to create a new Object, and execute the Object methods.
In my case the variable get a new object per each iteration, is not a new variable.
Is this what you were looking for?
var quillValueContainer = {};
// ...
data.forEach(function(el) {
quillValueContainer[el] = new Quill(el['editor']);
quillValueContainer[el].on('text-change', logHtmlContent);
});
This will only work if el is a string, or number. Seeing how you are using it like this: el['editor'], makes me thing it's an Object, in which case, you can instead use the indices of the elements.
var quillValueContainer = {}; // [] should also work for indexes
// ...
data.forEach(function(el, index) {
quillValueContainer[index] = new Quill(el['editor']);
quillValueContainer[index].on('text-change', logHtmlContent);
});
Also, I don't know if this is something you need to do, but you can check if the Quill Object has already been initialized and skipping a duplication if it has, by doing:
data.filter(function(el, index){ return !quillValueContainer[index]; }).foreach(...
Or
data.forEach(function(el, index) {
if(quillValueContainer[index]) return;
quillValueContainer[index] = new Quill(el['editor']);
quillValueContainer[index].on('text-change', logHtmlContent);
});
I'm adding three different objects to an ArrayList, but the list contains three copies of the last object I added.
For example:
for (Foo f : list) {
System.out.println(f.getValue());
}
Expected:
0
1
2
Actual:
2
2
2
What mistake have I made?
Note: this is designed to be a canonical Q&A for the numerous similar issues that arise on this site.
This problem has two typical causes:
Static fields used by the objects you stored in the list
Accidentally adding the same object to the list
Static Fields
If the objects in your list store data in static fields, each object in your list will appear to be the same because they hold the same values. Consider the class below:
public class Foo {
private static int value;
// ^^^^^^------------ - Here's the problem!
public Foo(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
In that example, there is only one int value which is shared between all instances of Foo because it is declared static. (See "Understanding Class Members" tutorial.)
If you add multiple Foo objects to a list using the code below, each instance will return 3 from a call to getValue():
for (int i = 0; i < 4; i++) {
list.add(new Foo(i));
}
The solution is simple - don't use the static keywords for fields in your class unless you actually want the values shared between every instance of that class.
Adding the Same Object
If you add a temporary variable to a list, you must create a new instance of the object you are adding, each time you loop. Consider the following erroneous code snippet:
List<Foo> list = new ArrayList<Foo>();
Foo tmp = new Foo();
for (int i = 0; i < 3; i++) {
tmp.setValue(i);
list.add(tmp);
}
Here, the tmp object was constructed outside the loop. As a result, the same object instance is being added to the list three times. The instance will hold the value 2, because that was the value passed during the last call to setValue().
To fix this, just move the object construction inside the loop:
List<Foo> list = new ArrayList<Foo>();
for (int i = 0; i < 3; i++) {
Foo tmp = new Foo(); // <-- fresh instance!
tmp.setValue(i);
list.add(tmp);
}
Your problem is with the type static which requires a new initialization every time a loop is iterated. If you are in a loop it is better to keep the concrete initialization inside the loop.
List<Object> objects = new ArrayList<>();
for (int i = 0; i < length_you_want; i++) {
SomeStaticClass myStaticObject = new SomeStaticClass();
myStaticObject.tag = i;
// Do stuff with myStaticObject
objects.add(myStaticClass);
}
Instead of:
List<Object> objects = new ArrayList<>();
SomeStaticClass myStaticObject = new SomeStaticClass();
for (int i = 0; i < length; i++) {
myStaticObject.tag = i;
// Do stuff with myStaticObject
objects.add(myStaticClass);
// This will duplicate the last item "length" times
}
Here tag is a variable in SomeStaticClass to check the validity of the above snippet; you can have some other implementation based on your use case.
Had the same trouble with the calendar instance.
Wrong code:
Calendar myCalendar = Calendar.getInstance();
for (int days = 0; days < daysPerWeek; days++) {
myCalendar.add(Calendar.DAY_OF_YEAR, 1);
// In the next line lies the error
Calendar newCal = myCalendar;
calendarList.add(newCal);
}
You have to create a NEW object of the calendar, which can be done with calendar.clone();
Calendar myCalendar = Calendar.getInstance();
for (int days = 0; days < daysPerWeek; days++) {
myCalendar.add(Calendar.DAY_OF_YEAR, 1);
// RIGHT WAY
Calendar newCal = (Calendar) myCalendar.clone();
calendarList.add(newCal);
}
Every time you add an object to an ArrayList, make sure you add a new object and not already used object. What is happening is that when you add the same 1 copy of object, that same object is added to different positions in an ArrayList. And when you make change to one, because the same copy is added over and over again, all the copies get affected.
For example,
Say you have an ArrayList like this:
ArrayList<Card> list = new ArrayList<Card>();
Card c = new Card();
Now if you add this Card c to list, it will be added no problem. It will be saved at location 0. But, when you save the same Card c in the list, it will be saved at location 1. So remember that you added same 1 object to two different locations in a list. Now if you make a change that Card object c, the objects in a list at location 0 and 1 will also reflect that change, because they are the same object.
One solution would be to make a constructor in Card class, that accepts another Card object. Then in that constructor, you can set the properties like this:
public Card(Card c){
this.property1 = c.getProperty1();
this.property2 = c.getProperty2();
... //add all the properties that you have in this class Card this way
}
And lets say you have the same 1 copy of Card, so at the time of adding a new object, you can do this:
list.add(new Card(nameOfTheCardObjectThatYouWantADifferentCopyOf));
It can also consequence of using the same reference instead of using a new one.
List<Foo> list = new ArrayList<Foo>();
setdata();
......
public void setdata(int i) {
Foo temp = new Foo();
tmp.setValue(i);
list.add(tmp);
}
Instead of:
List<Foo> list = new ArrayList<Foo>();
Foo temp = new Foo();
setdata();
......
public void setdata(int i) {
tmp.setValue(i);
list.add(tmp);
}
In jQuery and node.js environments, suppose you have the following:
var object = new Soda().drink("Coke").drink("Pepsi").drink("7Up");
Now let's say I have a list of N drinks and I don't want to hard code this programatically:
var object = new Soda().drink("D1").drink("D2").drink("Dn")...
What is the programatic approach to this problem if I need this to run sequentially and I can't use:
var object = new Soda();
for (var in j){
object.drink(i);
}
The line new Soda().drink("Coke").drink("Pepsi").drink("7Up") implies that .drink() returns a value that by itself is a valid object to call .drink() again with (either the original object, or some other object that encapsulates the modified state).
If that is the case, you could:
var currentDrinkable = object;
for(var drink in drinks) {
currentDrinkable = currentDrinkable.drink(drink)
}
I am trying to create a array with multiple fields in it.
For Example:
var person1 = {firstname:"Bob", lastname:"Smith", middlename:"happy"};
The problem I have is that I have 5000 variables I want to create so it would become:
var person1 = {firstname:"Bob", lastname:"Smith", middlename:"happy"};
var person2 = {firstname:"John", lastname:"Jones", middlename:"Long"};
..
var person5000 = {firstname:"Jim", lastname:"Cook", middlename:"Shorty"};
I think it would be silly to have 5000 lines of code to declare the variables.
So I want to be able to declare the variables on page load and then later assign the values to each.
I was trying to do this using the following code but I am guessing I am doing something wrong.
(I am loading some dummy data into the variables for testing)
<!DOCTYPE html>
<html>
<body>
<script>
var person = new Array (firstName:"", lastName:"", middleName:"");
for (var i = 0; i < 5000; ++i) {
person[i] = {firstName:"First"+i, lastName:"Last"+i, middlename:"Middle"+i};
}
alert(person1["firstName"]); // should alert First1
alert(person6["lastname"]); // should alert Last6
</script>
</body>
</html>
I was hoping to later in my code set the value using:
(I am pretty sure this code should work, but can't test it since I can't declare the variables correctly)
person1[firstname] = "Terry"; // should replace First1 with Terry
And then to receive a value using:
alert(person1[firstname]); // should alert Terry since it was changed
Anyone know what is wrong with my code since it's not returning the value ?
I am guessing I am declaring the variables wrong? If so how should I declare them ?
You appear to be confused about the difference between arrays and objects in Javascript. Arrays have numeric indexes, objects have named properties. So the initialization
new Array(firstName:"", lastName:"", middleName:"");
makes no sense. Not to mention, it's not valid Javascript syntax; property: value pairs can only be used in object literals, not in argument lists. If you use new Array(...), the argument should either be a single number, which is the size of the array to allocate, or a list of initial array element (with no property: prefixes. But the preferred way to create a new array is simply with the [] literal for an empty array; it will grow as necessary when you assign to it.
When you create an array, you don't get separate variables for each element. You access them using array[n] notation.
// Create an empty array
var person = [];
// Fill up the array
for (var i = 0; i < 5000; ++i) {
person[i] = {firstName:"First"+i, lastName:"Last"+i, middlename:"Middle"+i};
}
// Access elements
alert(person[1].firstName);
alert(person[6].middleName);
// Change elements
person[1].firstName = "Terry";
I believe this should work as you intended:
var person = new Array();
for (var i = 0; i < 5000; ++i) {
person[i] = {firstName:"First"+i, lastName:"Last"+i, middleName:"Middle"+i};
}
alert(person[1]["firstName"]);
alert(person[6]["lastName"]);
As pointed out by others, the person array is filled with objects, not arrays. You can use either property or associative array syntax with them.
I have the following example constructor:
function Loot(type, sellValue) {
this.type = type;
this.sellValue = sellValue;
}
I am looking to inherit these values into other objects, which are then pushed into an array, such as:
var inventory = [];
var stone = new Loot("craft", 20);
inventory.push(stone);
var hat = new Loot("clothing", 80);
inventory.push(hat);
var coal = new Loot("ore", 5);
inventory.push(coal);
var diamond = new Loot("ore", 400);
inventory.push(diamond);
console.log(inventory);
However, when I do so, my inventory reads as (Loot, Loot, Loot, Loot) and not the names given to the items, (stone, hat, coal, diamond).
How can I get around this? I imagine it would require some form of inheritance?
Thanks!
The variable names like stone do not mean anything to the object. They are a reference to your object, but not the data of the object.
So stone is simply a variable name for the same new Loot that was created.
You have only one Loot object in your example.
Also, if you look in your array with a debugger i will show the type of object (Loot). You need to expand that to see the values inside the object.
However, when I do so, my inventory reads as (Loot, Loot, Loot, Loot) and not the names given to the items, (stone, hat, coal, diamond).
You would need to iterate your inventory array and log the .type properties of all items:
for (var i=0; i<inventory.length; i++)
console.log(inventory[i].type);
Or you'd build right another array from the item types, which could most easily be accomplished with the map method:
var types = inventory.map(function(item) { return item.type; });
console.log(types);
The array can not have string keys.
Apparently you need to use an object to store these objects.
function Loot(type, sellValue){
this.type = type;
this.sellValue = sellValue;
}
var inventory = {};
var inventory2 = {};
var stone = new Loot("craft", 20);
var stone1 = new Loot("craft1", 30);
var stone2 = new Loot("craft2", 40);
//or as follows:
inventory2['stone'] = stone;
inventory2['stone1'] = stone1;
inventory2['stone2'] = stone2;
console.log(inventory); // Object {craft: Loot, craft1: Loot, craft2: Loot}
console.log(inventory2); // Object {stone: Loot, stone1: Loot, stone2: Loot}
http://jsbin.com/aNiXolo/5/edit