In my Javascript drag and drop build app, a variety of buildings can be built. The specific characteristics of these are all saved in one object, like
var buildings = {
house: ['#07DA21',12,12,0,20],
bank: ['#E7DFF2',16,16,0,3],
stadium: ['#000000',12,12,0,1],
townhall: ['#2082A8',20,8,0,1],
etcetera
}
So every building has a number of characteristics, like color, size, look which can be called as buildings[townhall][0] (referring to the color). The object changes as the user changes things. When clicking 'reset' however, the whole object should be reset to its initial settings again to start over, but I have no idea how to do that. For normal objects it is something like.
function building() {}
var building = new building();
delete building;
var building2 = new building();
You can easily delete and remake it, so the properties are reset. But my object is automatically initialized. Is there a way to turn my object into something that can be deleted and newly created, without making it very complicating, or a better way to store this information?
You can keep initial state as a prototype on an object.
var Base = function(){};
Base.prototype={a:1,b:2};
var c = new Base();
Now, you can change value of a or b to whatever you want.
To restore, just use
delete c.a or delete c.b
You will get your initial value back.
Hope this help.
Just use a copy/clone method to restore the original state
var defaults = {
foo: "bar"
};
var building;
function reset(){
building = {};
for (var key in defaults) {
if (defaults.hasOwnProperty(key){
building[key] = defaults[key];
}
}
}
Now you can just call reset() whenever you need to have building reset.
Related
I'm creating a game bot on telegram using node js.
Currently I'm facing a problem on shared variable (module.exports). I'm storing some of the data on the variable. And the problem is, the shared variable index always change. For example, please refer to my code below
var sharedVar = [];
createNewRoom = function(res) {
var index = sharedVar.length;
sharedVar.push({ groupId : res.chat.id }); // every time this function is invoked, it will create a new array inside sharedVar object
//Here comes the problem, it's about the index,
//because I'm using sharedVar to store arrays, then it will become a problem,
//if one array is deleted (the index will change)
var groupId = sharedVar[index].groupId; // it runs OK, if the structure of array doesn't change, but the structure of array change, the index will be a wrong number
}
As you can see, i got callGameData function, when i call it, it will show the last value of sharedVar, it's supposed to show the current room values / data.
As i mention on the code above, it's all about the dynamic array in the sharedVar object, the index will change dynamically
Any thoughts to tackle this kind of issue? I was thinking about using a new sharedVar object everytime the createNewRoom function is invoked, but the thing is, i have to use sharedVar in many different function, and i still can't figure it out on using that method.
EDIT
This is the second method
var gameData = undefined;
createNewRoom = function() {
this.gameData = new myConstructor([]); // it will instantiate a new object for each new room
}
myConstructor = function(data) {
var _data = data;
this.object = function() {
return _data;
}
}
callGameData = function() {
console.log(gameData);
}
An array is fundamentally the wrong data type to use if you want to keep indices the same even in the face of removing entries.
A better method is to use properties of an object. For example:
var roomCache = { nextId: 1 };
createNewRoom = function(res) {
roomCache[roomCache.nextId++] = {groupId: res.chat.id}; // Add a new object to the cache and increment the next ID
}
After adding two elements, you'll have the rooms in roomCache[1] and roomCache[2] - if you want to start at zero just change the original value of nextId. You can delete elements in this object and it won't shift any keys for any other objects - just use delete roomCache[1] for example to get rid of that entry.
This assumes there isn't a better ID out there to use for the cache - if, for example, it made more sense to lookup by res.chat.id you could certainly use that as the key into roomCache rather than an auto-incrementing number. Here's how it would look like to cache the values by the group ID instead:
var roomCache = { };
createNewRoom = function(res) {
roomCache[res.chat.id] = {groupId: res.chat.id}; // Assumes res.chat.id is not a duplicate of an already cached obhect
}
Now you could just look up by group ID in the cache.
Yes, it's definitely a problem cause you are not keeping track of the index in a logical way, you are relying on position on the array which it changes, you need something that doesn't change over time to keep consistency and supports deletition of the element without affecting the rest of the elements. You could use mongo to store the generated rooms by id or maybe redis or some kind of key value pair database to store that kind of information.
I trying to create Object-"Room" that have another objects-"Items".
I want that every "Item" will have a reference to "Room".
I just want to know what is the "Room" of some "Item"...
Here is the problem :
// Creating Room Class
function Room(name){
this.name = name;
this.items = [];
};
// function that creates item in a Room
Room.prototype.addItem = function(name){
var newItem = new Item(name, this);
this.items.push(newItem);
}
// Creating Items Class
function Item( name, room ){
this.name = name;
this.parentRoom = room; // HERE IS THE PROBLEM!!
// I need reference to my Room Class
};
// Lets create a Room
var myRoom = new Room('MyRoom');
// And lets add some items
myRoom.addItem("chair");
myRoom.addItem("bed");
myRoom.addItem("computer");
// Result -> you can see endless loop of Rooms in th Items
console.log( myRoom );
You can see in Inspect element endless loop.
Screenshot from Inspect element
Or what is the right way to create this thing?
I need to use "extends" method for "Item" Class to "Room"?
There is nothing wrong with un-ending object references when you inspect an javascript object. They essentially form a cyclic graph in object references.
However, this means that you get the benefits AND shortfalls of cyclic graphs.
When traversing/iterating through the graph, You need to be careful of infinite loops by keeping track of what objects you've already visited and do not visit them more than once. (i.e. by keeping track of a visited map)
function Todo(id, task, who, dueDate) {
this.id = id;
this.task = task;
this.who = who;
this.dueDate = dueDate;
this.done = false;
}
function updateDone(e) {
var spanClicked = e.target;
var id = spanClicked.parentElement.id;
var done = spanClicked.parentElement.done;
spanClicked.innerHTML = " ✔ ";
spanClicked.setAttribute("class", "done");
var key = "todos" + done;
localStorage.setItem(key, "true");
console.log(key);
}
In the second part of the last function I'm trying to change the value of the done property to "true" when the object I'm targeting is clicked for localStorage. What happens instead though is when I check localStorage in the web console the value of that object doesn't change and instead another object is added to the localStorage called "todosundefined: 'true'". I don't understand why when I click an object something is added to the localStorage as a separate, undefined object instead of changing the value of the object I clicked on. Any suggestions to modify it so that I change the done value of the object I click on for localStorage?
As mentioned in the comments above, there's no done property on DOM objects. I'm not entirely sure what you're trying to do, but in order to get the contents of the class attribute of a DOM object, you should use the className property. E.g:
var done = spanClicked.parentElement.className;
Then again, that doesn't appear to make any sense based on the code you posted. I'm assuming you want to use local storage to keep track which items on a list of todo's are done. In that case, wouldn't it be better to just store an array of id's of all items that are done (or the reverse)? You can't store an array directly in local storage, but you can use, for example, JSON.stringify() to get a string representation of the array that you can then store.
On page load I am creating two Javascript Objects, objDemo1 and objDemo1Backup where the latter is simply an exact copy of the first.
e.g.
objDemo1 {
sub_1 = { something: 123, somethingElse: 321 },
sub_2 = { something: 456, somethingElse: 654 }
}
I can modify the values in sub_ as well as add / delete new sub_'s but the only object I am editing is objDemo1. i.e. I never change objDemo1Backup
I have a reset button that when clicked will reset objDemo1 back to what it was when the page originally loaded (i.e. objDemo1 = objDemo1Backup). This is where I am having the issue..
How do I set objDemo1 to objDemo1Backup?
I have tried:
objDemo1 = objDemo1Backup;
and
objDemo1 = null;
var objDemo1 = objDemo1Backup;
...as well as similar variations but nothing seems to work.
Any ideas?
Note: I can confirm that at the point of resetting, objDemo1Backup is exactly the same as it was when I created it and objDemo1 has changed.
My code is definetly hitting the "reset" functionality, where I've tried the objDemo1 = objDemo1Backup... I just cannot figure out the syntax to replace the object.
I'm using angularjs and it took me some time to find out how to copy an object to another object. Normally you'll get an objects clone by calling clone or here in angular copy:
var targetObj = angular.copy(sourceObj);
This gives you a new cloned instance (with a new reference) of the source object. But a quick look into the docs reveals the second parameter of copy:
angular.copy(sourceObj, targetObj)
This way you can override a target object with the fields and methods of the source and also keep the target objects reference.
In JavaScript objects are passed by reference, never by value. So:
var objDemo, objDemoBackup;
objDemo = {
sub_1: "foo";
};
objDemoBackup = objDemo;
objDemo.sub_2 = "bar";
console.log(objDemoBackup.sub_2); // "bar"
To get a copy, you must use a copy function. JavaScript doesn't have one natively but here is a clone implementation: How do I correctly clone a JavaScript object?
var objDemo, objDemoBackup;
objDemo = {
sub_1: "foo";
};
objDemoBackup = clone(objDemo);
objDemo.sub_2 = "bar";
console.log(objDemoBackup.sub_2); // undefined
You can use Object.assign.
ObjectConstructor.assign(target: T, source: U): T & U
It takes up two parameters: target and source. When function completes, all internals of target object will be appended with source one.
I'm creating a page that will allow you to put multiple widgets on it, and some widgets can be duplicated on the page. So I need to understand the proper convention for creating an object instance on the fly.
// my bulb object
var bulb = {
state: 0
};
// programatically, hard-coded instance name of 'bulb1'
var bulb1 = new bulb();
$('button').click(function() {
// create another new bulb instance here with dynamic name
});
Or am I just going down the wrong path all together?
Thanks.
In JavaScript, we use functions (so called constructor functions) to instantiate object instances.
function Bulb() {
this.state = 0;
}
// one instance
var bulb1 = new Bulb();
// another instance
var bulb2 = new Bulb();
Your code doesn't work because your bulb is a regular object and not a function, so you cannot call it (which you are trying to do with bulb()).
Update: You could store your instances into an Array global variable:
var bulbs = [];
And then, whenever you create a new instance, just just make sure that you put it in the Array.
$('button').click(function() {
var bulb = new Bulb();
// do stuff with bulb
// make sure to store it into the Array
bulbs.push(bulb);
});
You can access the instances at any time like so:
bulbs[0] // the 1. instance
bulbs[1] // the 2. instance
// etc.