没有什么可以阻止您将字符串化函数作为消息后事件数据传递。对于任何函数声明,如
function doSomething(){
alert("hello world!");
}
你可以encodeURI
解释它的字符串:
console.log(encodeURI(doSomething.toString()));
//function%20doSomething()%20%7B%0A%20%20%20%20alert(%22hello%20world!%22);%0A%7D
然后它可以作为闭包的一部分执行——不要过于想象
eval('('+decodeURI(strCallback)+')();');
在没有跨框架架构的情况下有一个小提琴的概念证明 - 我会看看我是否可以组合一个 postMessage 版本,但托管 w/jsfiddle 并非易事
更新
正如所承诺的,一个完整的模型可以工作(下面的链接)。通过正确的event.origin
检查,这将是非常难以穿透的,但我知道我们的安全团队永远不会eval
像这样投入生产:)
给定选项,我建议在两个页面之间对功能进行规范化,以便只需要传递参数消息(即传递参数而不是函数);但是,在某些情况下,这是首选方法。
父代码:
document.domain = "fiddle.jshell.net";//sync the domains
window.addEventListener("message", receiveMessage, false);//set up the listener
function receiveMessage(e) {
try {
//attempt to deserialize function and execute as closure
eval('(' + decodeURI(e.data) + ')();');
} catch(e) {}
}
框架代码:
document.domain = "fiddle.jshell.net";//sync the domains
window.addEventListener("message", receiveMessage, false);//set up the listener
function receiveMessage(e) {
//"reply" with a serialized function
e.source.postMessage(serializeFunction(doSomething), "http://fiddle.jshell.net");
}
function serializeFunction(f) {
return encodeURI(f.toString());
}
function doSomething() {
alert("hello world!");
}
原型样机:父代码和iframe 代码。