2

I'm working on a JavaScript object and there are a lot of variables declared inside it. What I want to do is reference to another child of the parent object. Given the following object :

var clusters = {

    auxiliars: {
        environment         : "Development",
        local_storage_key   : "Cluster",

        iqns_class          : ".iqn",
        iqn                 : this.iqns_class.parent(),

        viewport            : $(window),

        viewport_width      : this.viewport.width(),
        viewport_height     : this.viewport.height(),

        plugin              : {
            containerID : "",
            first       : false,
            previous    : false,
            next        : false,
            last        : false,
            startPage   : 1,
            perPage     : 6,
            midRange    : 6,
            startRange  : 1,
            endRange    : 1,
            keyBrowse   : false,
            scrollBrowse: false,
            pause       : 0,
            clickStop   : true,
            delay       : 50,
            direction   : "auto",
            animation   : "fadeIn",
            links       : "title",
            fallback    : 1000,
            minHeight   : true,
            callback    : function(pages, items) {}
        }
    },

    set_local_storage_data: function(data_val) {
        return localStorage.setItem(auxiliars.local_storage_key, data_val);
    },

    get_local_storage_data: function() {
        return +(localStorage.getItem(auxiliars.local_storage_key) || 1);
    },

    set_environment: function(environment) {
        if(auxiliars.environment == "Development") {
            less.env = "development";
            less.watch();
        }
    },

    shop_iqns_selected_class: function() {
        if (auxiliars.viewport_width < 980) {
            $(auxiliars.iqns_class).each(function(index, element) {
                var element = $(element);
                $(auxiliars.iqn).on('click', function() {
                    if (element.hasClass('selected')) {
                        element.removeClass('selected');
                    } else {
                        element.addClass('selected');
                    }
                });
            });
        }
    },

    initiate_plugin: function(plugin_navigation, plugin_options) {
        var options = $.extend({}, auxiliars.plugin, plugin_options);
        return $(plugin_navigation).jPages(options);
    }

}

You will notice this.viewport.width(), by that I want to point to the viewport variable declared in the same auxiliars object. Obviously I'm getting an error, but how can I point to that child value of the same object ?

Roland
  • 9,321
  • 17
  • 79
  • 135
  • 1
    Next time please try to summarize your code example to the minimal expression that reproduces the issue. – fguillen May 14 '12 at 13:11

3 Answers3

3

There's no way to do that in JavaScript. That is, there's no way to reference the "in-progress" element being built with an object literal.

You can however reference the properties (and sub-properties) in a subsequent assignment statement.

var clusters = {

    auxiliars: {
        environment         : "Development",
        local_storage_key   : "Cluster",

        iqns_class          : ".iqn",
        iqn                 : this.iqns_class.parent(),

        viewport            : $(window),
        // ...

clusters.auxiliars.viewport_width = clusters.auxiliars.viewport.width();
clusters.auxiliars.viewport_height = clusters.auxiliars.viewport.height();
Pointy
  • 405,095
  • 59
  • 585
  • 614
  • Oh, so I have no other way but declaring some other variables outside the object and calling them inside the object after the object has been declared. – Roland May 14 '12 at 12:58
  • Yes. There are various ways of doing it, but basically the problem is that there's no "name" for an object that is under construction. – Pointy May 14 '12 at 13:00
  • That sucks :| Because using Prototypes it is possible, but it causes me some problems with some jQuery plugins, and I had to go with objects. – Roland May 14 '12 at 13:03
3

I think the simplest way is to transform your autoreferent attributes in methods:

var clusters = {
  auxiliars: {
    viewport        : $(window),
    viewport_width  : function(){ return this.viewport.width() },
  }
}

clusters.auxiliars.viewport_width();

Check the jsFiddle

fguillen
  • 36,125
  • 23
  • 149
  • 210
  • Oh, that's definitely much more elegant :) – Roland May 14 '12 at 13:09
  • But per say how would I go when trying to use the same principle in here: `set_local_storage_data: function(data_val) { return localStorage.setItem(auxiliars.local_storage_key, data_val); }` ? – Roland May 14 '12 at 13:13
  • 3
    And making `viewport_width` a function will allow it to reflect changes in the return value of `viewport.width()`. Using a plain variable just gets the iniital width, so it would be out of sync if the width ever changes. (Not sure if that's an issue for your case, anyway, though.) – apsillers May 14 '12 at 13:15
  • Yes I know that, that the plan since you use different devices you have different widths and I need to check that, but you won't resize anything while using a tablet per say ( that if you don't rotate the device in which case it switches from portrait to landscape or reverse ). I'm saying this because I cannot keep applying javascript functions live while the width keeps changing, what if you decide to resize your window ? That will probably make the browser crash – Roland May 14 '12 at 13:20
1

You can't reference part of a new object literal in other parts of the same object literal. You can instead build those parts in separate statements:

var clusters = ...;
clusters.auxiliars.viewport_height = clusters.auxiliars.viewport.height();
clusters.auxiliars.viewport_width = clusters.auxiliars.viewport.width();

It's less elegent, but I think it's the only way to do it.

apsillers
  • 112,806
  • 17
  • 235
  • 239