4

The jQuery version that we are using is 1.10.2.

On a particular screen we are getting a DOM element using jQuery and try to get its offset() object. Sometimes the object might not be displayed and, according to the jQuery documentation, when this is the case offset() is not supported.

This is all fine but, what's really making my head spin is why if I try to check if the offset() object is different than undefined the code always goes inside the condition?

My code (simplified because of non-disclosure agreements) is like follows:

var isCurrent = $('.detail-current[value=\'true\']:first');
if (isCurrent != 'undefined') {
   var button = isCurrent.closest('.batch-item').find('.batch-item-top').find('input[name=\'edit\']');

   var myOffsetTop = 0;
   if(button.offset() != 'undefined')
      myOffsetTop = button.offset().top;

   $('html, body').animate({
      scrollTop: myOffsetTop - 50
   });
}

When I debug this using IE development tools I see on the console that button.offset() is undefined but button.offset() != undefined returns true!!

Does anybody know why this happens and how we could best handle it?

Thank you.

Zevi Sternlicht
  • 5,399
  • 19
  • 31
Sergio Romero
  • 6,477
  • 11
  • 41
  • 71

3 Answers3

10

You are checking if it is a string called undefined, not whether it is actually undefined or not.

if (typeof something === "undefined") 
  alert("something is undefined");

To check whether it is NULL or not, use if (null === something)

Zevi Sternlicht
  • 5,399
  • 19
  • 31
  • 1
    Shouldn't use `typeof` like this to test for `undefined`. It causes too many bugs, like that in the question. –  Jul 09 '13 at 20:17
  • @CrazyTrain not sure I agree, what bug does it cause? http://stackoverflow.com/a/416327/1624960 – Zevi Sternlicht Jul 09 '13 at 20:18
  • 1
    What bug? The one in the question. It's a guard that causes more code problems than the problem it's supposed to solve. Better is to simply make sure the global `undefined` is never redefined, which is impossible in modern browsers anyway. –  Jul 09 '13 at 20:20
  • 1
    It also always seems a bit hacky to be comparing type names as strings. The whole point of the `undefined` keyword is so you don't have to do that. – jcsanyi Jul 09 '13 at 20:29
  • This answer also does not address the fact that the first check will never work as expected, because jQuery does not return `undefined` when no matching elements are found. – jcsanyi Jul 09 '13 at 20:31
  • @CrazyTrain its a robust way to test undefined. Wrong will be if `if (typeof something === undefined)` , undefined is not string – Grijesh Chauhan Jul 09 '13 at 20:38
  • 2
    @jcsanyi No problem to check it against string `"undefined"`, simply `undefined` may cause bug. [read here](http://stackoverflow.com/questions/27509/detecting-an-undefined-object-property-in-javascript/3550319#3550319) – Grijesh Chauhan Jul 09 '13 at 20:39
  • @GrijeshChauhan: It causes far more bugs than it prevents. It's a poor solution. For all the code that I've written and reviewed, I've *never* seen someone redefine `undefined`, but if seen *many* times people get `typeof foo === "undefined"` wrong in one way or another. –  Jul 09 '13 at 20:49
  • ...and @jcsanyi is correct. Any way of checking for `undefined` doesn't properly solve the issue in the question. –  Jul 09 '13 at 20:50
  • @CrazyTrain checking for `undefined` will be correct in the way Jcsanyi doing (but not with typeof) that the reason I voted Jcsanyi's answer before this answer. – Grijesh Chauhan Jul 09 '13 at 20:52
  • 1
    @GrijeshChauhan: The point is that the `$` function doesn't return `undefined`, so the condition will always pass. jcsanyi's solution to test the `.length` is correct. –  Jul 09 '13 at 20:54
5

You need to check against the keyword undefined, not the string "undefined".

A check for undefined should look like this:

if (someVar !== undefined)

However - if jQuery doesn't find something - it does not return undefined. It returns a jQuery object representing an empty set.

Because of that, your first check should use the .length property, like this:

if (isCurrent.length > 0)

offset(), on the other hand does return undefined if there's nothing defined - so your second check should look like this:

if (button.offset() !== undefined)
jcsanyi
  • 8,133
  • 2
  • 29
  • 52
0

You're not testing for undefined, it should be

if(typeof button.offset() !== 'undefined')
Kevin B
  • 94,570
  • 16
  • 163
  • 180
Robert Hoffmann
  • 2,366
  • 19
  • 29