Dynamically create Instance fields for a JavaScript Object - javascript

I have a dynamically-created list of strings called 'variables'. I need to use these strings as the instance variables for an array of JavaScript objects.
var objectsArr = [];
function obj(){};
for (var i=0; i<someNumberOfObjects; i++ ) {
...
objectsArr[i] = new Object();
for (var j=0; j<variables.length; j++) {
objectArr[i].b = 'something'; //<--this works, but...
//objectArr[i].variables[j] = 'something'; //<---this is what I want to do.
}
}
The commented-out line shows what I am trying to do.

You can use the bracket syntax to manipulate the property by name:
objectArr[i][variables[j]] = 'something';
In other words, get the object from objectArr at index i then find the field with name variables[j] and set the value of that field to 'something'.
In general terms, given object o:
var o = {};
You can set the property by name:
o['propertyName'] = 'value';
And access it in the usual way:
alert(o.propertyName);

Use the bracket notation. This will get it done:
var objectsArr = [], ii, jj;
function Obj() {}
for(ii = 0; ii < someNumberOfObjects; ii += 1) {
objectsArr[ii] = new Obj();
for (jj = 0; jj < variables.length; jj += 1) {
objectArr[ii][variables[jj]] = 'something';
}
}
A couple of additional notes:
Javascript doesn't have block scope, so you must have two separate loop variables.
By convention, constructor functions like Obj should begin with a capital letter to signify that they ought to be used with the new keyword. In this case though, unless you need the objects to have a non-Object prototype, you could just use a plain object literal (objectsArr[ii] = {};).

Related

Looping through variable names as strings, and destroying them

I have a list of variables (let's call them obj1, obj2, etc.). I would like to loop through all of them and, if they exist, destroy them. Obviously .destroy() is an external call.
Why does this work:
for (var i = 0; i < 10; i++) {
var obj = "obj" + i.toString();
if (window[obj]) {
window[obj].destroy();
}
}
But this doesn't:
var objs = [];
for (var i = 0; i < 10; i++) {
objs.push("obj" + i.toString());
if (objs[i]) {
objs[i].destroy(); //throws a TypeError
}
}
And is there a better solution that's more like the second, and doesn't involve accessing global scope via window? Please don't say eval().
objs.push("obj" + i.toString()); will push a string to the objs array. But strings don't have a .destroy property. In comparison, window["obj" + i.toString()] tries to reference a property on the window object by that name. (The value in that property, or undefined, will be pushed to objs)
It would be better to restructure your script so that rather than searching through the window object for variables of a certain name, you instead put all the related variables into an array at the start, so that you can then iterate through the array and destroy() them directly:
const objs = [
<someObj1>,
<someObj2>,
...
];
objs.forEach(obj => obj.destroy());
In the first example, you are using the string as the key to the object window, like this:
window.obj1
and then calling destroy on it.
The second example doesn't work because what you are pushing into the array is a string,
"obj" + i.toString()
You are calling destroy in the string itself since you created an array of strings. That's why you get the TypeError.
If you bother to use window object, why don't you clone it to a new object called container? That may work for you. Thanks
const container=window;
for (var i = 0; i < 10; i++) {
var obj = "obj" + i.toString();
if (container[obj]) {
container[obj].destroy();
}
}

Object.create to create an object with costructor

I am learning Javascript and I am a C++ programmer. I have tried creating an object with a constructor with object.create and here is the result:
var PlayGround ={
initGrid : function(N) {
this.N=N;
this.grid = new Array(N);
for (var i = 0; i < N; i++) {
this.grid[i] = new Array(N);
for (var j = 0; j < N; j++) {
this.grid[i][j] = false;
}
}
return true;
}
};
var PlayGround_property = {
N:{
value: 100,
writable:true
},
grid:{
value:null,
writable:true
}
}
var board= Object.create(PlayGround, PlayGround_property);
It works as I want: the object board contains the object grid, and now I can use the set and get keyword to define the behaviour of the = and () operator.
Anyway I have read around the web that the
this
keyword in Javascript is not safe and I want to be sure that it is referring always to the board object and not to the global window object. Is there a way or I am overthinking?
Other question, are there other ways to write object with a constructor (and maybe other members) in Javascript?
I want to be sure that [this] is referring always to the board object
A function's this is set either by how you call the function, or bind. So just make sure you call methods the right way. If you always call functions as methods of board, then this within the methods will always reference board.
If you are only going to have one instance of board, there doesn't seem much point in using a constructor. If you have multiple instances of board, then you want this to reference the particular instance that called the method so you don't want to fix this using bind.
Crockford just doesn't like the use of new, so encouraged Object.create, it fits his idea of how inheritance should work.
Your pattern could be rewritten to use a constructor something like:
function PlayGround (N) {
this.N = N;
this.grid = []; // Use array literal, it's less to type
for (var i = 0; i < N; i++) {
this.grid[i] = [];
for (var j = 0; j < N; j++) {
this.grid[i][j] = false; // Not sure why you bother with this
}
}
}
var board = new Playground(100);
I'm not exactly sure what you're doing, but that should be close. Note that javascipt is loosely typed, so only initialise variables and properties if you have something useful to assign. Variables are created with a value of undefined, Array properties are only created if you actually assign something to them, creating an array with length N does not create any indexes, e.g.
var arr = new Array(10);
console.log(arr.length); // 10
console.log(arr.hasOwnProperty(0)); // false

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.

string as object reference to object variable

var string = 'object.data.path';
That's a string that resembles a path to variable.
How can I return the corresponding variable from that string?
Something like transforming the string into return object.data.path;
The thing behind this is that the string could be much longer (deeper), like:
var string = 'object.data.path.original.result';
function GetPropertyByString(stringRepresentation) {
var properties = stringRepresentation.split("."),
myTempObject = window[properties[0]];
for (var i = 1, length = properties.length; i<length; i++) {
myTempObject = myTempObject[properties[i]];
}
return myTempObject;
}
alert(GetPropertyByString("object.data.path"));
this assumes that your first level object (in this case called object is global though.
Alternatively, although not recommended, you could use the eval function.
Assuming you don't want to just use eval you could try something like this:
function stringToObjRef(str) {
var keys = str.split('.'),
obj = window;
for (var i=0; i < keys.length; i++) {
if (keys[i] in obj)
obj = obj[keys[i]];
else
return;
}
return obj;
}
console.log(stringToObjRef('object.data.path.original.result'));
Uses a for loop to go one level down at a time, returning undefined if a particular key in the chain is undefined.

Access dynamically named JavaScript Objects?

I have a JS Object:
var testObj = new Object();
that has a property called volume1, so
testObj.volume1
has a value. How would I go about accessing that property by using something along the lines of
testObj.volume + "1"
To give it more context, the object actually has more properties, like
testObj.volume1, testObj.volume2 and testObj.volume3
and I want to access them using some iteration. I've tried playing with the window[] element, but have had not much success.
Thanks!
testObj["volume" + 1]
but you actually want an array here
testObj.volume = [...]
testObj.volume[1] = whatever
off topic it is considered better pratice to do
var testObj = {};
instead of
var testObj = new Object();
Use something in the fashion of testObj["volume" + "1"] ;)
The notations object.property and object["property"] are (almost) equivalent in javascript.
You can use for loop with in operation.
for(var PropName in testObj) {
var PropValue = testObj[PropName];
....
}
In case, you only want the property with the name started with 'value' only, you can also do this:
for(var PropName in testObj) {
if (!/^value[0-9]$/.match(PropName))
continue;
var PropValue = testObj[PropName];
....
}
OR if the number after the 'value' is always continuous you can just use a basic for loop.
for(var I = 0; I <= LastIndex; I++) {
var PropName = "value" + I;
var PropValue = testObj[PropName];
....
}
Hope this helps.

Categories

Resources