//window["Fluent"]["Include"]
function setGlobalVariableByName(name,value)
{
var indexes = name.split(".");
var variable = null;
$.each(indexes, function()
{
if (variable == null){
variable = window[this];
}else{
variable = variable[this];
}
});
variable = value;
}
setGlobalVariableByName("Fluent.Include.JqueryPulse",true);
console.log(Fluent.Include.JqueryPulse) // prints false
this doesn't work, obviously. It would work if I just wanted to get the variable's value, but not for setting it.
window["Fluent"]["Include"]["JqueryPulse"] = true;
console.log(Fluent.Include.JqueryPulse) // prints true
how could I achieve something like this without using eval?
I'd need some way to programmatically add array indices to this, I'd guess
The following works, can you suggest a better way to code it in order to make it more DRY?
function setGlobalVariableByName(name,value)
{
var indices = name.split(".");
var parent;
$.each(indices, function(i)
{
if(i==indices.length-1){
if (!parent){
window[this] = value;
}else{
parent[this] = value;
}
}else if (!parent){
parent = window[this];
}else{
parent = variable[this];
}
});
}
setGlobalVariableByName : function(name, value)
{
var indices = name.split(".");
var last = indices.pop();
var parent;
$.each(indices, function(i)
{
if (!parent){
parent = window[this];
}else{
parent = variable[this];
}
});
if (!parent){
window[last] = value;
}else{
parent[last] = value;
}
}
2 Answers 2
You need to call
variable[this] = value
somehow. So you need to break the loop of the splited string before reching the last name, and then assign the value.
Ultimatively you need to call:
variable = window['Fluent']['Include']; // build this in a loop
variable['JqueryPulse'] = someValue; // then call this
Comments
Ultimately you're just building an object chain and setting the final item in the chain to a value. Also, I would add a check to ensure that items which are already objects do not get overwritten so that their existing properties don't get lost:
//bootstrap the object for demonstration purposes--not necessary to make code work
window.Fluent = {
Include: {
foo: 'bar', //don't want to lose this'
JqueryPulse: false //want to set this to true
}
};
//define function
function setGlobalItemByName( name, value )
{
var names,
finalName,
//no need to figure out if this should be assigned in the loop--assign it now
currentOp = window;
if( typeof name === 'string' && name !== '' )
{
names = name.split( '.' );
//no need to track where we are in the looping--just pull the last off and use it after
finalName = names.pop();
$.each( names, function()
{
//If the current item is not an object, make it so. If it is, just leave it alone and use it
if( typeof currentOp[this] !== 'object' || currentOp[this] === null )
{
currentOp[this] = {};
}
//move the reference for the next iteration
currentOp = currentOp[this];
} );
//object chain build complete, assign final value
currentOp[finalName] = value;
}
}
//use function
setGlobalItemByName( 'Fluent.Include.JqueryPulse', true );
//Check that Fluent.Include.foo did not get lost
console.log( Fluent.Include.foo );
//Check that Fluent.Include.JqueryPulse got set
console.log( Fluent.Include.JqueryPulse );
However, I would do it without using jQuery, even if you have jQuery available on the page. There is no need for the overhead of executing a function for each index.
//bootstrap the object for demonstration purposes--not necessary to make code work
window.Fluent = {
Include: {
foo: 'bar', //don't want to lose this'
JqueryPulse: false //want to set this to true
}
};
//define function
function setGlobalItemByName( name, value )
{
var names,
finalName,
indexCount,
currentIndex,
currentName,
//no need to figure out if this should be assigned in the loop--assign it now
currentOp = window;
if( typeof name === 'string' && name !== '' )
{
names = name.split( '.' );
//no need to track where we are in the looping--just pull the last off and use it after
finalName = names.pop();
indexCount = names.length;
for( currentIndex = 0; currentIndex < indexCount; currentIndex += 1 )
{
currentName = names[currentIndex];
//If the current item is not an object, make it so. If it is, just leave it alone and use it
if( typeof currentOp[currentName] !== 'object' || currentOp[currentName] === null )
{
currentOp[currentName] = {};
}
//move the reference for the next iteration
currentOp = currentOp[currentName];
}
//object chain build complete, assign final value
currentOp[finalName] = value;
}
}
//use function
setGlobalItemByName( 'Fluent.Include.JqueryPulse', true );
//Check that Fluent.Include.foo did not get lost
console.log( Fluent.Include.foo );
//Check that Fluent.Include.JqueryPulse got set
console.log( Fluent.Include.JqueryPulse );
Fluent.Include.JqueryPulseis already there, with false value, and I want to set it to true. but I don't need to initialize anything