除了微信本身的 Bug 之外,微信小程序的兼容性问题主要体现在不同平台的 JavaScript 引擎对标准 API 的支持程度不同造成的。比如 Array.find()
在 Android 7.0 上是支持的,但在 Android 6.0.1 上却不支持。如果你的小程序里使用了这个 API 就引发兼容性问题。更详细的信息可以参阅微信小程序兼容性问题。
关于各个平台的标准库支持情况,可以查阅附录。
在特定平台上,对不支持的 API 使用 polyfill 来实现。
典型地,比如 Array.fill()
函数可以使用 MDN 上的 polyfill 来实现。
作为一次性的解决方案,你可以把 polyfill.js
下载到本机,放在微信小程序指定目录下。在需要使用标准 API 的 JavaScript 文件头部插入如下代码:
import 'path/to/polyfill.js'
这样就会自动给不支持特定 API 的平台打上补丁。
- 添加所有不支持 API 的 polyfill 实现
- 完善其他平台的 API 支持情况
- 优化 polyfill 代码的执行效率
贡献代码的同学需要安装 node 及 jasmine-node 作为开发环境。
- 在
polyfill.js
里编写兼容性函数,比如:
if (!String.prototype.startsWith) {
console.warn('define polyfill for Array.prototype.startsWith');
String.prototype.startsWith = function (searchString, position) {
position = position || 0;
return this.substr(position, searchString.length) === searchString;
};
}
- 在
polyfill.spec.js
里编写单元测试函数,比如:
// 设置为 null 是为了使用 polyfill.js 里定义的函数
String.prototype.startsWith = null;
...
// 真正的测试例在这
it('String.startsWith()', () => {
var s = 'test string';
expect(s.startsWith('test')).toEqual(true);
expect(s.startsWith('string')).toEqual(false);
});
...
- 运行
jasmine-node .
进行单元测试
$ jasmine-node .
define polyfill for Array.prototype.findIndex
define polyfill for Array.prototype.fill
define polyfill for String.prototype.startsWith
...
Finished in 0.008 seconds
3 tests, 12 assertions, 0 failures, 0 skipped
PR is welcome.
MIT
Component.apiName | iOS 10.2 | Android 6.0.1 | Android 7.0 | devtool |
---|---|---|---|---|
Array.toString | YES | YES | YES | YES |
Array.values | YES | N/A | YES | N/A |
Array.toLocaleString | YES | YES | YES | YES |
Array.concat | YES | YES | YES | YES |
Array.fill | YES | N/A | YES | YES |
Array.join | YES | YES | YES | YES |
Array.pop | YES | YES | YES | YES |
Array.push | YES | YES | YES | YES |
Array.reverse | YES | YES | YES | YES |
Array.shift | YES | YES | YES | YES |
Array.slice | YES | YES | YES | YES |
Array.sort | YES | YES | YES | YES |
Array.splice | YES | YES | YES | YES |
Array.unshift | YES | YES | YES | YES |
Array.every | YES | YES | YES | YES |
Array.forEach | YES | YES | YES | YES |
Array.some | YES | YES | YES | YES |
Array.indexOf | YES | YES | YES | YES |
Array.lastIndexOf | YES | YES | YES | YES |
Array.filter | YES | YES | YES | YES |
Array.reduce | YES | YES | YES | YES |
Array.reduceRight | YES | YES | YES | YES |
Array.map | YES | YES | YES | YES |
Array.entries | YES | N/A | YES | YES |
Array.keys | YES | N/A | YES | YES |
Array.find | YES | N/A | YES | YES |
Array.findIndex | YES | N/A | YES | YES |
Array.includes | YES | N/A | N/A | YES |
Array.copyWithin | YES | N/A | YES | YES |
Array.constructor | YES | YES | YES | YES |
Buffer | N/A | N/A | N/A | N/A |
DataView.getInt8 | YES | YES | YES | YES |
DataView.getUint8 | YES | YES | YES | YES |
DataView.getInt16 | YES | YES | YES | YES |
DataView.getUint16 | YES | YES | YES | YES |
DataView.getInt32 | YES | YES | YES | YES |
DataView.getUint32 | YES | YES | YES | YES |
DataView.getFloat32 | YES | YES | YES | YES |
DataView.getFloat64 | YES | YES | YES | YES |
DataView.setInt8 | YES | YES | YES | YES |
DataView.setUint8 | YES | YES | YES | YES |
DataView.setInt16 | YES | YES | YES | YES |
DataView.setUint16 | YES | YES | YES | YES |
DataView.setInt32 | YES | YES | YES | YES |
DataView.setUint32 | YES | YES | YES | YES |
DataView.setFloat32 | YES | YES | YES | YES |
DataView.setFloat64 | YES | YES | YES | YES |
DataView.constructor | YES | YES | YES | YES |
Date.toString | YES | YES | YES | YES |
Date.toISOString | YES | YES | YES | YES |
Date.toDateString | YES | YES | YES | YES |
Date.toTimeString | YES | YES | YES | YES |
Date.toLocaleString | YES | YES | YES | YES |
Date.toLocaleDateString | YES | YES | YES | YES |
Date.toLocaleTimeString | YES | YES | YES | YES |
Date.valueOf | YES | YES | YES | YES |
Date.getTime | YES | YES | YES | YES |
Date.getFullYear | YES | YES | YES | YES |
Date.getUTCFullYear | YES | YES | YES | YES |
Date.getMonth | YES | YES | YES | YES |
Date.getUTCMonth | YES | YES | YES | YES |
Date.getDate | YES | YES | YES | YES |
Date.getUTCDate | YES | YES | YES | YES |
Date.getDay | YES | YES | YES | YES |
Date.getUTCDay | YES | YES | YES | YES |
Date.getHours | YES | YES | YES | YES |
Date.getUTCHours | YES | YES | YES | YES |
Date.getMinutes | YES | YES | YES | YES |
Date.getUTCMinutes | YES | YES | YES | YES |
Date.getSeconds | YES | YES | YES | YES |
Date.getUTCSeconds | YES | YES | YES | YES |
Date.getMilliseconds | YES | YES | YES | YES |
Date.getUTCMilliseconds | YES | YES | YES | YES |
Date.getTimezoneOffset | YES | YES | YES | YES |
Date.setTime | YES | YES | YES | YES |
Date.setMilliseconds | YES | YES | YES | YES |
Date.setUTCMilliseconds | YES | YES | YES | YES |
Date.setSeconds | YES | YES | YES | YES |
Date.setUTCSeconds | YES | YES | YES | YES |
Date.setMinutes | YES | YES | YES | YES |
Date.setUTCMinutes | YES | YES | YES | YES |
Date.setHours | YES | YES | YES | YES |
Date.setUTCHours | YES | YES | YES | YES |
Date.setDate | YES | YES | YES | YES |
Date.setUTCDate | YES | YES | YES | YES |
Date.setMonth | YES | YES | YES | YES |
Date.setUTCMonth | YES | YES | YES | YES |
Date.setFullYear | YES | YES | YES | YES |
Date.setUTCFullYear | YES | YES | YES | YES |
Date.setYear | YES | YES | YES | YES |
Date.getYear | YES | YES | YES | YES |
Date.toJSON | YES | YES | YES | YES |
Date.toUTCString | YES | YES | YES | YES |
Date.toGMTString | YES | YES | YES | YES |
Date.constructor | YES | YES | YES | YES |
Error.toString | YES | YES | YES | YES |
Error.constructor | YES | YES | YES | YES |
Float32Array.constructor | YES | YES | YES | YES |
Float64Array.constructor | YES | YES | YES | YES |
Function.constructor | YES | YES | YES | YES |
Int16Array.constructor | YES | YES | YES | YES |
Int32Array.constructor | YES | YES | YES | YES |
Int8Array.constructor | YES | YES | YES | YES |
Map.forEach | YES | N/A | YES | YES |
Map.clear | YES | N/A | YES | YES |
Map.delete | YES | N/A | YES | YES |
Map.get | YES | N/A | YES | YES |
Map.has | YES | N/A | YES | YES |
Map.set | YES | N/A | YES | YES |
Map.keys | YES | N/A | YES | YES |
Map.values | YES | N/A | YES | YES |
Map.entries | YES | N/A | YES | YES |
Map.constructor | YES | N/A | YES | YES |
Math.abs | YES | YES | YES | YES |
Math.acos | YES | YES | YES | YES |
Math.asin | YES | YES | YES | YES |
Math.atan | YES | YES | YES | YES |
Math.acosh | YES | N/A | YES | YES |
Math.asinh | YES | N/A | YES | YES |
Math.atanh | YES | N/A | YES | YES |
Math.atan2 | YES | YES | YES | YES |
Math.cbrt | YES | N/A | YES | YES |
Math.ceil | YES | YES | YES | YES |
Math.clz32 | YES | N/A | YES | YES |
Math.cos | YES | YES | YES | YES |
Math.cosh | YES | N/A | YES | YES |
Math.exp | YES | YES | YES | YES |
Math.expm1 | YES | N/A | YES | YES |
Math.floor | YES | YES | YES | YES |
Math.fround | YES | N/A | YES | YES |
Math.hypot | YES | N/A | YES | YES |
Math.log | YES | YES | YES | YES |
Math.log10 | YES | N/A | YES | YES |
Math.log1p | YES | N/A | YES | YES |
Math.log2 | YES | N/A | YES | YES |
Math.max | YES | YES | YES | YES |
Math.min | YES | YES | YES | YES |
Math.pow | YES | YES | YES | YES |
Math.random | YES | YES | YES | YES |
Math.round | YES | YES | YES | YES |
Math.sign | YES | N/A | YES | YES |
Math.sin | YES | YES | YES | YES |
Math.sinh | YES | N/A | YES | YES |
Math.sqrt | YES | YES | YES | YES |
Math.tan | YES | YES | YES | YES |
Math.tanh | YES | N/A | YES | YES |
Math.trunc | YES | N/A | YES | YES |
Math.imul | YES | YES | YES | YES |
Object.toString | YES | YES | YES | YES |
Object.toLocaleString | YES | YES | YES | YES |
Object.valueOf | YES | YES | YES | YES |
Object.hasOwnProperty | YES | YES | YES | YES |
Object.propertyIsEnumerable | YES | YES | YES | YES |
Object.isPrototypeOf | YES | YES | YES | YES |
Object._defineGetter_ | YES | YES | YES | YES |
Object._defineSetter_ | YES | YES | YES | YES |
Object._lookupGetter_ | YES | YES | YES | YES |
Object._lookupSetter_ | YES | YES | YES | YES |
Object.constructor | YES | YES | YES | YES |
Promise.then | YES | YES | YES | YES |
Promise.catch | YES | YES | YES | YES |
Promise.constructor | YES | YES | YES | YES |
RegExp.compile | YES | YES | YES | YES |
RegExp.exec | YES | YES | YES | YES |
RegExp.toString | YES | YES | YES | YES |
RegExp.test | YES | YES | YES | YES |
RegExp.constructor | YES | YES | YES | YES |
Set.forEach | YES | N/A | YES | YES |
Set.add | YES | N/A | YES | YES |
Set.clear | YES | N/A | YES | YES |
Set.delete | YES | N/A | YES | YES |
Set.has | YES | N/A | YES | YES |
Set.entries | YES | N/A | YES | YES |
Set.values | YES | N/A | YES | YES |
Set.keys | YES | N/A | YES | YES |
Set.constructor | YES | N/A | YES | YES |
String.match | YES | YES | YES | YES |
String.padStart | YES | N/A | N/A | N/A |
String.padEnd | YES | N/A | N/A | N/A |
String.repeat | YES | N/A | YES | YES |
String.replace | YES | YES | YES | YES |
String.search | YES | YES | YES | YES |
String.split | YES | YES | YES | YES |
String.toString | YES | YES | YES | YES |
String.valueOf | YES | YES | YES | YES |
String.charAt | YES | YES | YES | YES |
String.charCodeAt | YES | YES | YES | YES |
String.codePointAt | YES | N/A | YES | YES |
String.concat | YES | YES | YES | YES |
String.indexOf | YES | YES | YES | YES |
String.lastIndexOf | YES | YES | YES | YES |
String.slice | YES | YES | YES | YES |
String.substr | YES | YES | YES | YES |
String.substring | YES | YES | YES | YES |
String.toLowerCase | YES | YES | YES | YES |
String.toUpperCase | YES | YES | YES | YES |
String.localeCompare | YES | YES | YES | YES |
String.toLocaleLowerCase | YES | YES | YES | YES |
String.toLocaleUpperCase | YES | YES | YES | YES |
String.big | YES | YES | YES | YES |
String.small | YES | YES | YES | YES |
String.blink | YES | YES | YES | YES |
String.bold | YES | YES | YES | YES |
String.fixed | YES | YES | YES | YES |
String.italics | YES | YES | YES | YES |
String.strike | YES | YES | YES | YES |
String.sub | YES | YES | YES | YES |
String.sup | YES | YES | YES | YES |
String.fontcolor | YES | YES | YES | YES |
String.fontsize | YES | YES | YES | YES |
String.anchor | YES | YES | YES | YES |
String.link | YES | YES | YES | YES |
String.trim | YES | YES | YES | YES |
String.trimLeft | YES | YES | YES | YES |
String.trimRight | YES | YES | YES | YES |
String.startsWith | YES | N/A | YES | YES |
String.endsWith | YES | N/A | YES | YES |
String.includes | YES | N/A | YES | YES |
String.normalize | YES | YES | YES | YES |
String.constructor | YES | YES | YES | YES |
Symbol.toString | YES | N/A | YES | YES |
Symbol.valueOf | YES | N/A | N/A | YES |
Symbol.constructor | YES | N/A | YES | YES |
TypeError.toString | YES | N/A | N/A | YES |
TypeError.constructor | YES | YES | YES | YES |
Uint16Array.constructor | YES | YES | YES | YES |
Uint32Array.constructor | YES | YES | YES | YES |
Uint8Array.constructor | YES | YES | YES | YES |
Uint8ClampedArray.constructor | YES | YES | YES | YES |
WeakMap.delete | YES | YES | YES | YES |
WeakMap.get | YES | YES | YES | YES |
WeakMap.has | YES | YES | YES | YES |
WeakMap.set | YES | YES | YES | YES |
WeakMap.constructor | YES | YES | YES | YES |
目前平台数据还不全,比如 Android 5.0 就没有相应的数据。愿意贡献数据的同学请发信给我,只要打开一个微信小程序,点个按钮即可。