出现的问题
在项目中使用了 ES6 的语法,比如let
、const
,导致在iOS 9.3.3版本的浏览器报错,但是在高版本的浏览器显示正常。
尝试解决
在确定了是由 ES6 新特性引起的报错以后,我们可以换回ES5的语法,当然这种不适合我们目前的情景。那有没有什么办法能把 ES6 在低版本浏览器中转译成ES5的语法呢?有。
目前有很多团队针对ES6的兼容问题,开发出了多种语法解析转换工具来把 ES6 转换成ES5,比较通用的解决方案有babel
、jsx
、es6-shim
等,接下来我们就使用babel
来做适配。
Babel
Babel 是一个转换编译器,它能将 ES6 转换成可以在浏览器中运行的代码。Babel 可以处理 ES6 的所有新语法,并且内置了 React JSX 扩展及 Flow 类型注解支持。
我们在HTML
页面中直接引用babel
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
然后在页面JS代码部分做如下修改
<script type="text/babel">
完成了上述操作以后,我们在浏览器里重新运行,这时候我们会发现如果页面只是使用了 ES6 的语法,上述转换是没有问题的,可以正常运行,但是如果使用了 ES6 的新增API,浏览器依然会报错。造成报错的原因就是 Babel默认只转换 ES6 的新语法(syntax),不转换新的API
我们需要使用babel-polyfill
实现对 ES6 新API的支持
babel-polyfill
Babel 默认只转码 ES6 的新语法(syntax),而不转换新的 API,比如 Set
、Maps
、Proxy
、Reflect
、Symbol
、Promise
等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign
、Array.from
)都不会转码。
如果想让这些方法运行,必须使用 babel-polyfill
,为当前环境提供一个中间层。
通过babel-polyfill
可以让我们使用如下新API:
- ArrayBuffer
- Array.from
- Array.of
- Array#copyWithin
- Array#fill
- Array#find
- Array#findIndex
- Function#name
- Map
- Math.acosh
- Math.hypot
- Math.imul
- Number.isNaN
- Number.isInteger
- Object.assign
- Object.getOwnPropertyDescriptors
- Object.is
- Object.entries
- Object.values
- Object.setPrototypeOf
- Promise
- Reflect
- RegExp#flags
- Set
- String#codePointAt
- String#endsWith
- String.fromCodePoint
- String#includes
- String.raw
- String#repeat
- String#startsWith
- String#padStart
- String#padEnd
- Symbol
- WeakMap
- WeakSet
进入项目文件夹,使用npm方式安装polyfill
:
npm install --save-dev babel-polyfill
在页面中引用:
<script type="text/javascript" src="node_modules/babel-polyfill/dist/polyfill.min.js"></script>
再运行页面,就不会有报错出现了,而且页面中使用新API的地方也完美的运行通过。