如何从文档对象获取窗口对象?

70

我可以获取 window.document,但如何获取 document.window?我需要知道如何在所有浏览器中实现。


2
敢问为什么?窗口是一个始终可用的对象,而且一个窗口中永远不会有多于1个文档,可以说是一对一的关系... - Colin
5
因为我在多个iframe中使用了prototype,如果元素在错误的作用域中扩展,则各种元素方法会在IE或Safari中出现故障。我已经修改了一些内容以修复这个问题,但解决方案的一部分需要我找到元素所在的窗口。 - Joren
1
@Joren,请考虑更改为已接受的答案。 - Kijewski
6个回答

125

如果你确定它是一个窗口并且可以跳过IE 9之前的Microsoft浏览器,那么你可以选择 document.defaultView


7
是的。只需记住,按照规范,document.defaultView 不必与 window 是同一个对象(实际上在某些旧版客户端中,如 Safari 2.x 中,它们是不同的)。 - kangax
在Firefox中,对于XUL文档也能很好地工作!谢谢 :) - macguru2000
4
doc.parentWindow || doc.defaultView可以在旧版的IE和Safari浏览器中使用。该代码段用于获取当前文档的窗口对象。 - Stefan Steiger
1
我不知道为什么这个回答没有被采纳?我在Stack Overflow看到很多Javascript问题都是这种格式...这让我相信当最初发表该问题时,可能默认视图要么不存在,要么并未得到广泛实施...只希望有一种方式可以使用标签来标记答案的信息...我经常看到这种情况。也许是Stack Overflow的做法有问题,它似乎认为任何问题如果问的是相同/类似的问题就是重复的。我不同意...虽然措辞相同/类似,但采纳的答案通常会过时。 - ycomp

18

跨浏览器的解决方案比较复杂,以下是 dojo 的实现方式(来自 window.js::get()):

// In some IE versions (at least 6.0), document.parentWindow does not return a
// reference to the real window object (maybe a copy), so we must fix it as well
// We use IE specific execScript to attach the real window reference to
// document._parentWindow for later use
if(has("ie") && window !== document.parentWindow){
    /*
    In IE 6, only the variable "window" can be used to connect events (others
    may be only copies).
    */
    doc.parentWindow.execScript("document._parentWindow = window;", "Javascript");
    //to prevent memory leak, unset it after use
    //another possibility is to add an onUnload handler which seems overkill to me (liucougar)
    var win = doc._parentWindow;
    doc._parentWindow = null;
    return win; //  Window
}

return doc.parentWindow || doc.defaultView; //  Window

has("ie") 返回 true 表示当前浏览器为 IE(否则返回 false)


3

这是我采用的解决方案。它可以工作,但我不太喜欢它。

getScope : function(element) {
    var iframes = top.$$('iframe');
    var iframe = iframes.find(function(element, i) {
        return top[i.id] ? top[i.id].document == element.ownerDocument : false;
    }.bind(this, element));
    return iframe ? top[iframe.id] : top;
}   

这个问题只在IE浏览器中存在吗?在FF\Saf\IE\Chrome中似乎都能正常工作。但其他浏览器都会自动扩展元素到正确的范围,所以只有在IE中需要这样做。 - Joren

2

我选择使用来自@angular/platform-browserDOCUMENT令牌进行注入:

import { DOCUMENT } from '@angular/platform-browser'

然后访问父元素:

constructor(@Inject(DOCUMENT) private document: any) {
}

public ngOnInit() {
  // this.document.defaultView || this.document.parentWindow;
}

0
首先,让我们明确一点。在处理框架、内嵌框架和多个窗口时,这种情况通常是必要的,如果你只能获取到来自于另一个窗口的文档,那么"窗口就是全局对象"这个答案无法令人满意。
其次,不幸的是没有一种直接的方式来获取窗口对象,只有间接的方法。
主要的机制是使用window.name。当从父窗口创建一个窗口或者框架时,通常可以给它一个唯一的名字。该窗口内部的任何脚本都可以访问window.name。窗口外部的任何脚本都可以获取所有子窗口的window.name。
要更具体地了解情况,则需要更多的信息。然而,在任何子脚本可以与父脚本进行通信或反之的情况下,它们始终可以通过名称互相识别,这通常已经足够了。

-6

Window对象是JavaScript层次结构中的顶级对象,因此只需将其称为window

编辑:Promote JS之前的原始答案。Mozilla开发者网络上的JavaScript技术概述说:

在浏览器环境中,这个全局对象是window对象。

编辑2: 在阅读作者对问题的评论(并获得了负评)后,似乎与iframe的文档窗口有关。查看window.parentwindow.top,并将它们与您的文档窗口进行比较。

if (window.parent != window.top) {
  // we're deeper than one down
}

8
在使用 open() 打开新窗口后,新窗口的 window 对象与原来的 opener 窗口的不同。如果你从某个函数接收到一个 document(或任何 Node),可能需要使用原始窗口。(哇,这是非常久远的内容了。) - Rudie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接