IE11 - Variable is out of range even though I used

2019-02-25 08:34发布

问题:

The console stops on this line with the error:

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

var srcObj = rollOverCollectionA[i].srcset.splice(171, 0, '-hover');

This above line is part of this section.

 document.addEventListener("DOMContentLoaded", function (event) {
   var rollOverCollectionA = document.getElementById("roll-over-collection-b").getElementsByClassName("rollover");
   rollOverCollectionA = Array.prototype.slice.apply(rollOverCollectionA);
   console.log("rollOverCollectionA", rollOverCollectionA);
   var l = rollOverCollectionA.length;
   for (let i = 0; i < l; i++) {
     on("mouseover", "#" + rollOverCollectionA[i].id, function () {
       var srcObj = rollOverCollectionA[i].srcset.splice(171, 0, '-hover');
       srcObj.splice(362, 0, 'hover-')
       rollOver(rollOverCollectionA[i].id, srcObj);
     });
     on("mouseout", "#" + rollOverCollectionA[i].id, function () {
       // remove the hovers
       rollOut(rollOverCollectionA[i].id, rollOverCollectionA[i].srcset.replace('-hover', '').replace('hover-', ''));
     });
   }
 });

i is outside the range of the collection, but I used let for i as shown in this question's answers.

What in IE is causing this? This works in Chrome, Firefox and Safari and Edge on Mac and PC.

Here's a runnable example:

var on = function(event, elem, callback, capture) {
  console.log('elem in onFunction', elem);
  console.log('elem in onFunction', typeof elem);
  if (typeof elem === "function") {
    capture = callback;
    callback = elem;
    elem = window;
  }
  capture = !!capture;
  elem = typeof elem === "string" ? document.querySelector(elem) : elem;
  if (!elem) return;
  elem.addEventListener(event, callback, capture);
};

function rollOver(elem, src) {
  console.log('rollOver src', src);
  document.getElementById(elem).srcset = src;
}

function rollOut(elem, src) {
  console.log('rollOut src', src);
  document.getElementById(elem).srcset = src;
}
if (!String.prototype.splice) {
  /** * {JSDoc} * * The splice() method changes the content of a string by removing a range of * characters and/or adding new characters. * * @this {String} * @param {number} start Index at which to start changing the string. * @param {number} delCount An integer indicating the number of old chars to remove. * @param {string} newSubStr The String that is spliced in. * @return {string} A new string with the spliced substring. */
  String.prototype.splice = function(start, delCount, newSubStr) {
    return this.slice(0, start) + newSubStr + this.slice(start + Math.abs(delCount));
  };
}

document.addEventListener("DOMContentLoaded", function(event) {
  var rollOverCollectionA = document.getElementById("roll-over-collection-b").getElementsByClassName("rollover");
  rollOverCollectionA = Array.prototype.slice.apply(rollOverCollectionA);
  console.log("rollOverCollectionA", rollOverCollectionA);
  var l = rollOverCollectionA.length;
  for (let i = 0; i < l; i++) {
    on("mouseover", "#" + rollOverCollectionA[i].id, function() {
      var srcObj = rollOverCollectionA[i].srcset.splice(171, 0, '-hover');
      srcObj.splice(362, 0, 'hover-')
      rollOver(rollOverCollectionA[i].id, srcObj);
    });
    on("mouseout", "#" + rollOverCollectionA[i].id, function() {
      // remove the hovers
      rollOut(rollOverCollectionA[i].id, rollOverCollectionA[i].srcset.replace('-hover', '').replace('hover-', ''));
    });
  }
});
.homepage-banner .offers-banner .button {
  background-color: #000;
}

.homepage-banner .offers-banner .button a {
  color: #fff;
}

.homepage-banner .offers-banner a {
  margin: 0px auto;
}

.homepage-banner .offers-banner {
  text-align: center;
  padding: 20px 0 0;
  margin: 50px auto 0;
  bottom: inherit;
  position: relative;
}

.homepage-banner .offers-banner h2 {
  margin-bottom: 8px;
  width: 90%;
  font-size: 36px;
  padding: 0;
  line-height: 34px;
  margin: 0 0 10px;
}

.homepage-banner .offers-banner p {
  font-family: termina, sans-serif;
  margin: 25px auto !important;
  font-weight: 600;
  /* font-size: 15px; */
}

.homepage-banner .offers-banner p:last-of-type {
  margin-bottom: 0;
}


/* .homepage-banner .offers-banner a:hover {
      color: #000;
    } */

.homepage-banner .offers-banner .offer-banner-content-wrapper {
  position: relative;
}

.homepage-banner .offers-banner .offers-listing-container {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100%;
  transform: translate(-50%, -50%);
  display: -webkit-flex;
  display: flex;
  -webkit-flex-direction: row;
  flex-direction: row;
  text-align: left;
  margin: 0 auto;
  flex-flow: nowrap;
  align-self: flex-start;
  justify-content: center;
}

.homepage-banner .offers-banner .offers-listing-container .item {
  width: 33%;
  text-align: center;
  padding-bottom: 10px;
}

.homepage-banner .offers-banner .offers-listing-container .item .item-name {
  margin: 20px auto 0;
}

.homepage-banner .offers-banner .offers-listing-container .item .item-name p {
  text-align: center;
  font-size: 16px;
  line-height: 20px;
  margin: 20px auto 0;
  text-transform: uppercase;
}

.homepage-banner .offers-banner .offers-listing-container .item:nth-of-type(2n) {
  margin: 0;
}

.homepage-banner .offers-banner .offers-listing-container .item .item-name .button.button-helper {
  margin-bottom: 0;
  padding: 3px 8px;
  background-color: #e87ea6;
  border-color: #e87ea6;
  border-radius: 0;
  border-style: solid;
  border-width: 1px;
  color: #fff;
  cursor: pointer;
  display: inline-block;
  font-size: 14px;
  padding: .23em 2em;
  text-align: center;
  transition: all .3s ease;
  outline: 0;
  font-family: termina, sans-serif;
  font-weight: 500;
  font-style: normal;
  -webkit-font-kerning: none;
  -moz-font-kerning: none;
  font-kerning: none;
  text-transform: uppercase;
  line-height: inherit;
  height: inherit;
}

div#roll-over-collection-b {
  position: absolute;
}

@media screen and (min-width: 1024px) and (max-width: 1199px) {
  .homepage-banner .offers-banner .offers-listing-container .item {
    width: 30%;
  }
  .homepage-banner .offers-banner .offers-listing-container .item:nth-of-type(2n) {
    margin: 0 2em;
  }
}

@media screen and (min-width: 768px) and (max-width: 1023px) {
  .homepage-banner .offers-banner .offers-listing-container .item:nth-of-type(2n) {
    margin: 0 3em;
  }
  .homepage-banner .offers-banner .offers-listing-container .item {
    width: 26%;
  }
}

@media screen and (max-width: 767px) {
  .homepage-banner .offers-banner {
    margin: 0;
  }
  .homepage-banner .offers-banner picture>img {
    /* width: 100%; */
    height: auto;
    line-height: 0;
    vertical-align: bottom;
  }
  .homepage-banner .offers-banner h2 {
    font-size: 24px;
    line-height: 26px;
    width: 95%;
    margin: 0 auto 10px;
  }
  .homepage-banner .offers-banner p {
    width: 95%;
    margin: 0px auto 10px;
    font-size: 16px;
    font-weight: 400;
  }
  .homepage-banner .offers-banner .button {
    background-color: #fff;
  }
  /* .homepage-banner .offers-banner .button a {
        color: #000;
      } */
  .homepage-banner .offers-banner .offers-listing-container {
    -webkit-flex-direction: column;
    flex-direction: column;
    text-align: left;
    margin: 0 auto;
    flex-flow: wrap;
    align-self: flex-start;
    justify-content: center;
  }
  .homepage-banner .offers-banner .offers-listing-container .item {
    width: 100%;
    margin: 0px auto 3em;
  }
  .homepage-banner .offers-banner .offers-listing-container .item img {
    width: 50%;
  }
  .homepage-banner .offers-banner .offers-listing-container .item:nth-of-type(2n) {
    margin: 0px auto 3.5em;
  }
  .homepage-banner .offers-banner .offers-listing-container .item:last-of-type {
    margin: 0px auto;
  }
  .homepage-banner .offers-banner .offers-listing-container .item p {
    margin-bottom: 20px;
  }
}

@media screen and (min-width: 480px) and (max-width: 767px) {
  .homepage-banner .offers-banner .offers-listing-container .item img {
    width: 56%;
  }
}

@media screen and (max-width: 479px) {
  .homepage-banner .offers-banner .offers-listing-container .item img {
    width: 60%;
  }
}
<div class="offers-banner">
  <picture>
    <source media=" (max-width: 767px)" srcset="images/home-page/mobile/eyes-on-you-statement-banner-mobile.jpg?$staticlink$, images/home-page/mobile/eyes-on-you-statement-banner-mobile_2x.jpg?$staticlink$ 2x" />
    <source media="(min-width: 480px) and (max-width: 767px)" srcset="eyes-on-you-statement-banner-sp.jpg?$staticlink$?$staticlink$,images/home-page/smartphone/eyes-on-you-statement-banner-sp_2x.jpg?$staticlink$ 2x" />
    <source media="(min-width: 768px) and (max-width: 1023px)" srcset="images/home-page/tablet/eyes-on-you-statement-banner-tablet.jpg?$staticlink$, images/home-page/tablet/eyes-on-you-statement-banner-tablet_2x.jpg?$staticlink$ 2x" />
    <img class="new-makeup-banner" alt="Eyes On You!" src="images/home-page/desktop/eyes-on-you-statement-banner-desktop.jpg?$staticlink$" srcset="images/home-page/desktop/eyes-on-you-statement-banner-desktop.jpg?$staticlink$, images/home-page/desktop/eyes-on-you-statement-banner-desktop_2x.jpg?$staticlink$ 2x"
    />
  </picture>
  <p>Twinkle, twinkle, you star! Transform your <br> holiday look with Juicy Couture Beauty. </p>
  <div class="offer-banner-content-wrapper">
    <div id="roll-over-collection-b" class="offers-listing-container">
      <div class="item">
        <a href="$url('Product-Show','pid','1502A0116919')$">
          <picture>
            <source media=" (max-width: 767px)" srcset="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/mobile/mobile_eye_linner.jpg?$staticlink$, https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/mobile/mobile_eye_linner_2x.jpg?$staticlink$ 2x"
            />
            <source media="(min-width: 480px) and (max-width: 767px)" srcset="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/smartphone/smartphone_eye_linner.jpg?$staticlink$, https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/smartphone/smartphone_eye_linner_2x.jpg?$staticlink$ 2x"
            />
            <source media="(min-width: 768px) and (max-width: 1023px)" srcset="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/tablet/eyes-on-you-1-hover-tablet.jpg?$staticlink$, https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/tablet/eyes-on-you-1-hover-tablet_2x.jpg?$staticlink$ 2x"
            />
            <img id="hover-1" alt="Juicy Couture Oui Slay EyeLiner" class="rollover" src="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/desktop/eyes-on-you-desktop-1.jpg?$staticlink$ 1x"
              srcset="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/desktop/eyes-on-you-desktop-1.jpg?$staticlink$, https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/desktop/eyes-on-you-desktop-2x-1.jpg?$staticlink$ 2x"
            />
          </picture>
          <div class="item-name">
            <div class="button button-helper">SHOP NOW</div>
          </div>
        </a>
      </div>

      <div class="item">
        <a href="$url('Product-Show','pid','1502A0116950')$">
          <picture>
            <source media=" (max-width: 767px)" srcset="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/mobile/mobile_EYE_TOPPER.jpg?$staticlink$, https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/mobile/mobile_EYE_TOPPER_2x.jpg?$staticlink$ 2x"
            />
            <source media="(min-width: 480px) and (max-width: 767px)" srcset="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/smartphone/SMARTPHONE_EYE_TOPPER.jpg?$staticlink$, https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/smartphone/SMARTPHONE_EYE_TOPPER_2X-.jpg?$staticlink$ 2x"
            />
            <source media="(min-width: 768px) and (max-width: 1023px)" srcset="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/tablet/eyes-on-you-2-hover-tablet.jpg?$staticlink$, https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/tablet/eyes-on-you-2-hover-tablet_2x.jpg?$staticlink$ 2x"
            />
            <img id="hover-2" alt="Juicy Couture Lip + Eye Topper" class="rollover" src="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/desktop/eyes-on-you-desktop-2.jpg?$staticlink$ 1x"
              srcset="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/desktop/eyes-on-you-desktop-2.jpg?$staticlink$, https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/desktop/eyes-on-you-desktop-2x-2.jpg?$staticlink$ 2x"
            />
        </a>
        </picture>

        <div class="item-name">
          <div class="button button-helper">SHOP NOW </div>
        </div>
        </a>
      </div>

      <div class="item">
        <a href="$url('Product-Show','pid','1502A0116930')$">
          <picture>
            <source media=" (max-width: 767px)" srcset="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/mobile/mobile_color_palette.jpg?$staticlink$, https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/mobile/mobile_color_palette_2x.jpg?$staticlink$ 2x"
            />
            <source media="(min-width: 480px) and (max-width: 767px)" srcset="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/smartphone/eyes-on-you-eye-liner-sp.jpg?$staticlink$, https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/smartphone/smartphone_color_palette_2x.jpg?$staticlink$ 2x"
            />
            <source media="(min-width: 768px) and (max-width: 1023px)" srcset="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/tablet/eyes-on-you-3-hover-tablet.jpg?$staticlink$, https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/tablet/eyes-on-you-3-hover-tablet_2x.jpg?$staticlink$ 2x"
            />
            <img id="hover-3" alt="Juicy Couture The Shady Color Palette" class="rollover" src="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/desktop/eyes-on-you-desktop-3.jpg?$staticlink$"
              srcset="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/desktop/eyes-on-you-desktop-3.jpg?$staticlink$, https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/desktop/eyes-on-you-desktop-2x-3.jpg?$staticlink$ 2x"
            />
          </picture>
          <div class="item-name">
            <div class="button button-helper">SHOP NOW </div>
          </div>
        </a>
      </div>
    </div>
    <div class="bkgrd-img">
      <picture>
        <source media=" (max-width: 479px)" srcset="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/mobile/updated_mobile_eyes_on_you_background.jpg?$staticlink$, https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/mobile/updated_mobile_eyes_on_you_background_2x.jpg?$staticlink$ 2x "
        />
        <source media="(min-width: 480px) and (max-width: 767px)" srcset="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/smartphone/updated_smartphone_eyes_on_you_background.jpg?$staticlink$, https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/smartphone/smartphone_eyes_on_you_background_2x-up.jpg?$staticlink$ 2x"
        />
        <source media="(min-width: 768px) and (max-width: 1023px)" srcset="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/tablet/eyes-on-you-background-tablet.jpg?$staticlink$, https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/tablet/eyes-on-you-background-tablet_2x.jpg?$staticlink$ 2x "
        />
        <img alt="" src="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/desktop/EYES_ON_YOU_desktop_HP_background.jpg?$staticlink$" srcset="https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/desktop/EYES_ON_YOU_desktop_HP_background.jpg?$staticlink$, https://staging.elizabetharden.pfsweb.demandware.net/on/demandware.static/-/Sites-JuicyCoutureBeauty-Library/default/dwd13910f1/images/home-page/desktop/EYES_ON_YOU_desktop_HP_background_@2x.jpg?$staticlink$ 2x"
        />
      </picture>
    </div>
  </div>
</div>

回答1:

There are two problems:

  1. Sadly, IE9-IE11 support let, but don't support the correct ES2015 ("ES6") semantics for let. In particular, they don't create a new i for each iteration of the loop as ES2015 defines.

    To support IE, you'll have to use one of the other solutions shown in the answers to the question linked in your question, such using bind (IE9+):

    document.addEventListener("DOMContentLoaded", function(event) {
      var rollOverCollectionA = document.getElementById("roll-over-collection-b").getElementsByClassName("rollover");
      rollOverCollectionA = Array.prototype.slice.apply(rollOverCollectionA);
      console.log("rollOverCollectionA", rollOverCollectionA);
      var l = rollOverCollectionA.length;
      for (var i = 0; i < l; i++) {
        //     ^^^
        on("mouseover", "#" + rollOverCollectionA[i].id, function() {
        console.log("mouseover " + this.id + " " + (typeof this.srcset));
          var srcObj = this.srcset.splice(171, 0, '-hover');
        // ------------^^^^
          srcObj.splice(362, 0, 'hover-')
          rollOver(this.id, srcObj);
          // ------^^^^
        }.bind(rollOverCollectionA[i]));
      // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        on("mouseout", "#" + rollOverCollectionA[i].id, function() {
        console.log("mouseout " + this.id + " " + (typeof this.srcset));
          // remove the hovers
          rollOut(this.id, this.srcset.replace('-hover', '').replace('hover-', ''));
          // -----^^^^-----^^^^
        }.bind(rollOverCollectionA[i]));
      // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      }
    });
    

    It's a very subtle bug if you don't happen to know that late-model IE has this not-spec-compliant let. We generally expect that a keyword will either blow up the script entirely (if not supported) or work correctly (if supported). Sadly, that's not the case here.

  2. The srcset property doesn't exist on IE, because IE doesn't support the srcset attribute. You'll need to manipulate src instead. (You could still access the srcset attribute as an attribute [via getAttribute and setAttribute], but the value you get/set is a string and IE won't use it).