Looping through variable names as strings, and destroying them - javascript

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();
}
}

Related

Unwrap objects in array

I have an array of objects:
var Props = [booleanPoint, buttonPoint, checkboxPoint, datePoint, dialPoint, gaugePoint,
groupboxPoint, htmlPoint, imagePoint, livetextPoint, livetrendsPoint, permissionsPoint,
rangePoint, selectPoint, spectrumPoint];
Console log shows:
Edited:
I want to extract the properties inside each object. How do I do it?
To be clear I just want the first property in the array, so that I can do Props.booleanPoint, Props.buttonPoint etc.
You question is not very clear, but I guess you're trying to extract the first (and only) property from each object in the list, whose name you don't know.
If yes, consider this:
extracted = Props.map(function(obj) {
for(var p in obj)
return obj[p];
});
If you want to combine all properties into one big object, try this:
allProps = Object.assign.apply(null, Props)
I'm not sure exactly what result you're after, but the best solution is probably either a forEach or a map.
var properties = {};
Props.forEach(function(object) {
// update properties somehow based on object
});
or
var properties = Props.map(function(object) {
return [some property of object];
});
The first just runs some code on each entry in the array; the second returns a new array with the results of that code.
Otherwise, the classic for loop works too:
var properties = {};
for (var i = 0; i < Props.length; i++ {
// update properties somehow based on Props[i]
}

For loop is not working with json data

I'm trying to make a loop in javascript with the following code. It's getting length from json data.
The console.log(albums.data.length); line is working and returning 3. Why the loop is not working then?
The console.log(x); is not returning anything, even not blank line.
There is also no error in console.
function getBestPhoto(albums){
console.log(albums);
console.log(albums.data.length);
for(var x in albums.data.length){
console.log(x);
for(var y in albums.data[x].photos.length){
console.log(y);
}
}
}
I have tried another type of loop(for(var i = 0; i < blabla; i++)) but its not working too.
Edit:
I wanna use
for(var x = 0; x < albums.data.length; x++){
console.log(albums.data[x].photos.id);
}
instead of
for(var x in albums.data){
How can i do it?
You should remove .length from loops
function getBestPhoto(albums){
console.log(albums);
console.log(albums.data.length);
for(var i = 0; i < albums.data.length; i++){
var x = albums.data[i];
console.log(x);
for(var j = 0; j < albums.data[i].photos.length; j++){
var y = albums.data[i].photos[j];
console.log(y);
console.log(albums.data[i].photos[j].id);
}
}
}
The for-in loop is not for arrays, it is for iterating over properties/fields of an object. If albums.data is an array, you should use the forEach loop statement instead. If albums.data is an object, and you are trying to access its properties/fields/attributes, you can use the for-in construct.
If albums.data is an array, try:
albums.data.forEach(function(element, index) {
// Here you have access to each element (object) of the "albums.data" array
console.log(element.toString());
// You can also access each element's properties/fields if the element is an
// object.
// If the element is an array itself, you need to iterate over its elements
// in another inner foreach.
// Here we are accessing the "photos" property of each element - which itself
// is another array.
element.photos.forEach(function(photo, index) {
// Here you have access to the elements of the "photos" array
// Each element of the "photos" array is put in the photo variable.
// Assuming each element of the "photos" array is an object, you can access
// its properties, using the dot notation:
console.log("photo id=", photo.id);
// If the property name (e.g. "id") is not a valid javascript name
// (has some special symbols), use the bracket notation
console.log("photo URL=", photo["photo-url"]);
});
});
You can also use the lodash library for this (and many other neat functionalities).
If albums.data is an object, try:
for (var prop in albums.data) {
// Again, this construct is for accessing properties of an object
// (e.g. if albums.data is an object), not an array.
console.log("property name=" + prop + ", " + "property value=" +
albums.data[prop]);
}

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.

Dynamically create Instance fields for a JavaScript Object

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] = {};).

Why for-in iterates through array methods also?

on a page I use similar syntax to google analitycs code, to pass parameters to another script. I iterate through the array and try to construct query part of URL according to the parameters in the included script.
The problem is the following iterates through the javascript array objects methods also and mess up resulting queryString.
index.html:
<script>
var params = [];
params['first'] = '1';
params['second'] = '2';
(function() {
var vs = document.createElement('script');
vs.async = true; vs.type = 'text/javascript';
vs.src = 'http://my.domain.com/js/includedScript.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(vs, s);
})();
</script>
includedScript.js:
function(paramsArray) {
tmpArray = [];
for(i in paramsArray) {
tmpArray.push(i + '=' + escape(paramsArray[i]));
}
var queryString = tmpArray.join('&');
}(params);
I got (shortened):
queryString == 'first=1&second=2&push&$family=function%20%28%29%20%7B%0A%20%20%20%20return%20lower%3B%0A%7D&$constructor=function%20Array%28%29%20%7B%0A%20%20%20%20%5Bnative%20code%5D%0A%7D&pop=function%20pop%28%29%20%7B%0A%20%20%20%20%5Bnative%20code%5D%0A%7D&push=function%20push%28%29%20%7B%0A%'
I expect:
queryString == 'first=1&second=2'
It's strange, that on my localhost blank page it's working well. Could some other javascript on the index.html page collide with my code? How can I fix the collision by changing only my code (preferably only the includedScript.js file)?
Thanks in advance.
One small change:
var params = {}; // notice the difference here!
params['first'] = '1';
params['second'] = '2';
and another one here
for(i in paramsArray) {
if(paramsArray.hasOwnProperty(i)){
tmpArray.push(i + '=' + escape(paramsArray[i]));
}
}
JavaScript's Array should only be used with numeric indexes. For associative arrays use Object instead. Also to make sure that the properties you get were added by you and do not belong to the a prototype use hasOwnProperty.
See the documentation on mozilla.org for more info.
An array is an ordered set of values
associated with a single variable
name. Note that you shouldn't use it
as an associative array, use Object
instead.
Also you could read this article:
http://andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/
Note: The for ... in JavaScript construct has no connection with Array. Its purpose is to iterate over Object properties, not Array elements. In JavaScript properties also include methods.
Fun with JavaScript.
Try the following code and tell me if you're surprised:
var x = [];
x['one'] = 1;
x['one'] = 2;
alert(x.length);
then try this one:
Object.prototype.myProp = 123;
var x = {one: 1, two: 2}
for(var prop in x){
alert(x[prop]);
}
You want to do this
for (i in paramsArray) {
if (paramsArray.hasOwnProperty(i)) {
....
}
}
You should not use for..in to iterate through array elements. Things can be prototyped onto an object automatically to make use of DOM methods or programatically by other javascript on a page (like prototyping).
You should instead get a count of array elements using .length and a normal for loop.
var l = paramsArray.length;
for (var c = 0; c < l; c++) {
// do stuff
}
duncan's answer is correct, and that is because the for-in loop treats the paramsArray as an object, not an array.
And as Alin mentioned, use for (var i = 0; i < paramsArray.length; i++) for arrays.
This is usually an issue when looping using for...in, which is never really recommended.
A way around it is to use the .hasOwnProperty() method to ensure you are getting your own variables:
for (var k in foo) {
if (foo.hasOwnProperty(k)) {
// do something with foo[k]
}
}
Or as others have suggested, use a regular for loop:
for(var k = foo.lenght-1; k >= 0; --k) {
// do something with foo[k]
}
Which is more efficient (especially when reversed)
I love Array.forEach(). It takes a function as an argument. That function receives the element, index, and original list as arguments.
["a","b","c"].forEach(function(item, index, list)
{
console.log("the item at index " + index + " is " + item);
});
To make it compatible with older versions of IE, see here.

Categories

Resources