我看到这些术语作为DOM的全局环境可以互换使用。有什么区别(如果有的话),什么时候我应该使用它们?
window是实际的全局对象。
window
screen是屏幕,它包含关于用户显示的属性。
screen
document是DOM所在的地方。
document
window是主要的JavaScript对象根,也就是浏览器中的global object,它也可以被视为文档对象模型的根。你可以通过window来访问它。
global object
window.screen或screen是一个关于屏幕物理尺寸的小信息对象。
window.screen
window.document或document是潜在可见(或更好:呈现)的文档对象模型/DOM的主对象。
window.document
由于window是全局对象,你可以用属性名引用它的任何属性——所以你不必写下window.——它将由运行时计算出来。
window.
window包含了所有元素,所以你可以调用window.screen和window.document来获取这些元素。看看这个小提琴,漂亮地打印每个对象的内容:http://jsfiddle.net/JKirchartz/82rZu/
你也可以像这样在Firebug/开发工具中看到对象的内容:
console.dir(window); console.dir(document); console.dir(screen);
window是所有东西的根,screen只是屏幕尺寸,而document是顶级DOM对象。所以你可以把它想象成window就像一个超-document…
窗口是载入浏览器的第一个东西。这个窗口对象具有大多数属性,如长度,innerWidth, innerHeight,名称,如果它已关闭,它的父属性等等。
那么文档对象呢?文档对象是你的html、aspx、php或其他将被加载到浏览器中的文档。文档实际上是在窗口对象中加载的,并具有可用的属性,如标题、URL、cookie等。这到底是什么意思?这意味着如果你想访问窗口的属性,它就是window。属性,如果是document,它就是window。document。Property也可以简写为document。Property。
这似乎很简单。但是一旦IFRAME被引入会发生什么呢?
简单地说,下面会有更多的细节,
有关这些对象的详细信息,请参阅W3C和window0引用。这三者之间最基本的关系是每个浏览器选项卡都有自己的window,而window具有window.document和window.screen属性。浏览器选项卡的window是全局上下文,因此document和screen指向window.document和window.screen。关于这三个对象的更多细节在window1后面。
每个浏览器选项卡都有自己的顶级window对象。每个<iframe>(和已弃用的<frame>)元素也有自己的window对象,嵌套在父窗口中。每个窗口都有自己独立的全局对象。window.window总是引用window,但window.parent和window.top可能引用封闭窗口,从而访问其他执行上下文。除了下面描述的document和screen之外,window属性包括
<iframe>
<frame>
window.window
window.parent
window.top
setTimeout()
setInterval()
location
history
back()
forward()
navigator
每个window对象都有一个要呈现的document对象。这些对象之所以容易混淆,部分原因是HTML元素在分配唯一id时被添加到全局对象中。例如,在HTML片段中
<body> <p id="holyCow"> This is the first paragraph.</p> </body>
段落元素可以被下列任意元素引用:
window.holyCow
window["holyCow"]
document.getElementById("holyCow")
document.querySelector("#holyCow")
document.body.firstChild
document.body.children[0]
window对象还有一个screen对象,其属性描述物理显示:
屏幕属性width和height是全屏
width
height
屏幕属性availWidth和availHeight省略工具栏
availWidth
availHeight
显示呈现文档的屏幕部分是JavaScript中的视窗,这可能会令人困惑,因为在讨论与操作系统的交互时,我们将应用程序的屏幕部分称为窗口。任何document元素的getBoundingClientRect()方法将返回一个具有top、left、bottom和right属性的对象,这些属性描述了元素在视口中的位置。
getBoundingClientRect()
top
left
bottom
right
在控制台,通过编写
this
或
然后按回车键,我们就可以访问浏览器中的顶层对象window——甚至也可以使用窗口的这两个属性之一:
parent
self
globalThis
甚至两者结合。
实际上,检查上述任意一对将返回true:
true
this === window // true
this === window
window === globalThis // true
window === globalThis
this === self // true
this === self
parent === window // true
parent === window
top === parent // true
top === parent
甚至是它们的多种组合,这是可能的,因为
window.window === window // true
window.window === window
因为window也是自有属性,所以我们甚至可以写window.window.window === window,甚至像window.window.self.top.parent.globalThis === window这样的东西,所有这些都返回true。
window.window.window === window
window.window.self.top.parent.globalThis === window
唯一的例外是我们不能在最后一个位置使用this,因为它不是财产(因此window.window.this === window // false,因为实际上window.this === undefined // 真正的,因为window没有这样的这属性)。
window.window.this === window
window.this === undefined
因此,我们不能写self.this, top.this, parent.this, top.this0,唯一可能的方法是在最后一个位置用top.this1代替它,作为window的属性,就像top.globalThis等。
self.this
top.this
parent.this
top.globalThis
当拥有一个带有帧的网页时,每个帧文档将属于一个单独的窗口对象,该对象将窗口分离为前面所示的顶层窗口的子对象——你可以简单地在一个带有帧的平台上测试(如jsfiddle, codepen, false0),在帧中写入和执行console.log(window.parent === window);将返回false,而如果你直接在控制台中写入window.parent === window将返回true。在框架中,window.parent将访问全局窗口(框架窗口对象的父对象显然与框架窗口对象本身不相同)。你可以检查每一个这些窗口的内容分别运行在框架的代码(并看到结果如下):
false
console.log(window.parent === window);
window.parent === window
console.log(window.document.all); // HTMLAllCollection(6) [html, head, body, p#demo,按钮,脚本,demo: p#demo]
console.log(window.document.all);
分别
console.log(window.parent.document.all); / / HTMLAllCollection (335) [html,头,脚本,脚本,标题、元,元,元,元,元,元,元,元,链接,链接,链接,链接,脚本,脚本,脚本,脚本,脚本,脚本,脚本,脚本,脚本,风格,脚本,脚本,脚本,脚本,风格,脚本,元,元,元,元,元,元,元,元,脚本,argprec0, argprec1,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接、脚本、链接、脚本链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,脚本链接, , ...] - __ ABC2
console.log(window.parent.document.all);
做同样的检查,但这次是从控制台:
window.document.all / / HTMLAllCollection (335) [html,头,脚本,脚本,标题、元,元,元,元,元,元,元,元,链接,链接,链接,链接,脚本,脚本,脚本,脚本,脚本,脚本,脚本,脚本,脚本,风格,脚本,脚本,脚本,脚本,风格,脚本,元,元,元,元,元,元,元,元,脚本,argprec0, argprec1,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接、脚本、链接、脚本链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,链接,脚本,脚本链接, , ...] - __ ABC2
window.document.all
正如我们所看到的,控制台(用F12打开它)可以访问最顶层的窗口作用域/上下文(而下面的框架包含在它自己有限的上下文/范围中),因此它一次显示所有元素。这和我们一开始提到的环境是一样的。
因此,我们可以在控制台上访问document -查看它的结构-只需使用window.document,我们可以通过单击#document查看其中的所有内容。同样,我们将在那里看到文档的表示而不是文档本身。在控制台中看到的表示形式是DOM,是原始文件的模型,并通过以某种方式加上改善来创建,在需要时,由浏览器的JavaScript引擎从原始文档的源代码解析出的数据。源代码是不可变的(浏览器不会改变从internet接收到的html文件),而DOM是可变的(在设备硬件上呈现页面之前或之后运行到浏览器中的JavaScript代码进行了更改)。为了清晰起见:我们在控制台中看到的是DOM,在浏览器中看到的是渲染,在源代码中看到的是原始文件。他们不一样,每个人都和另外两个不一样。
#document
为了帮助您理解,我将把这个过程与“真实生活”中的客户端软件进行比较。一些有才华的人参观卢浮宫,看到蒙娜丽莎的画(源代码文件)。蒙娜丽莎在游客心目中的形象是不是一样的是达芬奇的原画,这只是一种心理表征。然后,有才华的游客将在他的大脑中重新创造一些“自己的”。蒙娜丽莎,在这里和那里改进什么应该改进或改变,最后画回家时在画布上所有的原始图像的颜色加上更多。
因此,我们有3个“实体”(a - html文件,不可变,包含源代码,b -它的一个表示,在源代码被解析和“理解”后创建。c -显示在屏幕上的渲染本身)。所提到的主要改进可以像在源文件中缺少的地方添加结束标记,根据源文件中包含的脚本指令在Model中添加或删除元素,更改它们,请求进一步的资源(如图像、字体、css文件、用作最终完整页面资产的媒体文件等)等等。
尽管名字很相似,与特定文档相关的窗口和浏览器窗口不应该被认为是同一件事,第一个被附加到后一个(并且可以作为它的属性访问)。类似地,当有多个浏览器窗口(例如10个实例)时,每个窗口都有多个选项卡(或没有),这些选项卡附加到浏览器窗口,它们的对象可以通过window[0]直到window[9]访问。
window[0]
window[9]
关于屏幕,浏览器客户端是一个软件(代码),它运行和执行另一个软件(源代码),目的是最终通过几层在硬件设备(监视器/屏幕)上显示该(第二个)代码。出于这个目的,浏览器软件实际上也有自己独立的编程例程,能够与操作系统交互,以检测屏幕分辨率,大小,颜色深度,一些设置和更多,因此它充当操作系统和文件之间的桥梁,意味着显示在其呈现区域。
使用console.log(window.screen)将返回浏览器从操作系统收集到的关于设备监视器的详细信息(并存储在其内存中),例如{availWidth: 1920, availHeight: 1040, width: 1920, height: 1080, colorDepth: 24, …}
console.log(window.screen)
{availWidth: 1920, availHeight: 1040, width: 1920, height: 1080, colorDepth: 24, …}
可以使用一个更简单的代码(不需要总是写window字)并提取例如设备的宽度:
console.log(screen.width) // 1920
例如,您甚至可以使用这些数据来执行一些纯粹基于JavaScript而不使用CSS的伪媒体查询
function goMobile() { if (screen.width < 900) {location.replace("/index-mobile.html");} } goMobile();
结论:window和document属于DOM, screen不属于DOM。你需要所有这些属性,但是因为document和screen都是window对象的属性,所以你可以直接在代码中调用它们(缩短代码)。而且,screen是关于硬件部分的,而不是任何浏览器的矩形可用区域,它没有document.body的意义。最多,你可以使用screen数据来优化你的加载页面,例如限制资产下载以获得更好的移动设备体验等等。
document.body