【问题标题】:IE11 Object doesn't support property or method 'indexOf' (but it's not an object and works in other browsers)IE11 对象不支持属性或方法“indexOf”(但它不是对象,在其他浏览器中也可以使用)
【发布时间】:2019-02-19 11:53:18
【问题描述】:

我有一个脚本,它遍历数组中传递的值,并检查浏览器是否原生支持这些项目。这在 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 中工作,但同时在所有其他浏览器中也能工作!

【问题讨论】:

  • 您尝试使用indexOfnull 是怎么来的?我的意思是,当条件通过时,check 不存在...
  • 您问题中的代码存在语法错误(我在将其放入现场可运行的 sn-p 时发现了这一点)。我添加了似乎合适的},但请根据您的实际代码检查它。 总是最好使用复制和粘贴来复制您的代码(首先将其降至绝对最小值MCVE),以避免引入类似的错误。
  • 为糟糕的代码 sn-p 道歉 - 我现在添加了完整的代码 sn-p - 错误不在 Promise,而是在 if (check.indexOf(splitChars) >= 1) {

标签: javascript internet-explorer cross-browser legacy


【解决方案1】:

您可以在 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

【讨论】:

  • Ahaaaa - @t-j-crowder 谢谢!抱歉,我对 JS 还很陌生,因为我无法弄清楚为什么它一直认为它是一个对象,所以我正在拔头发!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-27
  • 1970-01-01
  • 1970-01-01
  • 2015-06-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多