0

I have the following function:

function get_stoplight_color(count, position) {
    console.log(count + ', ' + position);

    var colors = {
        'QB' : ['#8b3a25', '#ceca63', '#68c24c', '#68c24c', '#68c24c'],
        'RB' : ['#8b3a25', '#ceca63', '#ceca63', '#ceca63', '#68c24c'],
        'WR' : ['#8b3a25', '#ceca63', '#ceca63', '#ceca63', '#ceca63'],
        'TE' : ['#8b3a25', '#ceca63', '#68c24c', '#68c24c', '#68c24c'],
        'DST' : ['#8b3a25', '#68c24c', '#68c24c', '#68c24c', '#68c24c'],
        'K' : ['#8b3a25', '#68c24c', '#68c24c', '#68c24c', '#68c24c']
    };

    console.log(colors);
    if (count <= 4) return colors.position[count];
    else return '#68c24c';
}

As you can see, I've logged a couple vars out to the console, and they appear to be just fine there. However, at runtime I'm getting the following error:

Uncaught TypeError: Cannot read property '4' of undefined

(That's when count = 4.)

Again, the object colors clearly exists, because console.log(colors) outputs:

Object {QB: Array[5], RB: Array[5], WR: Array[5], TE: Array[5], DST: Array[5]…}

So I would expect colors.position[count] to return #68c24c when position = 'QB' and count = 4.

Why is the object still returning undefined in this case? Thank you, and I'll provide more details if necessary (I've provided everything I've thought of up front).

2 Answers 2

4

The expression colors.position[count] uses a position property on colors. I think you meant colors[position][count], which will look up the property named by the variable position (e.g., QB) on colors instead, and then look up the property named by count (e.g., 4) on the result.

If there's any chance position may not be defined, I would change that bit at the end slightly. Instead of:

if (count <= 4) return colors.position[count];
else return '#68c24c';

perhaps:

return (colors[position] && colors[position][count]) || '#68c24c';

...which takes advantage of JavaScript's curiously-powerful || and && operators.


Re your comment below:

Wow, OK, that worked, but I'm not sure how? I didn't even try that since I view [] operands as indexes of an array, while colors is an object (not an array).

In JavaScript (unlike many languages), you can access an object property in two ways:

  1. Using dot notation and a literal property name, e.g. obj.foo (provided the property name is a valid identifier name), or

  2. Using bracketed notation and a string property name, e.g. obj["foo"] (and in this case, the property name can be just about anything, it doesn't have to be a valid identifier name).

In the second case, the string can be from any expression, including a variable lookup. So all of these refer to obj.foo:

obj.foo
obj["foo"]
obj["f" + "o" + "o"]
var x = "o";
obj["f" + x + x]

...and in fact, this is is the same notation you use when dealing with arrays, because in JavaScript, arrays aren't really arrays, they're just objects.

Sign up to request clarification or add additional context in comments.

3 Comments

Wow, OK, that worked, but I'm not sure how? I didn't even try that since I view [] operands as indexes of an array, while colors is an object (not an array). Guess I have more to learn about objects. Thanks!
@praguian: Ah, no, in JavaScript [] is more powerful than that. :-) I've updated the answer to explain that a bit more. [] is very useful with objects (and arrays are just objects).
Thanks! Very informative and helpful. I wish I could upvote your answer more than once.
4

If position is a variable then you should say colors[position][count]. Otherwise JS will think position is a property of colors and not resolve its value.

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.