3
//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;
    }
}
3
  • they do actually exist, I just explained it like that for the question. the variable Fluent.Include.JqueryPulse is already there, with false value, and I want to set it to true. but I don't need to initialize anything Commented Oct 25, 2011 at 13:14
  • Here's a different version: jsfiddle.net/3WtJM/2 Commented Oct 25, 2011 at 13:39
  • @Nico - you said, "the variable Fluent.Include.JqueryPulse is already there..." Be careful that you don't stomp on objects which already exist in that chain as you will lose their properties. See my answer and the code comments to avoid that problem. Commented Oct 25, 2011 at 13:46

2 Answers 2

5

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
Sign up to request clarification or add additional context in comments.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.