5

Let's say I have two objects like

var a = {
    b: 1,
    c: this.b
};

And

var funcObj = {
    b : function() {
        return 1;
    },
    c: function() {
       console.log(return this.b())
    }
}

On logging these two like

console.log(a.c)//results undefined
console.log(funcObj.c()) //results 1

Why can't the first function use the this property but the second one can? I am really confused.

1
  • 1
    Because the first example shows an object literal, and does not have a function scope. Commented Feb 6, 2015 at 2:54

3 Answers 3

6

The answer depends on what this refers to in each context. In JavaScript, this is bound to whatever object was on the left of the dot (.) when the current function was called. If we're not in a function, things get a little hairier -- this is either the global window object or undefined, depending on the environment.

In your first example, the value of this is dependent on the surrounding context. As JavaScript builds your object a, it evaluates this.b. Whatever object this is currently bound to has no b property, so the c property is set to undefined.

In your second example, when you call funcObj.c() the this in the function gets bound to funcObj. So, when you ask for the b property, you get the b you defined above. The fact that funcObj.b is a function is actually irrelevant. The following would work just as well:

var funcObj = {
    b :  1,
    c: function() {
       return this.b
    }
}
Sign up to request clarification or add additional context in comments.

Comments

5

You cannot refer to other properties in the declaration as part of a Javascript literal declaration. So, in your Javascript literal declaration:

var a = {
    b: 1,
    c: this.b
};

this is not set to what you want and a has not yet been initialized yet so you can't refer to it either. There is simply no way to reach the other properties at the time of the literal declaration. This is a limitation of the current specification for Javascript. You could do this instead:

var a = {
    b: 1
};
a.c = a.b;

because a is fully formed at that point so you can then reference other properties in it.


Or, in modern browsers, you could even use a getter to get the "live" version of b like this (which isn't exactly the same functionality as you were asking for since it's a "live" version of b that will track it's value), but shows you another possibility:

var a = {
    b: 1,
    get c() {
         return b;
    }
};

console.log(a.c); //results 1

In your second example:

var funcObj = {
    b : function() {
        return 1;
    },
    c: function() {
       console.log(return this.b())
    }
}

console.log(funcObj.c()) //results 1

You are calling funcObj.c() and that will set the value of this inside of c to funcObj so thus you can reference other properties via this.


The main difference here is that this is not set to the object inside of Javascript literal definition (your first example), but this is set to the object when you invoke a method as in funcObj.c().

2 Comments

I think you meant to write a.c = a.b; in your second example.
@ChrisBouchard - yep. Fixed now.
0

I know this post is a bit old, but I came across it while trying to figure out how to solve a similar issue.

I was wanting to do something like:

const x = {
  a: 12,
  b: a + 1
}
console.log(x) //results undefined

(That's extremely simplified compared to what I was actually doing, but the principle is the same.)


My solution was to first create a function that would build the object I wanted, then pass in the primary value I was trying to act on (in this example, the value in 'a'):

function buildObj (val) {
  const response = {
    a: val,
    b: val + 1
  };
  return response;
}

And then:

const x = buildObj(12)

console.log(x) // results { a: 12, b: 13 }

Once x has been initialized, any subsequent attempt to access
x.a 

or

x.b

will return the values stored therein.


If a future searcher comes across this question because they're wanting to take an action on a value stored in a nested key within the same object, hopefully this will help.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.