1. BOM 概述

BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window。
BOM 由一系列相关的对象构成,并且每个对象都提供了很多方法与属性。
BOM 缺乏标准,JavaScript 语法的标准化组织是 ECMA,DOM 的标准化组织是 W3C,BOM 最初是Netscape 浏览器标准的一部分。

image.png

1.2 BOM 的构成

image.png
window 对象是浏览器的顶级对象,它具有双重角色

  • 它是 JS 访问浏览器窗口的一个接口。
  • 它是一个全局对象。定义在全局作用域中的变量、函数都会变成 window 对象的属性和方法。

在调用的时候可以省略 window,如 alert()、prompt() 等

2. window对象

都可以不通过window.访问

1. 窗口

关系

  • window.parent 当前窗口的父窗口对象,如果没有返回自身
  • window.top 顶层窗口对象
  • windows.self 自身对象

大小

  • outerWidth 和 outerHeight 返回浏览器窗口自身的大小
  • innerWidth 和 innerHeight 返回浏览器窗口中页面视口的大小

位置

  • window.pageXoffset / window.scrollX 页面水平方向滚动的像素值。
  • window.pageYoffset / window.scrollY 页面垂直方向滚动的像素值。

    pageXOffset 属性是 scrollX 属性的别名,为了跨浏览器兼容性,请使用 window.pageXOffset 代替 window.scrollX。另外,旧版本的 IE(<9)两个属性都不支持

滚动

  • scroll / scrollTo
  • scrollBy

这3个方法都接收表示相对 视口距离的和坐标,这两个参数在前两个方法中表示要滚动到的坐标,在最后一个方法中表示滚动的距 离

  1. // 相对于当前视口向右滚动40像素
  2. window.scrollBy(40, 0);
  3. // 滚动到页面左上角
  4. window.scrollTo(0, 0);
  5. // 除了提供偏移值,还可以通过 behavior 属性,告诉浏览器是否平滑滚动。
  6. window.scrollTo({
  7. left: 100,
  8. top: 100,
  9. behavior: 'smooth'
  10. });

导航

  • window.open()

window.open() 方法可以用于导航到指定URL,也可以用于打开新浏览器窗口。这个方法接收3个参数:要加载的URL、目标窗口、特性字符串,并返回新窗口对象的引用

  1. window.open("http://www.wrox.com/",
  2. "topFrame",
  3. "height=400,width=400,top=10,left=10,resizable=yes");

如果有一个窗口名叫 “topFrame” ,则这个窗口就会打开这个URL;否 则就会打开一个新窗口并将其命名为 “topFrame” 。第二个参数也可以是一个特殊的窗口名,比如 _self_parent_top_blank

2. 常见事件

2.1 窗口加载事件

  1. window.onload = function(){}
  2. //或者
  3. window.addEventListener("load",function(){});

window.onload 是窗口 (页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS 文件等), 就调用的处理函数。

注意:
1. 有了window.onload就可以把 JS 代码写到页面元素的上方,因为 onload是等页面内容全部加载完毕,再去执行处理函数。
2.window.onload传统注册事件方式 只能写一次,如果有多个,会以最后一个 window.onload为准。
3. 如果使用 addEventListener 则没有限制。

  1. document.addEventListener('DOMContentLoaded',function(){})
  • DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等。IE9以上才支持
  • 如果页面的图片很多的话, 从用户访问到onload触发可能需要较长的时间, 交互效果就不能实现,必然影响用户的体验,此时用 DOMContentLoaded事件比较合适。

2.2 调整窗口大小事件

  1. window.onresize = function(){}
  2. window.addEventListener("resize",function(){});

window.onresize是调整窗口大小加载事件, 当触发时就调用的处理函数。

注意:
1. 只要窗口大小发生像素变化,就会触发这个事件。
2. 我们经常利用这个事件完成响应式布局。window.innerWidth当前屏幕的宽度

3. 定时器

  • setTimeout() 定时器

    1. setTimeout(调用函数, [延迟的毫秒数]);
  • 停止 setTimeout() 定时器

    1. clearTimeout(timeoutID)
    2. //里面的参数就是定时器的标识符 。
  • setInterval() 定时器

setInterval() 方法重复调用一个函数,每隔这个时间,就去调用一次回调函数。

  1. setInterval(回调函数, [间隔的毫秒数]);
  • 停止 setInterval() 定时器
    1. clearInterval(intervalID);
    2. //里面的参数就是定时器的标识符 。

    所有超时执行的代码(函数)都会在全局作用域中的一个匿名函数中运行,因此函数中的 this 值在非严格模式下始终指向 window ,而在严格模式下是 undefined 。如果给 setTimeout() 提供了一个箭头函数,那么 this 会保留为定义它时所在的词汇作用域。


3. location 对象

3.1 什么是 location 对象

location 是最有用的BOM对象之一,提供了当前窗口中加载文档的信息,以及通常的导航功能。 这个对象独特的地方在于,它既是 window 的属性,也是 document 的属性。也就是说, window.location 和 document.location 指向同一个对象。
location 对象不仅保存着当前加载文档的信息,也保存着把URL解析为离散片段后能够通过属性访问的信息。

3.2 location 对象的属性

image.png

  1. // 当前网址为
  2. // http://user:passwd@www.example.com:4097/path/a.html?x=111#part1
  3. document.location.href // 整个url
  4. // "http://user:passwd@www.example.com:4097/path/a.html?x=111#part1"
  5. document.location.protocol //当前 URL 的协议,包括冒号
  6. // "http:"
  7. document.location.host //主机。如果端口不是协议默认的80和433,则还会包括冒号(:)和端口
  8. // "www.example.com:4097"
  9. document.location.hostname //主机名,不包括端口
  10. // "www.example.com"
  11. document.location.port //端口号
  12. // "4097"
  13. document.location.pathname //URL 的路径部分
  14. // "/path/a.html"
  15. document.location.search // 查询字符串部分
  16. // "?x=111"
  17. document.location.hash //hash
  18. // "#part1"
  19. document.location.username
  20. // "user"
  21. document.location.password
  22. // "passwd"
  23. document.location.origin //URL的协议、主机名和端口
  24. // "http://user:passwd@www.example.com:4097"

这些属性里面,只有origin属性是只读的,其他属性都可写。
注意,如果对 Location.href 写入新的 URL 地址,浏览器会立刻跳转到这个新地址。

这个特性常常用于让网页自动滚动到新的锚点。

  1. document.location.href = '#top';
  2. // 等同于
  3. document.location.hash = '#top';

直接改写location,相当于写入href属性。

  1. document.location = 'http://www.example.com';
  2. // 等同于
  3. document.location.href = 'http://www.example.com';

3.3 location 对象的方法

image.png

3.4 查询字符串

虽然 location.search 返回了从问号开始直到URL末尾的所有内容,但没有办法逐个访问每个查询参数。
可以手写方法:

  1. let getQueryStringArgs = function() {
  2. // 取得没有开头问号的查询字符串
  3. let qs = (location.search.length > 0 ? location.search.substring(1) :
  4. ""),
  5. // 保存数据的对象
  6. args = {};
  7. // 把每个参数添加到args对象
  8. for (let item of qs.split("&").map(kv => kv.split("="))) {
  9. let name = decodeURIComponent(item[0]),
  10. value = decodeURIComponent(item[1]);
  11. if (name.length) {
  12. args[name] = value;
  13. }
  14. }
  15. return args;
  16. }
  17. // 假设查询字符串为?q=javascript&num=10
  18. let args = getQueryStringArgs();
  19. alert(args["q"]); // "javascript"
  20. alert(args["num"]); // "10"

URLSearchParam

https://www.wangdoc.com/javascript/bom/location.html#urlsearchparams-%E5%AF%B9%E8%B1%A1

URLSearchParams 提供了一组标准API方法,通过它们可以检查和修改查询字符串。给 URLSearchParams 构造函数传入一个查询字符串,就可以创建一个实例。这个实例上暴露了 get() 、 set() 和 delete() 等方法,可以对查询字符串执行相应操作

  1. let qs = "?q=javascript&num=10";
  2. let searchParams = new URLSearchParams(qs);
  3. alert(searchParams.toString()); // " q=javascript&num=10"
  4. searchParams.has("num"); // true
  5. searchParams.get("num"); // 10
  6. searchParams.set("page", "3");
  7. alert(searchParams.toString()); // " q=javascript&num=10&page=3"
  8. searchParams.delete("q");
  9. alert(searchParams.toString()); // " num=10&page=3"

大多数支持 URLSearchParams 的浏览器也支持将 URLSearchParams 的实例用作可迭代对象

  1. let qs = "?q=javascript&num=10";
  2. let searchParams = new URLSearchParams(qs);
  3. for (let param of searchParams) {
  4. console.log(param);
  5. }
  6. // ["q", "javascript"]
  7. // ["num", "10"]


3.5 URL对象

URL 的编码和解码

网页的 URL 只能包含合法的字符,其他需要进行转义,JavaScript 提供四个 URL 的编码/解码方法。

encodeURIComponent(‘春节’) // “%E6%98%A5%E8%8A%82” decodeURIComponent(‘%E6%98%A5%E8%8A%82’) // “春节”

  1. <a name="ZnHzO"></a>
  2. #### URL 接口
  3. 浏览器原生提供URL()接口,它是一个构造函数,用来构造、解析和编码 URL。一般情况下,通过window.URL可以拿到这个构造函数。
  4. ```javascript
  5. var url = new URL('http://www.example.com/index.html');
  6. url.href // "http://www.example.com/index.html"

URL 实例的属性与Location对象的属性基本一致,返回当前 URL 的信息。

  • URL.href:返回整个 URL
  • URL.protocol:返回协议,以冒号:结尾
  • URL.hostname:返回域名
  • URL.host:返回域名与端口,包含:号,默认的80和443端口会省略
  • URL.port:返回端口
  • URL.origin:返回协议、域名和端口
  • URL.pathname:返回路径,以斜杠/开头
  • URL.search:返回查询字符串,以问号?开头
  • URL.searchParams:返回一个URLSearchParams实例,该属性是Location对象没有的
  • URL.hash:返回片段识别符,以井号#开头
  • URL.password:返回域名前面的密码
  • URL.username:返回域名前面的用户名

静态方法:

  • URL.createObjectURL() 方法用来为上传/下载的文件、流媒体文件生成一个 URL 字符串。这个字符串代表了 File 对象或 Blob 对象的 URL。
  • URL.revokeObjectURL() 方法用来释放 URL.createObjectURL() 方法生成的 URL 实例。它的参数就是URL.createObjectURL() 方法返回的 URL 字符串。

    文件二进制相关

4. navigator 对象

navigator 对象包含有关浏览器的信息,它有很多属性,我们最常用的是 userAgent,该属性可以返回由客户机发送服务器的 user-agent 头部的值。

  1. //下面前端代码可以判断用户那个终端打开页面,实现跳转
  2. if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
  3. window.location.href = ""; //手机
  4. } else {
  5. window.location.href = ""; //电脑
  6. }


5. history 对象

window 对象给我们提供了一个 history 对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的 URL。
image.png

历史状态管理

https://www.wangdoc.com/javascript/bom/history.html#historypushstate

这个方法接收3个参数:一个 state 对象、一个新状态的标题和一个(可选的)相对URL 。

  1. var stateObj = { foo: 'bar' };
  2. history.pushState(stateObj, 'page 2', '2.html');

添加新记录后,浏览器地址栏立刻显示example.com/2.html,但并不会跳转到2.html,甚至也不会检查2.html是否存在,它只是成为浏览历史中的最新记录。这时,在地址栏输入一个新的地址(比如访问google.com),然后点击了倒退按钮,页面的 URL 将显示2.html;你再点击一次倒退按钮,URL 将显示1.html。

总之,pushState()方法不会触发页面刷新,只是导致 History 对象发生变化,地址栏会有反应。

每当同一个文档的浏览历史(即history对象)出现变化时,就会触发popstate事件。

  1. window.addEventListener('popstate', function(event) {
  2. console.log('location: ' + document.location);
  3. console.log('state: ' + JSON.stringify(event.state));
  4. });

注意,仅仅调用pushState()方法或replaceState()方法 ,并不会触发该事件,只有用户点击浏览器倒退按钮和前进按钮,或者使用 JavaScript 调用History.back()、History.forward()、History.go()方法时才会触发。另外,该事件只针对同一个文档,如果浏览历史的切换,导致加载不同的文档,该事件也不会触发。

使用HTML5状态管理时,要确保通过 pushState() 创建的每个“假”URL背后都对应着服务器 上一个真实的物理URL。否则,单击“刷新”按钮会导致404错误。所有单页应用程序(SPA,Single Page Application)框架都必须通过服务器或客户端的某些配置解决这个问题。

8.存储

Cookie

https://www.wangdoc.com/javascript/bom/cookie.html
Cookie 是服务器保存在浏览器的一小段文本信息,一般大小不能超过4KB。浏览器每次向服务器发出请求,就会自动附上这段信息。

document.cookie属性返回当前网页的 Cookie。

document.cookie是可以写的,一次只能写入一个 Cookie,而且写入并不是覆盖,而是添加

  1. document.cookie // "id=foo;key=bar"

HTTP响应设置Cookie

  1. Set-Cookie:foo=bar

如果Set-Cookie字段没有指定Expires或Max-Age属性,那么这个 Cookie 就是 Session Cookie,即它只在本次对话存在,一旦用户关闭浏览器,浏览器就不会再保留这个 Cookie。 删除一个现存 Cookie 的唯一方法,是设置它的expires属性为一个过去的日期。

一些属性:

  • Expires 到期时间,UTC格式,
  • Max-Age 秒数,如果同时指定了Expires和Max-Age,那么Max-Age的值将优先生效。
  • Domain 属性指定 Cookie 属于哪个域名,Domain 属性只能是当前域名或者当前域名的上级域名,但设为上级域名时,不能设为顶级域名(.com)或公共域名(github.io)
  • Path 属性指定浏览器发出 HTTP 请求时,哪些路径要附带这个 Cookie。只要浏览器发现,Path属性是 HTTP 请求路径的开头一部分就会在头信息里面带上这个 Cookie。
  • Secure 属性指定浏览器只有在加密协议 HTTPS 下,才能将这个 Cookie 发送到服务器。
  • HttpOnly属 性指定该 Cookie 无法通过 JavaScript 脚本拿到,主要是document.cookie属性、XMLHttpRequest 对象和 Request API 都拿不到该属性
  • SameSite 用来防止 CSRF 攻击和用户追踪。

浏览器向服务器发送 HTTP 请求时,每个请求都会带上相应的 Cookie

  1. Cookie: foo=bar

sessionStorage

1、生命周期为关闭浏览器窗口
2、在同一个窗口(页面)下数据可以共享
3、以键值对的形式存储使用

  1. //存储数据:
  2. sessionStorage.setItem(key, value)
  3. //获取数据:
  4. sessionStorage.getItem(key)
  5. //删除数据:
  6. sessionStorage.removeItem(key)
  7. //删除所有数据:
  8. sessionStorage.clear()

localStorage

1、声明周期永久生效,除非手动删除 否则关闭页面也会存在
2、可以多窗口(页面)共享(同一浏览器可以共享)
3、以键值对的形式存储使用

  1. //存储数据:
  2. localStorage.setItem(key, value)
  3. //获取数据:
  4. localStorage.getItem(key)
  5. //删除数据:
  6. localStorage.removeItem(key)
  7. //删除所有数据:
  8. localStorage.clear()

不同浏览器给 localStorage 和 sessionStorage 设置了不同的空间限制,但大多数会限制为每个域名 5MB。

IndexedDB

Indexed Database API 简称 IndexedDB,是浏览器中存储结构化数据的一个方案。IndexedDB 用于代 替目前已废弃的 Web SQL Database API。IndexedDB 背后的思想是创造一套 API,方便 JavaScript 对象的 存储和获取,同时也支持查询和搜索。

IndexedDB 的设计几乎完全是异步的。为此,大多数操作以请求的形式执行,这些请求会异步执行, 产生成功的结果或错误。绝大多数 IndexedDB 操作要求添加 onerror 和 onsuccess 事件处理程序来确定输出。

IndexedDB 数据库就是在一个公共命名空间下的一组对 象存储,类似于 NoSQL 风格的实现。

网页定位

1. offset

1.1 offset 概述

offset 翻译过来就是偏移量, 我们使用 offset 系列相关属性可以动态的得到该元素的位置(偏移)、大小等。

  • 获得元素距离带有定位父元素的位置
  • 获得元素自身的大小(宽度高度)
  • 注意: 返回的数值都不带单位

offset 系列常用属性:
image.png
image.png

1.2 offset 与 style 区别

image.png

2. client

client 翻译过来就是客户端,我们使用 client 系列的相关属性来获取元素可视区的相关信息。通过 client 系列的相关属性可以动态的得到该元素的边框大小、元素大小等。
image.png
image.png

3.scroll

scroll 翻译过来就是滚动的,我们使用 scroll 系列的相关属性可以动态的得到该元素的大小、滚动距离等。
image.png
image.png

如果浏览器的高(或宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发 onscroll 事件。

页面被卷去的头部兼容性解决方案

需要注意的是,页面被卷去的头部,有兼容性问题,因此被卷去的头部通常有如下几种写法:

    1. 声明了 DTD,使用 document.documentElement.scrollTop
    1. 未声明 DTD,使用 document.body.scrollTop
    1. 新方法 window.pageYOffset 和 window.pageXOffset,IE9 开始支持
      1. function getScroll() {
      2. return {
      3. left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft||0,
      4. top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
      5. };
      6. }
      7. // 使用的时候 getScroll().left

3.总结

image.png
主要用法:

  • offset系列 经常用于获得元素位置 offsetLeft offsetTop
  • 经常用于获取元素大小 clientWidth clientHeight
  • 经常用于获取滚动距离 scrollTop scrollLeft
  • 注意页面滚动的距离通过 window.pageXOffset 获得

mouseenter 和mouseover的区别

当鼠标移动到元素上时就会触发 mouseenter事件
类似 mouseover,它们两者之间的差别是:

  • mouseover鼠标经过自身盒子会触发,经过子盒子还会触发。 mouseenter只会经过自身盒子触发
  • 之所以这样,就是因为mouseenter不会冒泡
  • 鼠标离开 mouseleave同样不会冒泡

对于深层次结构,发送的 mouseover事件数量可能非常大并且会导致严重的性能问题。在这种情况下,最好是监听 mouseenter 事件。