如果没有被浏览器阻止,主 html 文档中的 JavaScript 代码可以访问其 iframe 中的代码和数据,反之亦然。然而,性能呢?跨 iframe 边界是否存在性能损失?
我做了一个简单的测试,发现它依赖于浏览器:
- chrome 28:从主文档调用 iframe 中的函数与在主文档中调用函数一样快。
- firefox 23:在 iframe 中调用函数要慢得多(~6x)。
- IE 11 预览:在 iframe 中调用函数要慢得多(~3.5x),但比 firefox 好。
我想知道是什么让这些不同?主文档和 iframe 中的代码是否在同一个 JavaScript 虚拟机中运行?
我们能否期望 Firefox 和 IE 在不久的将来减少甚至消除这些性能损失?
我的测试代码如下:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Calc in iframe</title>
</head>
<body>
<button onclick="testCalcIFrame()">testCalcIFrame</button>
<button onclick="testCalc()">testCalc</button>
<button onclick="iwin.testCalcAllIframe()">testCalcAllIframe</button>
<iframe id="iframe" style="display:none;"></iframe>
<script>
var iwin = document.getElementById('iframe').contentWindow;
iwin.document.open('text/html');
iwin.document.close();
//Copy functions calc() and testCalcAllIframe() into the iframe.
iwin.eval(calc.toString());
iwin.eval(testCalcAllIframe.toString());
var icalc = iwin.calc;
var arrLength = 1000 * 1000;
var arr = new Array(arrLength);
for (var i = 0; i < arrLength; i++)
arr[i] = i;
function calc() {
var n = 0;
for (var i = 0; i < 2; i++) {
n += Math.round(arguments[i] / 3);
}
return n;
}
//test calling calc() in the main document
function testCalc() {
var t1 = performance.now();
var r = arr.reduce(calc);
console.log('testCalc(' + arr.length + '):time:' + (performance.now() - t1) + ', result:' + r);
}
//test calling calc() in the iframe
function testCalcIFrame() {
var t1 = performance.now();
var r = arr.reduce(icalc);
console.log('testCalcIFrame(' + arr.length + '):time:' + (performance.now() - t1) + ', result:' + r);
}
function testCalcAllIframe() {
var arr2 = new Array(1000 * 1000);
for (var i = 0; i < arr2.length; i++)
arr2[i] = i;
var t1 = performance.now();
var r = arr2.reduce(calc);
console.log('testCalcAllIframe(' + arr2.length + '):time:' + (performance.now() - t1) + ', result:' + r);
}
</script>
</body>
</html>
要尝试测试代码,请在浏览器中打开开发人员工具的控制台,然后按“testCalcIFrame”测试调用 iframe 中的函数,然后按“testCalc”测试调用主文档中的函数。
更新:我尝试将脚本元素注入 iframe 而不是使用 eval(),正如 Jan Dvorak 所建议的:
//iwin.eval(...) replaced by:
var iscript = iwin.document.createElement('script');
iwin.document.body.appendChild(iscript);
iscript.textContent = calc.toString() + '\n' + testCalcAllIframe.toString();
但是,性能几乎与使用 eval() 相同。