最近遇到一个bug,在调用APP的js接口时,有一个接口须要传递函数名过去,在js中我已经传递了函数名过去,可是在部分Android6.0及如下的安卓手机以及iOS 8上发现,APP并无收到我传递函数名,函数名为空,百思不得其解,后来浏览了MDN上对function.name的解释后,修复了这个bug。vue
项目基于VUE2.X开发,语法大部分使用ES6。webpack
具体以下:es6
//须要传递给APP的函数 let callbackFn = { fn: () => { //... } } //调用APP的js接口 nativeAPI.call(callbackFn.fn.name)
简单的逻辑如上所示,可是在与安卓开发和iOS开发联调时,他们告诉我,在低版本手机中,我传过去的回调函数名称callbackFn.fn.name值为空字符串!就是说我并有获取到function的名字!web
通过思考,尝试了如下几种办法浏览器
通过检查,webpack中确实引入了babel-polyfillbabel
module.exports = { context: path.resolve(__dirname, '../'), entry: { app: ["babel-polyfill", "./src/main.js"] }, ...
.babelrc文件中配置以下app
{ "presets": [ ["env", { "modules": false, "targets": { "browsers": ["last 2 versions", "safari >= 7"] } }], "stage-0" ], "plugins": ["transform-vue-jsx", "transform-runtime"] }
结果:然而发现并无解决问题。函数
将callbackFn改成code
var callbackFn = { fn: function() { //... } }
结果:仍是不行orm
由于js的混淆会改变变量名,为了不可能发生的错误,将回调函数单独挪到static文件夹中,不参与打包
结果:失败
由于步骤3的失败,让我感受问题可能没有出在打包过程当中,直觉告诉我,我获取函数名的方法(function.name)可能有问题,因而去MDN搜索了一下,确实有所收获。
Function.name - JavaScript | MDN
推断函数名称
变量和方法能够从句法位置推断匿名函数的名称(ECMAScript 2015中新增)。
var f = function() {}; var object = { someMethod: function() {} }; console.log(f.name); // "f" console.log(object.someMethod.name); // "someMethod"
注意描述:(ECMAScript 2015中新增)
这让我极度怀疑,在函数名的传递过程当中,可能浏览器并无帮我“推断”,也许取到的仍是匿名函数,因此我获取函数名时,获取的是空字符串,因而我开始手动改写,代码以下:
//声明函数 function callbackFn() { //... } //获取函数名称 let callbackName = callbackFn.name //调用APP的js接口 nativeAPI.call(callbackName)
至此,这个问题解决了。
总结:1.须要传递函数名的时候,最好显式的声明函数,不然依赖浏览器推断函数名的话不可靠,浏览器种类众多,不能肯定是否实现了这个标准;2.尽可能避免使用传递函数名这种方式来作为回调函数,由于通过压缩混淆时会改变函数名,这种作法不可靠。