0

I'm dynamically creating an array of objects like this:

let span = document.createElement('span')

span.classList.add('animated')
span.classList.add('char')

span.textContent = (char.match(/'|\.|\!|\?| |\,|\.|\;|\:|\./)) ? char  : '\ '

chars.push({
    char: char,
    span: span,
    solved: span.textContent === '\ ' ? false : true
 })

Later when I try to iterate through the array and accessing the element like this:

chars[i].span.classList.add('high-light')

I get the following error:

Unable to get property 'span' of undefined or null reference

Why?

The full code is available here: https://github.com/sickdyd/secret-sentence

devamat
  • 2,293
  • 6
  • 27
  • 50

1 Answers1

4

The problem is here:

for (let i = 0; i < chars.length; i++) {
  // ...
  setTimeout(function() {
    chars[i].span.classList.add('high-light')

This is a bug in IE11. Variables declared with let syntax were officially introduced in ES2015, and IE11 was released in 2013 - although it does not throw a syntax error when encountering let, it does not conform to the specification. Specifically, variables declared with let in IE11 do not get block scoped - rather, they have function scope, just like var, so by the end of the loop, i is equal to chars.length, and chars[chars.length] is undefined, so trying to reference chars[i].span will throw an error.

I'd recommend avoiding for loops and using forEach instead, which will fix the problem and also let you avoid having to keep track of indicies:

chars.forEach(function(char) {
  // ...
  setTimeout(function() {
    char.span.classList.add('high-light')
    // ...
    // instead of referencing chars[i], reference char

You can also use the main closure inside loops example, though it's pretty ugly:

for (let i = 0; i < chars.length; i++) {
  (function(i) {
    // now, there will be a separate `i` argument for every iteration
    // ...
    setTimeout(function() {
      chars[i].span.classList.add('high-light')
      // ...
  })(i);
}

You can also consider automatically transpiling your code to be ES5 compatible with Babel.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320