使用Jasmine测试时Array.from()无法正常工作的问题求助
解决Jasmine测试中
Array.from()报TypeError的问题 嘿,我之前也碰到过类似的情况——明明在现代浏览器和Node里Array.from()用得好好的,一跑Jasmine测试就报错说它是undefined。大概率是测试环境的锅,我给你梳理下可能的原因和解决办法:
为什么会出现这个问题?
最常见的元凶是PhantomJS——很多老项目的Jasmine会用它当无头浏览器跑测试,但PhantomJS基于非常老旧的WebKit内核,根本不支持ES6的Array.from()方法。哪怕你的Node和Firefox都是新版的,测试环境的JS引擎跟不上,照样会报错。
另外一种可能是你的测试代码没经过转译,ES6特性直接跑到不支持的环境里了。
怎么解决?
方案1:换掉PhantomJS(推荐)
PhantomJS早就停止维护了,完全没必要再用它。换成现代的无头浏览器就行:
- Chrome Headless:直接用Chrome的无头模式,支持所有ES6+特性,Jasmine很容易配置它。
- Firefox Headless:同样靠谱,兼容性拉满。
方案2:给Array.from()加Polyfill
如果暂时没法换测试环境,那就给旧环境补个Polyfill,让它认识Array.from()。把这段MDN官方的Polyfill代码放到你的测试入口文件,或者被测试模块的最顶部:
// Array.from Polyfill (来自MDN) if (!Array.from) { Array.from = (function () { var toStr = Object.prototype.toString; var isCallable = function (fn) { return typeof fn === 'function' || toStr.call(fn) === '[object Function]'; }; var toInteger = function (value) { var number = Number(value); if (isNaN(number)) { return 0; } if (number === 0 || !isFinite(number)) { return number; } return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); }; var maxSafeInteger = Math.pow(2, 53) - 1; var toLength = function (value) { var len = toInteger(value); return Math.min(Math.max(len, 0), maxSafeInteger); }; return function from(arrayLike/*, mapFn, thisArg */) { var C = this; var items = Object(arrayLike); if (arrayLike == null) { throw new TypeError("Array.from requires an array-like object - not null or undefined"); } var mapFn = arguments.length > 1 ? arguments[1] : void undefined; var T; if (typeof mapFn !== 'undefined') { if (!isCallable(mapFn)) { throw new TypeError('Array.from: when provided, the second argument must be a function'); } if (arguments.length > 2) { T = arguments[2]; } } var len = toLength(items.length); var A = isCallable(C) ? Object(new C(len)) : new Array(len); var k = 0; var kValue; while (k < len) { kValue = items[k]; if (mapFn) { A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k); } else { A[k] = kValue; } k += 1; } A.length = len; return A; }; }()); }
加了这个之后,旧环境就能像现代浏览器一样正常使用Array.from()了。
方案3:用Babel转译测试代码
如果你的项目本来就用Babel处理ES6,那得确保测试代码也被转译。可以在Jasmine配置里加Babel预处理,或者用@babel/preset-env自动把不支持的特性转成ES5代码。
验证一下
按上面的方法调整后,再跑你的测试代码:
var t = [1, 2, 3]; console.log(Array.from(t)); console.log(Array.from(baseObject.childNodes));
应该就能顺利执行,不会再报那个烦人的TypeError啦。
内容的提问来源于stack exchange,提问作者MVanOrder
相关产品推荐
相关产品推荐

