写JS时最头疼啥?不是逻辑绕,而是刚在Chrome里跑得好好的,一打开IE11或者旧版Edge就报错——Array.from不认、Object.assign报undefined、箭头函数直接SyntaxError……别急,这不是你代码有毛病,是浏览器太老了。
兼容性函数,其实就是“兜底”
比如想用Array.from把类数组转成真数组,但IE不支持。与其满屏写if (typeof Array.from === 'function'),不如自己先定义一个:
if (!Array.from) {
Array.from = function(arrayLike) {
return [].slice.call(arrayLike);
};
}这段代码放在所有业务逻辑之前执行,后面就能放心用Array.from(document.querySelectorAll('li')),不用再判断。
几个高频兼容写法,抄了就能用
1. Object.assign(深拷贝不用它,浅合并够用)
if (typeof Object.assign !== 'function') {
Object.assign = function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (source.hasOwnProperty(key)) {
target[key] = source[key];
}
}
}
return target;
};
}2. String.prototype.includes(比indexOf更直观)
if (!String.prototype.includes) {
String.prototype.includes = function(search, start) {
if (typeof start !== 'number') start = 0;
return this.indexOf(search, start) !== -1;
};
}3. Element.classList(操作class再也不用正则拼字符串)
IE10+支持classList,但IE9不行。简单补个hasClass和addClass就够日常用了:
if (!('classList' in document.documentElement)) {
HTMLElement.prototype.hasClass = function(className) {
return new RegExp('(^| )' + className + '( |$)', 'gi').test(this.className);
};
HTMLElement.prototype.addClass = function(className) {
if (!this.hasClass(className)) {
this.className += ' ' + className;
}
};
HTMLElement.prototype.removeClass = function(className) {
this.className = this.className.replace(new RegExp('(^| )' + className + '( |$)', 'gi'), ' ').trim();
};
}小技巧:只补你真用到的
别一股脑把MDN上所有polyfill全塞进项目。比如你压根没用Promise,就别加es6-promise;页面里全是for...of,那补Symbol.iterator比补Array.from更关键。打开F12,在Console里敲typeof Array.from,返回'undefined'?那就补。返回'function'?跳过。
最后提醒一句
有些API没法完美模拟,比如fetch,靠XMLHttpRequest能实现基本功能,但AbortController这种就得另想办法。遇到这类情况,要么降级处理(比如用loading状态代替取消请求),要么引入轻量库如whatwg-fetch。兼容不是硬扛,是让老用户不卡死,新用户不憋屈。