1

When executing the following code I get this error:

Uncaught TypeError: Cannot read property 'theTests' of undefined

$(document).ready(function() {

  var Example = {};

  Example = {
    settings: {
      theTests: $('.test'),
      firstTest: Example.settings.theTests[0]
    }
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>

But if I do it this way:

$(document).ready(function() {
  var Example = {};

  Example = {
    settings: {
      theTests: $('.test'),
      firstTest: $('.test')[0]
    },
    test: function() {
      var theTests = $('.test'),
        firstTest = theTests[0]
    }
  }

  Example.test();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>

Defining it inside the settings, or in the function, both of them work this way.

So my question is:

Why when defining the firstTest property based on the theTests property inside the settings doesn't work?

Edit:

Like suggested by duplicate I checked this question but I'm not looking for a way to do it. I'm trying to understand why it doesn't work.

Community
  • 1
  • 1
Joel Almeida
  • 7,939
  • 5
  • 25
  • 51

5 Answers5

2

I agree - it's not entirely a duplicate, since you're asking why - not how.

The reason you can't do this is given in the error - the object you're referring to isn't yet defined. Whilst you've assigned an empty object to Example, you're then immediately trying to set it to something else. Note that this is going to get evaluated from the innermost items first, ie it will be doing:

  • Set Example to be the result of:
    • Create an object that contains:
      • A settings property, which is the result of:
        • Create an object with two properties:
          • theTests: set to $(.test)
          • firstTest: set to Example.settings.theTests[0]

In the last line, note that we haven't yet assigned the settings object (we're still defining the properties on the object that will be assigned to settings), so it's undefined at the point when that line runs.

James Thorpe
  • 31,411
  • 5
  • 72
  • 93
  • Got it! It goes from the innermost items first. So the property won't be defined till the settings property and object are defined. Thanks. – Joel Almeida Jun 09 '15 at 15:45
0

you are trying to access a variable property that is not defined in that specific time.

Example.settings will be available AFTER the Example initalization.

var Example = {};
var theTests = $('.test');

Example = {
  settings: {
    theTests: theTests,
    firstTest: theTests[0]
  }
}

the second line of this code will:

  1. create the object
  2. assign the object to the variable
  • That won't work. `Example.settings` won't exist yet, on the `firstTest:` line. – Cerbrus Jun 09 '15 at 15:32
  • well, this is just an explanation WHY it won't work... ty for the downvote –  Jun 09 '15 at 15:32
  • I'd suggest adding a explanation on how to make it work, then. – Cerbrus Jun 09 '15 at 15:33
  • 1
    stop this, the OP already has an explanation how to make it work, he was clearly asking for the cause... –  Jun 09 '15 at 15:35
  • Okay, let me give you a suggestion: _"`Example.settings` will be available AFTER the `Example` initalization."_ <-- that's not true. It will only be available after you initialize `Example` _and_ assing a `settings` property to it. From your explanation, it looks like the code in your example should work, which it doesn't. I'm trying to help you improve your answer, here... – Cerbrus Jun 09 '15 at 15:37
0

In the first sample you are trying to access a property of Example before Example has fully been initialized.

You could do something along these lines instead

$(document).ready(function() {
  var tests = $('.test');
  var Example =  {
    settings: {
      theTests: tests,
      firstTest: tests[0]
    },
    test: function() {
      var theTests = $('.test'),
        firstTest = theTests[0]
    }
  }

  Example.test();
});
hooda
  • 105
  • 6
0

Try:

var Example = new function(){
    this.settings = {theTests:  $('.test')};
    this.settings.firstTest = this.settings.theTests[0];

    this.test = function(){
        console.log(this.settings.theTests);
        console.log(this.settings.firstTest)
    };
};

Example.test();
-1
 var Example = {};

  Example = {
    settings: {
      theTests: $('.test'),
      firstTest: Example.settings.theTests[0] //theTests does not exist
    }
  }




 Example = {
    settings: {
      theTests: $('.test'),
      firstTest: $('.test')[0]
    },
    test: function() {
      var theTests = $('.test'), // theTests has been defined
        firstTest = theTests[0]  // and used here
    }
  }
Himanshu Tanwar
  • 906
  • 6
  • 18