IE11 对象不支持 属性 或方法 'indexOf'(但它不是一个对象并且在其他浏览器中工作)

IE11 Object doesn't support property or method 'indexOf' (but it's not an object and works in other browsers)

我有一个脚本可以遍历数组中传递的值,并检查浏览器是否原生支持这些项目。这在 Chrome、Edge、FireFox 和 Safari 中工作正常,但 IE11 和更早版本(确实 需要它才能工作的浏览器)会抛出错误。 数组值是字符串(如下所示)但出于某种原因,IE11 将它们视为对象,这意味着当我尝试检查一个 .在字符串中,IE 出错了。

我已经尝试转换数组项 toString,但这只会导致 object objectobject undefined

我已经设置了一个包含完整代码集的 CodePen: https://codepen.io/willstocks_tech/pen/YBEzLW?editors=1012

可以在IE中使用的版本是:https://s.codepen.io/willstocks_tech/debug/YBEzLW/mWAoNxdogGvr(虽然这个可能会过期!)

//https://github.com/willstocks-tech/dynamically-polyfill-features-for-a-script/releases/
dynamicPolyfill(
 ['IntersectionObserver', 'IntersectionObserverEntry', 'Object.assign', 'Array.copyWithin']
 ,'https://cdn.jsdelivr.net/npm/quicklink@1.0.0/dist/quicklink.umd.js' 
 ,'quicklink()' 
)

function dynamicPolyfill(tocheck, scriptToPolyfill, functionToRunonLoad) {
 if(typeof Promise !== "undefined"){
  var checkPromises = [];
  if(Array.isArray(tocheck)) {
   tocheck.forEach(
    function(tocheck){
     checkPromises.push(checking(tocheck))
    }
   )
  } else {
   checkPromises.push(checking(tocheck))
  }
  checkPromises = checkPromises.filter(function(p){return p !== undefined}).join(' ');
  loadPolyfill(checkPromises, scriptToPolyfill, functionToRunonLoad)
 } else {
  promiFill(tocheck, scriptToPolyfill, functionToRunonLoad);
 }
}

function promiFill(tocheck, scriptToPolyfill, functionToRunonLoad){
  var promPolyfill = document.createElement('script'); 
  promPolyfill.src = ('https://polyfill.io/v3/polyfill.min.js?features=Promise'); 
  document.body.appendChild(promPolyfill); 
  promPolyfill.onerror = function(response) { 
   console.error("Polyfilling promise failed", response); 
  } 
  promPolyfill.onload = function(tocheck, scriptToPolyfill, functionToRunonLoad) {
   dynamicPolyfill(tocheck, scriptToPolyfill, functionToRunonLoad);
  }
}

function checking(check){
 var splitChars = '.';
 if ((check in window) != true || (check in this) != true) {
  if (check.indexOf(splitChars) >= 1) {
   var split = check.split('.');
   var firstWord = window[split[0]];
   var lastWord = new Object(split[split.length - 1]);
   if (lastWord in firstWord != true && lastWord in firstWord.prototype != true) {
    return check;
   }
  } else {
   return check;
  }
 }
}

function loadPolyfill(url, scriptToPolyfill, functionToRunonLoad) {
 if(url !== "") {
  var polyfill = document.createElement('script'); 
  polyfill.src = ('https://polyfill.io/v3/polyfill.min.js?features='+encodeURIComponent(url)); 
  document.body.appendChild(polyfill); 
  polyfill.onerror = function(response) { 
   console.error("Loading the polyfill(s) failed!", response); 
  } 
  polyfill.onload = function() {
   loadMyScript(scriptToPolyfill, functionToRunonLoad)
  }
 } else {
     loadMyScript(scriptToPolyfill, functionToRunonLoad)
 }
}

function loadMyScript(url, functionToRunonLoad) {
 if(Array.isArray(url)) {
  var promises = [];
  url.forEach(
   function(url){
    promises.push(nonblankURL(url));
   }
  );
  Promise.all(promises)
   .then( 
    function() {
     initialiseMyScript(functionToRunonLoad)
    }
  ).catch(function(error){return error})
 } else if (!Array.isArray(url) && url !== null && url !== '') {
  nonblankURL(url)
   .then( 
    function() {
     initialiseMyScript(functionToRunonLoad)
    }
  ).catch(function(error){return error}) 
 } else {
  initialiseMyScript(functionToRunonLoad) 
 }
}

function nonblankURL(uri){
 return new Promise( 
  function(resolve, reject) { 
   var thescript = document.createElement('script');
   thescript.src = encodeURI(uri);
   document.body.appendChild(thescript);
   thescript.onerror = function(response) {
    return reject("Loading the script failed!", response);
   } 
   thescript.onload = function() {
    return resolve(uri);
   } 
  }
 )

}

function initialiseMyScript(functionToRunonLoad) {
 if(Array.isArray(functionToRunonLoad)) {
  functionToRunonLoad.forEach(
   function(functionToRunonLoad){
    initScript(functionToRunonLoad)
   }
  )
 } else { 
  initScript(functionToRunonLoad)
 }
 function initScript(fn) {
  try {
   window[fn];
  } catch(err) {
   console.error('There was an error: ', err, err.name, err.stack);
  }
 }
}

所有其他浏览器似乎都能很好地处理这个问题,但 IE11 和更早版本会抛出以下错误: SCRIPT438: Object doesn't support property or method 'indexOf'

我一辈子都想不出如何让它在 IE 中工作,但同时在所有其他浏览器中也能工作!

你可以在IE11调试器中看到tocheck此时是一个Event对象(显然没有indexOf)。那是因为这段代码:

promPolyfill.onload = function(tocheck, scriptToPolyfill, functionToRunonLoad) {
    dynamicPolyfill(tocheck, scriptToPolyfill, functionToRunonLoad);
}

DOM 事件处理程序接收的第一个也是唯一一个参数是一个事件对象,但您将其作为 tocheck 接受,然后使用该事件调用 dynamicPolyfill

您的意思可能是:

promPolyfill.onload = function() {
    dynamicPolyfill(tocheck, scriptToPolyfill, functionToRunonLoad);
};

或类似的。无论如何,问题是在 Event 对象上调用 indexOf