JVG
JVG

Reputation: 21150

Javascript "Cannot read property 'length' of undefined" when checking a variable's length

I'm building a node scraper that uses cheerio to parse the DOM. This is more or a vanilla javascript question though. At one part of my scrape, I'm loading some content into a variable, then checking the variable's length, like so:

var theHref = $(obj.mainImg_select).attr('href');
if (theHref.length){
   // do stuff
} else {
  // do other stuff
}

This works just fine, until I came across a url for which $(obj.mainImg_select).attr('href') didn't exist. I assumed that my theHref.length check would account for this and skip through to the else: do other stuff statement, but instead I got:

TypeError: Cannot read property 'length' of undefined

What am I doing wrong here and how can I fix this?

Upvotes: 28

Views: 208507

Answers (7)

Spark
Spark

Reputation: 2487

You can simply check whether the element length is undefined or not just by using

var theHref = $(obj.mainImg_select).attr('href');
if (theHref){
   //get the length here if the element is not undefined
   elementLength = theHref.length
   // do stuff
} else {
   // do other stuff
}

Upvotes: 0

Peter Alfvin
Peter Alfvin

Reputation: 29399

As has been discussed elsewhere, the .length property reference is failing because theHref is undefined. However, be aware of any solution which involves comparing theHref to undefined, which is not a keyword in JavaScript and can be redefined.

For a full discussion of checking for undefined variables, see Detecting an undefined object property and the first answer in particular.

Upvotes: 1

Tadeck
Tadeck

Reputation: 137350

In addition to others' proposals, there is another option to handle that issue.

If your application should behave the same in case of lack of "href" attribute, as in case of it being empty, just replace this:

var theHref = $(obj.mainImg_select).attr('href');

with this:

var theHref = $(obj.mainImg_select).attr('href') || '';

which will treat empty string ('') as the default, if the attribute has not been found.

But it really depends, on how you want to handle undefined "href" attribute. This answer assumes you will want to handle it as if it was empty string.

Upvotes: 4

Benjamin Gruenbaum
Benjamin Gruenbaum

Reputation: 276306

Why?

You asked why it happens, let's see:

The official language specificaion dictates a call to the internal [[GetValue]] method. Your .attr returns undefined and you're trying to access its length.

If Type(V) is not Reference, return V.

This is true, since undefined is not a reference (alongside null, number, string and boolean)

Let base be the result of calling GetBase(V).

This gets the undefined part of myVar.length .

If IsUnresolvableReference(V), throw a ReferenceError exception.

This is not true, since it is resolvable and it resolves to undefined.

If IsPropertyReference(V), then

This happens since it's a property reference with the . syntax.

Now it tries to convert undefined to a function which results in a TypeError.

Upvotes: 6

JCOC611
JCOC611

Reputation: 19719

There's a difference between an empty string "" and an undefined variable. You should be checking whether or not theHref contains a defined string, rather than its lenght:

if(theHref){
   // ---
}

If you still want to check for the length, then do this:

if(theHref && theHref.length){
   // ...
}

Upvotes: 4

AlliterativeAlice
AlliterativeAlice

Reputation: 12577

If you aren't doing some kind of numeric comparison of the length property, it's better not to use it in the if statement, just do:

if(theHref){
   // do stuff
}else{
  // do other stuff
}

An empty (or undefined, as it is in this case) string will evaluate to false (just like a length of zero would.)

Upvotes: 1

Paul S.
Paul S.

Reputation: 66334

You can check that theHref is defined by checking against undefined.

if (undefined !== theHref && theHref.length) {
    // `theHref` is not undefined and has truthy property _length_
    // do stuff
} else {
    // do other stuff
}

If you want to also protect yourself against falsey values like null then check theHref is truthy, which is a little shorter

if (theHref && theHref.length) {
    // `theHref` is truthy and has truthy property _length_
}

Upvotes: 54

Related Questions