164

The following code can be run without a problem in Chrome, but throws the following error in Internet Explorer 11.

Object doesn't support property or method 'startsWith'

I am storing the element's ID in a variable. What is the issue?

function changeClass(elId) {
  var array = document.getElementsByTagName('td');
  
  for (var a = 0; a < array.length; a++) {
    var str = array[a].id;
    
    if (str.startsWith('REP')) {
      if (str == elId) {
        array[a].style.backgroundColor = "Blue";
        array[a].style.color = "white";
      } else {
        array[a].style.backgroundColor = "";
        array[a].style.color = "";
      }
    } else if (str.startsWith('D')) {
      if (str == elId) {
        array[a].style.backgroundColor = "Blue";
        array[a].style.color = "white";
      } else {
        array[a].style.backgroundColor = "";
        array[a].style.color = "";
      }
    }
  }
}
<table>
  <tr>
    <td id="REP1" onclick="changeClass('REP1');">REPS</td>
    <td id="td1">&nbsp;</td>
  </tr>
  <tr>
    <td id="td1">&nbsp;</td>
    <td id="D1" onclick="changeClass('D1');">Doors</td>
  </tr>
  <tr>
    <td id="td1">&nbsp;</td>
    <td id="D12" onclick="changeClass('D12');">Doors</td>
  </tr>
</table>
Kerem
  • 11,377
  • 5
  • 59
  • 58
Bhushan Dhamdhere
  • 1,677
  • 2
  • 10
  • 8
  • 10
    You'll likely need to use `str.indexOf("REP") == 0` for IE instead. – Grant Thomas Jun 16 '15 at 12:13
  • 1
    ES6 is not yet a standard https://kangax.github.io/compat-table/es6/ There is an ES6 shim library to help the transition https://github.com/paulmillr/es6-shim/ Just like for ES5 (including not everything is shimmable) – Xotic750 Jun 16 '15 at 12:13

8 Answers8

333

String.prototype.startsWith is a standard method in the most recent version of JavaScript, ES6.

Looking at the compatibility table below, we can see that it is supported on all current major platforms, except versions of Internet Explorer.

╔═══════════════╦════════╦═════════╦═══════╦═══════════════════╦═══════╦════════╗
║    Feature    ║ Chrome ║ Firefox ║ Edge  ║ Internet Explorer ║ Opera ║ Safari ║
╠═══════════════╬════════╬═════════╬═══════╬═══════════════════╬═══════╬════════╣
║ Basic Support ║    41+ ║     17+ ║ (Yes) ║ No Support        ║    28 ║      9 ║
╚═══════════════╩════════╩═════════╩═══════╩═══════════════════╩═══════╩════════╝

You'll need to implement .startsWith yourself. Here is the polyfill:

if (!String.prototype.startsWith) {
  String.prototype.startsWith = function(searchString, position) {
    position = position || 0;
    return this.indexOf(searchString, position) === position;
  };
}
Oka
  • 23,367
  • 6
  • 42
  • 53
  • 3
    there are another implementation at [MDN web docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith#Polyfill) `String.prototype.startsWith = function(search, pos) { return this.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search; };` – oCcSking May 03 '18 at 07:27
  • 1
    I tend to the first implementation as given by @Oka. Just as an additional refinement one might test for "position" being really numeric: position = !isNaN(parseInt(position)) ? position : 0; – ErnestV Jan 15 '19 at 11:16
40

text.indexOf("newString") is the best method instead of startsWith.

Example:

var text = "Format";
if(text.indexOf("Format") == 0) {
    alert(text + " = Format");
} else {
    alert(text + " != Format");
}
MSeifert
  • 145,886
  • 38
  • 333
  • 352
Jona
  • 517
  • 4
  • 3
  • Why is it the best method? – TylerH May 12 '17 at 13:18
  • 1
    indexOf Method in not replacement for startsWith, indexOf will return value if it matches any where in given string, i don't suggest to use indexOf. – Raj Kumar Samala Dec 21 '17 at 11:13
  • 13
    `indexOf` does return value, but @Jona has checked that the return value is zero (i.e. the string is at the beginning), meaning it *is* a good replacement for `startsWith`! – SharpC Mar 02 '18 at 14:00
  • This is the same functionality as the polyfill without having to add a polyfill or bring in an extra library. It's an excellent solution - the only downside I can see is perhaps code readability- the intention is more clear when the function is named startsWith. – John T Jan 04 '19 at 16:09
14

If this is happening in Angular 2+ application, you can just uncomment string polyfills in polyfills.ts:

import 'core-js/es6/string';
Vitaliy Ulantikov
  • 10,157
  • 3
  • 61
  • 54
  • I added the Oka's polyfill fix, but it didn't work for me on my Angular 5 application, but `import 'core-js/es6/string';` fixed it. Many thanks! – decebal May 25 '18 at 10:35
  • It appears that the polyfill has moved to `import 'core-js/es/string';`. I'm on Angular 10. `import 'core-js/stable/string/starts-with';` seems even better though – Richard Jan 04 '21 at 15:28
7

Replace the startsWith function with:

yourString.indexOf(searchString, position) // where position can be set to 0

This will support all browsers including IE

Position can be set to 0 for string matching from the start meaning 0th position.

Harshit Pant
  • 1,032
  • 11
  • 14
  • Useful solution without having to rewrite prototypes nor using polyfills. Plus it is wide compatible among browsers. +1 – Sergio A. Jan 24 '20 at 10:56
2

As others have said startsWith and endsWith are part of ES6 and not available in IE11. Our company always uses lodash library as a polyfill solution for IE11. https://lodash.com/docs/4.17.4

_.startsWith([string=''], [target], [position=0])
mbokil
  • 3,202
  • 30
  • 22
0

While the post of Oka is working great, it might be a bit outdated. I figured out that lodash can tackle it with one single function. If you have lodash installed, it might save you a few lines.

Just try:

import { startsWith } from lodash;

. . .

    if (startsWith(yourVariable, 'REP')) {
         return yourVariable;        
    return yourVariable;
       }      
     }
TheGabornator
  • 523
  • 1
  • 7
  • 20
0

I also recently faced the prob. I solved using ^ which is similar to startwith in jquery. Say,

var str = array[a].id;
if (str.startsWith('REP')) {..........}

we can use

if($("[id^=str]").length){..........}

Here, str is id of element.

User Learning
  • 3,165
  • 5
  • 30
  • 51
0

Follow this method if problem comes when working with angular2+ projects

I was looking for a solution when i got this error, and it got me here. But this question seems to be specific but the error is not, its a generic error. This is a common error for angular developers dealing with Internet Explorer.

I had the same issue while working with angular 2+, and it got resolved just by few simple steps.

In Angular latest versions, there are come commented codes in the polyfills.ts shows all the polyfills required for the smooth running in Internet Explorer versions IE09,IE10 and IE11

/** IE9, IE10 and IE11 requires all of the following polyfills. **/
//import 'core-js/es6/symbol';
//import 'core-js/es6/object';
//import 'core-js/es6/function';
//import 'core-js/es6/parse-int';
//import 'core-js/es6/parse-float';
//import 'core-js/es6/number';
//import 'core-js/es6/math';
//import 'core-js/es6/string';
//import 'core-js/es6/date';
//import 'core-js/es6/array';
//import 'core-js/es6/regexp';
//import 'core-js/es6/map';
//import 'core-js/es6/weak-map';
//import 'core-js/es6/set';

Uncomment the codes and it would work perfectly in IE browsers

/** IE9, IE10 and IE11 requires all of the following polyfills. **/
import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/weak-map';
import 'core-js/es6/set';

But you might see a performance drop in IE browsers compared to others :(

jithin john
  • 552
  • 4
  • 12