如何获取对iframe的窗口对象的引用iframe的onload处理程序从父窗口创建 [英] How to get a reference to an iframe's window object inside iframe's onload handler created from parent window
问题描述
- 我有一个HTML文档,使用JavaScript创建一个空的iframe
- JavaScript创建一个函数,并将该函数的引用附加到iframe的文档对象(使用
doc.open()
获取引用文档) - 然后,该函数作为iframe文档的
onload
处理程序附加(通过写入< ; body onload =...>
进入iframe。
现在我陷入了什么是在onload处理程序(运行时)中的全局(窗口)和文档对象与通过脚本节点添加的JavaScript运行的相同对象不同。
这里是HTML:
<!doctype html>
< html>
< head>
< script>
(function(){
var dom,doc,where,iframe;
iframe = document.createElement('iframe ');
iframe.src =javascript:false;
其中= document.getElementsByTagName('script')[0];
where.parentNode.insertBefore(iframe,where);
doc = iframe.contentWindow.document;
var _doc = document;
doc.open()._ l = function(){
//窗口对象应该是文档在
中的一个window.vanishing_global = new Date()。的getTime();
var js = this.createElement(script);
js.src ='test-vanishing-global.js?'+ window.vanishing_global;
window.name =foobar;
this.foobar =foobar:+ Math.random();
document.foobar =barfoo:+ Math.random();
//`this`应该是文档对象,但它不是
console.log(this == document:%s,this == document);
console.log(this == doc:%s,this == doc);
//根据@ Ian的评论添加下一行两行
console.log(_ doc == document:%s,_doc == document);
console.log(_ doc == doc:%s,_doc == doc);
console.log(name:+ window.name +\\\
+window.vanishing_global:+ window.vanishing_global +\\\
typeof window.vanishing_global:+ typeof window .vanishing_global +\\\
document.foobar:+ document.foobar);
this.body.appendChild(js);
};
doc.write('< body onload =document._l();>< / body>');
doc.close();
})();
< / script>
< / head>
< body>
< / body>
< / html>
这里是 test-vanishing-global.js
:
console.log(name:+ window.name +\\\
+window.vanishing_global: + window.vanishing_global +\\\
typeof window.vanishing_global:+ typeof window.vanishing_global +\\\
document.foobar:+ document.foobar);
说明:
把这两个文件进入目录,并在浏览器中打开HTML(在最新的Chrome和Firefox中进行测试,同样的结果)。
这是我得到的输出:
this == document:false
/ pre>
this == doc:true
_doc == document:true
_doc == doc:false
名称:foobar
window.vanishing_global:1366037771608
typeof window.vanishing_global:number
document.foobar:barfoo:0.9013048021588475
名称:
window.vanishing_global:undefined
typeof window.vanishing_global:undefined
document.foobar:foobar:0.5015988759696484
处理程序内的
这个
对象应该是文档对象。它是一个文档对象,但不是与它在里面运行的文档相同的文档对象(它也和父文档不一样)。处理程序中的窗口对象也不同于在页面中加载的JavaScript中运行的窗口对象。
最后我的问题:
$ b有没有人知道发生了什么,以及如何获得对实际窗口对象的引用,或者至少从同一个全局上下文声明和引用全局变量?
脚注:
由于它们位于同一个域,因此此iframe不存在跨域问题。如果有人设置
document.domain
,但是在这个示例代码中没有完成,则会出现问题。解决方案您正在声明父页面中的所有内容。因此,引用
窗口
和文档
是父页面。如果要对iframe
执行任务,请使用iframe.contentWindow || iframe
访问其窗口
和iframe.contentDocument || iframe.contentWindow.document
访问其文档
。
有一个字是什么发生,可能是词汇范围:什么是词汇范围?
范围的唯一上下文是这个。在你的例子中,方法的所有者是
doc
,这是iframe
的文档
。除此之外,在该函数中使用已知对象访问的任何内容都是父级(如果未在函数中声明)。如果函数在不同的地方被声明,那么它将是一个不同的故事,但是它在父页面中声明。
这是我如何写:
(function(){
var dom,win,doc,where,iframe;
iframe = document.createElement('iframe');
iframe.src =javascript:false;
其中= document.getElementsByTagName('script')[0];
where.parentNode.insertBefore(iframe,where);
win = iframe.contentWindow || iframe;
doc = iframe.contentDocument || iframe.contentWindow.document;
doc.open();
doc._l =(function(w,d){
return function(){
w.vanishing_global = new Date()。getTime ;
var js = d.createElement(script);
js.src ='test-vanishing-global.js?'+ w.vanishing_global;
w.name =foobar;
d.foobar =foobar:+ Math.random();
d.foobar =barfoo:+ Math.random();
d.body.appendChild(js);
};
})(win,doc);
doc.write('< body onload =document._l();>< / body>');
doc.close();
})();
win
和doc
作为w
和d
不是必需的,它可能会它因为对范围的误解而变得混乱。这样,它们是参数,您必须引用它们才能访问iframe
的内容。如果您想要访问父母,则仍然使用窗口
和文档
。
我不知道在
文档中添加方法的含义是什么?
(doc
这种情况),但在win
上设置_l
方法可能更有意义。这样就可以运行没有前缀的东西,例如< body onload =_ l();>< / body>
Before I paste any code, here's the scenario:
- I have an HTML document that creates an empty iframe using JavaScript
- The JavaScript creates a function and attaches a reference to that function to the iframe's document object (using
doc.open()
to get a reference to the document)- The function is then attached as an
onload
handler for the iframe's document (by writing<body onload="...">
into the iframe.Now what has me stumped is that the global (window) and document objects inside the onload handler (while it's running) is different from the same objects run through JavaScript added via script nodes.
Here's the HTML:
<!doctype html> <html> <head> <script> (function(){ var dom,doc,where,iframe; iframe = document.createElement('iframe'); iframe.src="javascript:false"; where = document.getElementsByTagName('script')[0]; where.parentNode.insertBefore(iframe, where); doc = iframe.contentWindow.document; var _doc = document; doc.open()._l=function() { // the window object should be the one that doc is inside window.vanishing_global=new Date().getTime(); var js = this.createElement("script"); js.src = 'test-vanishing-global.js?' + window.vanishing_global; window.name="foobar"; this.foobar="foobar:" + Math.random(); document.foobar="barfoo:" + Math.random(); // `this` should be the document object, but it's not console.log("this == document: %s", this == document); console.log("this == doc: %s", this == doc); // the next two lines added based on @Ian's comment below console.log("_doc == document: %s", _doc == document); console.log("_doc == doc: %s", _doc == doc); console.log("name: " + window.name + "\n" + "window.vanishing_global: " + window.vanishing_global + "\ntypeof window.vanishing_global: " + typeof window.vanishing_global + "\ndocument.foobar: " + document.foobar); this.body.appendChild(js); }; doc.write('<body onload="document._l();"></body>'); doc.close(); })(); </script> </head> <body> </body> </html>
And here's
test-vanishing-global.js
:console.log("name: " + window.name + "\n" + "window.vanishing_global: " + window.vanishing_global + "\ntypeof window.vanishing_global: " + typeof window.vanishing_global + "\ndocument.foobar: " + document.foobar);
Instructions:
Put these two files into a directory, and open the HTML in a browser (tested in latest Chrome and Firefox, same result in both).
This is the output I get:
this == document: false this == doc: true _doc == document: true _doc == doc: false name: foobar window.vanishing_global: 1366037771608 typeof window.vanishing_global: number document.foobar: barfoo:0.9013048021588475 name: window.vanishing_global: undefined typeof window.vanishing_global: undefined document.foobar: foobar:0.5015988759696484
The
this
object inside the handler should be either the document object. It is a document object, but not the same document object as the document that it runs inside (it's also not the same as the parent document). The window object inside the handler is also not the same as the window object that runs in JavaScript loaded in the page.So finally my question:
Does anyone know what's going on, and how I can either get a reference to the actual window object, or at least declare and reference global variable from the same global context?
Footnotes:
There are no cross-domain issues with this iframe since they're on the same domain. There is an issue if someone sets
document.domain
, but that's not being done in this example code.解决方案You're declaring everything in the parent page. So the references to
window
anddocument
are to the parent page's. If you want to do stuff to theiframe
's, useiframe.contentWindow || iframe
to access itswindow
, andiframe.contentDocument || iframe.contentWindow.document
to access itsdocument
.There's a word for what's happening, possibly "lexical scope": What is lexical scope?
The only context of a scope is this. And in your example, the owner of the method is
doc
, which is theiframe
'sdocument
. Other than that, anything that's accessed in this function that uses known objects are the parent's (if not declared in the function). It would be a different story if the function were declared in a different place, but it's declared in the parent page.This is how I would write it:
(function () { var dom, win, doc, where, iframe; iframe = document.createElement('iframe'); iframe.src = "javascript:false"; where = document.getElementsByTagName('script')[0]; where.parentNode.insertBefore(iframe, where); win = iframe.contentWindow || iframe; doc = iframe.contentDocument || iframe.contentWindow.document; doc.open(); doc._l = (function (w, d) { return function () { w.vanishing_global = new Date().getTime(); var js = d.createElement("script"); js.src = 'test-vanishing-global.js?' + w.vanishing_global; w.name = "foobar"; d.foobar = "foobar:" + Math.random(); d.foobar = "barfoo:" + Math.random(); d.body.appendChild(js); }; })(win, doc); doc.write('<body onload="document._l();"></body>'); doc.close(); })();
The aliasing of
win
anddoc
asw
andd
aren't necessary, it just might make it less confusing because of the misunderstanding of scopes. This way, they are parameters and you have to reference them to access theiframe
's stuff. If you want to access the parent's, you still usewindow
anddocument
.I'm not sure what the implications are of adding methods to a
document
(doc
in this case), but it might make more sense to set the_l
method onwin
. That way, things can be run without a prefix...such as<body onload="_l();"></body>
这篇关于如何获取对iframe的窗口对象的引用iframe的onload处理程序从父窗口创建的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!