Samantha J T Star
Samantha J T Star

Reputation: 32848

startsWith is not a function getting called for no reason

I have this code:

for (var i = 0; i < value.length; i++) {
    if (typeof value[i].keyword == 'undefined' || value[i].keyword == null || value[i].keyword.startsWith(keyword)) {
        out.push(value[i]);
    }
}

I am getting an error message saying:

> TypeError: r[e].startsWith is not a function
>    at js-cf2cc68….min.js.gz:85
>    at fn (eval at compile (js-cf2cc68….min.js.gz:8), <anonymous>:4:1003)
>    at js-cf2cc68….min.js.gz:7
>    at p.$digest (js-cf2cc68….min.js.gz:7)
>    at p.$apply (js-cf2cc68….min.js.gz:7)
>    at HTMLBodyElement.<anonymous> (js-cf2cc68….min.js.gz:9)

How is this possible? I think I've accounted for everything.

Upvotes: 15

Views: 81644

Answers (6)

kevin ternet
kevin ternet

Reputation: 4612

value[i].keyword.startsWith("keyword") because the parameter of startsWith with must be a string.

So that will work better this way

for (var i = 0; i < value.length; i++) {
    if (typeof value[i].keyword == String(undefined) || value[i].keyword.startsWith("keyword"))
        out.push(value[i]);
}

Upvotes: 16

Yossi Shasho
Yossi Shasho

Reputation: 3640

I fixed this by calling value.toString().startsWith(...)

Upvotes: 2

Proxxa
Proxxa

Reputation: 11

There's a definitely obvious problem.

(This is entirely for people who have a problem like this one, but they don't really understand)

Of course, just like many others are saying, it's in the type. If you don't know what types are (You likely do if you know this advanced type of stuff, but just in case!), its simple. The primitive types are True/False, Undefined/Null, Numbers, and Strings, any string type that is not empty or numbers not equal to 0 resulting in being true if put through an if statement on their own. Now that we've got that out of the way, its time to talk about startsWith(). If you run console.log("Hey VSauce, Michael here.".startsWith("Hey")), it would output true to the console due to how the string starts out with a string. If you run console.log(1234.startsWith(1)), would occur with a TypeError due to startsWith() requiring a string. We can tell this is a TypeError from the error output. So, the problem above (that was already answered) was that the variable keyword wasn't being defined as a string, but rather any other variable, and needed to be defined as a string

Upvotes: 1

Samra
Samra

Reputation: 2013

Found a useful article on this topic

The three approaches for converting to string are:

  1. value.toString()
  2. "" + value
  3. String(value)

The point to note here is that approach # 1 doesn’t work if the value is null or undefined.

In my case, approach # 2 for some reason did not work either so the best option would be String(value)

var col = "rt_" + rows[i]["results"][r].ResultTypeID.substring(1); //did not work

var col = "rt_" + String(rows[i]["results"][r].ResultTypeID).substring(1);

Upvotes: 6

Thomas
Thomas

Reputation: 12677

Is there a way that I can check if it's a string rather than have it error out?

checking the type?

var out = values.filter(v => v.keyword == null || typeof v.keyword === "string" && v.keyword.startsWith( keyword ));

or simply enforcing the type

var out = values.filter(v => v.keyword == null || String(v.keyword).startsWith( keyword ));

or if you use desctructuring, you can use even this:

var out = values.filter({keyword: v}) => v == null || String(v).startsWith( keyword ));

I'd reccomend you to use the Array-methods instead of manually writing loops.

  • Imo. it is a better description of your intent (good for scanning over code).

  • If this is a hot path (it's called often) the JS-optimizer can take advantage of knowing, that youre'just filtering, and optimize the code. Maybe by skipping the lots of integrity-checks for the Array it performs during your loop.

  • And if this is not a hot-path, the performance-impact of calling a function a few times will even be hard to measure, in JS.

Upvotes: 4

Anton Bessonov
Anton Bessonov

Reputation: 9813

I assume value[i].keyword is a string. String.prototype.startWith is not supported in older browsers. See browser support.

To use it in older browsers, you can use one of existing polyfills. See also answers from How to check if a string “StartsWith” another string?

Upvotes: 1

Related Questions