1

Possible Duplicate:
Javascript dynamic variable name

I have variables being passed from an onClick event to a JavaScript function. There are four variables in total: two that tell the direction and two that tell the speed change. I want the function to evaluate which direction was chosen (either h_ or v_, for horizontal and vertical) and then apply the necessary speed (either faster or slower).

Right now, I do this successfully by first evaluating the direction and calling a different changeSpeed function depending on the direction which was chosen.

What I would like to do is combine these functions. In the example, $(direction + "speed") is meant to become either h_speed or v_speed.

Is JavaScript equipped to do this? (sincerely, miguel)

var h_speed = 10;
var v_speed = 10;

function changeSpeed(speed, direction){
var direction = direction;
    switch (speed)
    {
        case 'slower':
                        $($direction + "speed") = $($direction + "speed")*2;
                        break;
        case 'faster':
                        $($direction + "speed") = $($direction + "speed")/2;
                        break;
    }
}

Here are two versions of my working code:

VERSION 1

var h_speed = 10;
var v_speed = 10;

function identifyDirection(speed, direction){
    switch (direction)
    {
        case 'vertical':
                        v_changeSpeed(speed);
                        break;
        case 'horizontal':
                        h_changeSpeed(speed);
                        break;
    }
}

function h_changeSpeed(speed){
    switch (speed)
    {
        case 'slower':
                    h_speed = h_speed*2;
                    break;
        case 'faster':
                    h_speed = h_speed/2;
                    break;
    }
}

function v_changeSpeed(speed){
    switch (speed)
{
        case 'slower':
                    v_speed = v_speed*2;
                    break;
        case 'faster':
                    v_speed = v_speed/2;
                    break;
    }
}

VERSION 2

/**
 * the changeSpeed functions' arguments
 * are placed directly in the function that
 * determines whether horizontal or vertical
 * speed is changing.
 *
 */

function changeSpeed(speed, direction){
    switch (direction)
{
    case 'vertical':
        switch (speed)
        {
            case 'slower':
                v_speed = v_speed*2;
                break;
            case 'faster':
                v_speed = v_speed/2;
                break;
        }
        break;
    case 'horizontal':
        switch (speed)
        {
            case 'slower':
                h_speed = h_speed*2;
                break;
            case 'faster':
                h_speed = h_speed/2;
                break;
        }
        break;
    }
}
Community
  • 1
  • 1
Miguel Valencia
  • 221
  • 3
  • 14
  • `if (direction == 'vertical') { v_speed *= speed == 'slower' ? 2 : 0.5; } else { h_speed *= speed == 'slower' ? 2 : 0.5; }` – zerkms Oct 01 '12 at 23:29
  • Thanks everyone! All these replies are excellent. zerkms, yours is the only code I've tried so far and it works. – Miguel Valencia Oct 30 '12 at 04:54

4 Answers4

1

Variables are made properties of a variable object. The only variable object you can access by name is the global variable object (this in a global context or window in a browser). So for global variables you could do:

function hSpeed() {...}

function vSpeed(){...}

// Set direction
var direction = 'h';

// Call related function
window[direction + 'Speed']();

However, you can't do that in a function execution context (because ECMA-262 explicitly denies access to function execution and variable objects), you need to make the "variable" a property of an object that you access the same way (i.e. using square bracket notation):

var lib = {};
var lib.hSpeed = function(){...};
var lib.vSpeed = function(){...};

// Set direction
var direction = 'h';

// Call related function
lib[direction + 'Speed']();
RobG
  • 142,382
  • 31
  • 172
  • 209
1

Put the 2 variables in a single object like:

var directions = {
  horizontal: 1,
  vertical: 1
}

Then you'd be able to take the direction out of the arguments and match the child of the object:

function changeSpeed(speed, direction) {
  //operate on diections[direction]
}

As far as changing the speed you could do a similar thing with functions in an object, but in your case I'd just suggest using another data structure since the logic doesn't change, only the parameter:

var speedFactor = {
  faster: 2,
  slower: .5
}

then you'd be able to do everything with:

function changeSpeed(speed, direction) {
  directions[direction] = directions[direction] * speedFactor[speed]
}
Matt Whipple
  • 7,034
  • 1
  • 23
  • 34
1

There are certainly better ways to do what you wanna achieve, but if you wanna have the same thing (note that you shouldn't use global variables, you can use function scoping to make them private, but that's another topic).

var speed = {
  h: 10,
  v: 10
};

function changeSpeed(speedChange, direction) {
  switch (speedChange) {
    case 'slower':
      speed[direction] *= 2;      
      break;
    case 'faster':
      speed[direction] /= 2;      
      break;
  }
}

Now you can change the speed by calling, for example:

changeSpeed("slower", "h");

and access that speed by speed.h or speed.v

Chris
  • 486
  • 2
  • 11
0

Okay...

Tricky but:

//Global namespace
var speeds = {};
speeds['h_speed'] = 10;
speeds['v_speed'] = 10;


function changeSpeed(speed, direction){
  var dir = direction.substring(0,1);
  var sp = (speed === 'slower') ? 0.5 : 2;
  //Still accessible from inside your function
  speeds[dir + '_speed'] = speeds[dir + '_speed'] * sp;
}

Will do the work.

red
  • 3,163
  • 1
  • 17
  • 16