4

I created an object literal in JS, but wanna to access a property without being in a function. Whenever I try, I don't get any results or it returns null.

JS:

var settings = {
        prev: '#prev',
        next: '#next',
        slides: '#slides',
        crslContainer: '#carousel',

        //I'm trying to access the 'slides' by using 'this.slides'
        inDent: $(this.slides).find('li').outerWidth(),
        fx: 'rotate',

        myFunction: function () {
          console.log(settings.inDent); //This shows null in the console, why??
        }
    }

In the code above I'm trying to access slides by using this.slides, all inside the same object, but the console says null. But when I do the method, inDent: $('#slides').find('li').outerWidth(), then it works. Why is that? I assumed it's the same as using those properties inside a function by using this keyword, apparently it's not the case. I just wanna pass the value of that object property , i.e. a string, to another property that's not a function.

Many thanks

Shaoz
  • 10,573
  • 26
  • 72
  • 100

3 Answers3

9

You can't refer to the "object being defined" in an object literal. That is, there's no way to have the value expression for a property of the under-construction object refer to the object itself in order to access another (presumably, already-defined) property.

You can however add a property to the object after it's been defined.

 var obj = { a: 0 };
 obj.b = (obj.a ? 1 : 2);

Or in your case:

 var settings = { ... };
 settings.inDent = ($(settings.slides).find('li').outerWidth());
Pointy
  • 405,095
  • 59
  • 585
  • 614
  • Many thanks for your answer. your method works. They should have made object literals a bit more flexible, so we can transfer variables anywhere we want like constructors but nothing is perfect in life... lol. thanks though – Shaoz Mar 26 '12 at 14:29
0

You need to use

this.inDent

The inDent field would be accessed via settings.inDent only outside of the settings object definition

scibuff
  • 13,377
  • 2
  • 27
  • 30
  • Many thanks for your answer @scibuff. I know I can use this.inDent but I can only do that inside a function. – Shaoz Mar 26 '12 at 14:25
  • 1
    This does not answer the question as they can't successfully use `this` or `this.inDent` inside the static declaration of the `settings` object. – jfriend00 Mar 26 '12 at 15:19
  • @jfriend00 of course you can use `this` just try it - `var s = { x: 'foo', y:function(){ console.log(this.x); }}; s.y(); // outputs 'foo'` – scibuff Mar 26 '12 at 15:29
  • 1
    @scibuff - that's inside a function. That's explicitly NOT what the OP is asking about. The OP is asking about the line they have like this: `inDent: $(this.slides).find('li').outerWidth(),` where one static declaration refers to another which is not possible. – jfriend00 Mar 26 '12 at 15:53
  • @scibuff: What you've just demonstrate with the `console.log`, I know about that already, i.e. using `this` inside a function. But I wanna be able to use `this` when I'm declaring variables. I know I can use `this` when inside a function but my question is what about using `this` like that: `var obj = { foo: '#id', bar: $(this.foo) };` here I want `foo` value inside `bar`, that's my question but the answer is we cannot do tis techniques in object literals. But still thanks for your effort, I appreciate very much. I'm still learning... – Shaoz Mar 26 '12 at 15:56
  • @Shaoz, sorry I think I misunderstood your question originally - but you can still do what you wanna do - read my answer above (about closures) – scibuff Mar 26 '12 at 16:22
0

Use closures, e.g

var settings = function(){
    var private = {};
    private.slides = '#slides';

    var public = {}
    public.inDent = ($(private.slides).find('li').outerWidth());
    public.doSomething = function(){
        console.log( public.inDent );
    }

    return public;
}();

The advantage of this is also that it gives you "encapsulation" for free

BTW, you shouldn't rely on anything that is publicly available, because, well, it can be changed, e.g. settings.inDent = null and then settings.doSomething() may no longer function correctly. What correct way to do it is the following

...
private.inDent = ($(settings.slides).find('li').outerWidth());

public.inDent = private.inDent;
public.doSomething = function(){
    console.log( private.inDent );
}

i.e. make the inDent value "read only" (in a sense that nothing outside of the settings object can actually change the internal implementation of private.inDent); as long as you always use private.inDent from within settings you're safe because even if someone does settings.inDent = null, the settings.doSomething(); will still function properly

scibuff
  • 13,377
  • 2
  • 27
  • 30