4

Just curious about jQuery/Javascript and referring to options within variables.

So, I wrote a little plugin that when I call "populate" will fill in some text. Very basic. Here's what I'm trying to do:

var foo = {
    msg1: "Hey",
    msg2: this.msg1 + "how",
    msg3: this.msg2 + "are",
    msg4: this.msg3 + "you",
    msg5: this.msg4 + "doing",
    msg6: this.msg5 + "today"
}

$("#bar").populate({text: foo.msg6});

So when the .populate plugin is called, #bar will get "Hey how are you doing today" added to it.

The populate plugin is hard to explain but trust me it's working great and not the issue. I'm just curious if this sort of organization of variables and options is possible, as it seems cleaner, more "semantic", and more organized to me than just a bunch of variables referring to other variables...

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
ggwicz
  • 568
  • 1
  • 5
  • 20
  • possible duplicate of [Self-references in object literal declarations](http://stackoverflow.com/questions/4616202/self-references-in-object-literal-declarations) – Felix Kling Nov 13 '11 at 15:57
  • I edited my answer to show what you could if you wanted to do this style :) It's at the bottom of my answer. – Ryan Nov 13 '11 at 16:22

2 Answers2

2

In an object definition like you have, this does not refer to the object itself so your object declaration will not do what you want.

In fact, in this sample code, you can see that this in that object definition is the window object which is what the javascript interpreter sets it to when there isn't some other value that it is supposed to have.

I don't understand why you're trying to do what you're doing (so I can't suggest better alternatives), but you could do end up with the desired foo object like this with an init() method:

var foo = {
    msg1: "Hey",
    init: function() {
        this.msg2 = this.msg1 + "how";
        this.msg3 = this.msg2 + "are";
        this.msg4 = this.msg3 + "you";
        this.msg5 = this.msg4 + "doing";
        this.msg6 = this.msg5 + "today";
    }
}

foo.init();
$("#bar").populate({text: foo.msg6});

or you could use this with a constructor function:

function Foo() {
    this.msg1 = "Hey";
    this.msg2 = this.msg1 + "how";
    this.msg3 = this.msg2 + "are";
    this.msg4 = this.msg3 + "you";
    this.msg5 = this.msg4 + "doing";
    this.msg6 = this.msg5 + "today";
}

var foo = new Foo();
$("#bar").populate({text: foo.msg6});
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Yes, I know. That's what I'm looking for. Is there a way to correctly map these? Sorry if the question wasn't very clear it's hard to explain! Thanks for the input man. – ggwicz Nov 13 '11 at 16:04
  • I added a couple options that will produce the desired `foo` object, though I'm thinking that there is likely a better way to accomplish your result (if I knew what you were really trying to do). – jfriend00 Nov 13 '11 at 16:19
2

this only has meaning in an execution context. When you define a function, a scope chain is created for that function that will be used whenever that function enters the current execution context. When that occurs, this will become defined (at runtime). See this for more details.

In your example, you are not defining any new scope chains, because you are not creating any methods on your object. Therefore, when you refer to this, you are referring to whatever this is whenever you make your foo object. Most likely, you are working in the global space, so this will be window (if you're in the browser), but it could be another object that has a function that you are currently executing in. For example:

    var myScopeObj = {
        myMethod: function() {
            var foo = {
                msg1: "Hey",
                msg2: this.msg1 + "how",
                msg3: this.msg2 + "are",
                msg4: this.msg3 + "you",
                msg5: this.msg4 + "doing",
                msg6: this.msg5 + "today"
            };
            var foo2 = foo.msg6;
        }
    };

There are a couple of possibilities in the above example:

    myScopeObj.myMethod();  // 'this' refers to myScopeObj

or

    var method = myScopeObj.myMethod;
    method();  // 'this' refers to window

or

    myScopeObj.myMethod.call(window);  // 'this' refers to window

What you could do is use make a constructor function for your object, and use this to map properties.

    function Foo() {
        this.msg1 = "Hey";
        this.msg2 = this.msg1 + "how";
        this.msg3 = this.msg2 + "are";
        this.msg4 = this.msg3 + "you";
        this.msg5 = this.msg4 + "doing";
        this.msg6 = this.msg5 + "today";
    };
    var foo = new Foo();
    $("#bar").populate({text: foo.msg6});
Ryan
  • 1,557
  • 9
  • 11
  • YES! I understood all the stuff you talked about at first. But the suggestion at the bottom works perfectly. Thanks you so much man! Awesome. You rock. I tried doing this earlier but forgot to have the `this.` in the actual variable declaration itself. Great tip and I really appreciate it. – ggwicz Nov 13 '11 at 16:24