BOM

BOM是 Browser Object Model的缩写,中文翻译过来就是 浏览器对象模型. 从名字上就可以看出,它是用于访问浏览器功能的对象.

window对象

window对象是BOM的核心对象,一个window表示一个浏览器实例.当你打开多个选项卡的时候,每个选项卡对应一个window对象.
在下图中,我们在浏览器中 打开了 两个选项卡,那么每个选项卡就对应一个自己的window对象.
DOM知识点累计 - 图1

window对象结构

window 对象处于 JavaScript 结 构的最顶层,对于每个打开的窗口,系统都会自动为其定义 window 对象。 DOM知识点累计 - 图2

window对象的属性

属性名 含义
document 当前窗口中的文档对象
frames 当前窗口中的框架数
history 记录浏览器的浏览历史
location 当前页面的URL地址
navigator 与浏览器相关的信息
screen 屏幕信息

注意: 以上所有的属性都可以直接在页面中使用或者通过window.xxx的方式访问

history

负责管理浏览器的浏览记录,控制页面的前进或者后退 数

  1. 获取history对象
  2. var historyObj = window.history;
  3. //可以直接使用history对象
  4. console.log(history);

DOM知识点累计 - 图3

属性名 含义
length 历史记录条数
go 跳转到指定页数
back 后退一页
forward 前进一页
pushStaete 不刷新页面修改URL链接
replaceState 修改当前历史记录
  1. history.go(-2); //后退2页
  2. history.go(3);//前进三页
  3. history.back();//后退一页
  4. history.forward();//前进一页

pushStaete

在不刷新浏览器的情况下,将新的浏览器记录插入到历史记录中

  1. history.pushState(stateObject, title, url);
  2. 参数说明:
  3. stateObject: 状态对象.将要传递到新页面中的内容存储在该对象中.
  4. titile: 标题,由于兼容性问题,这里建议传递一个空值
  5. url: 新的历史URL记录.浏览器在调用pushState()方法后不会加载该地址;传入的URL与当前URL应该是同源的,否则,pushState()会抛出异常。

示例

  1. 打开我们的测试页面 http://www.baidu.com 查看相关的History信息,

DOM知识点累计 - 图4

  1. 在控制台中 输入

    1. history.pushState({status:0},'','?info=110')
  2. 然后再查看history记录,如下图

DOM知识点累计 - 图5
地址栏也变成了

  1. http://www.githuo.com/jsbook/?info=110

从上面的例子中我们可以看到,通过 pushState 改变了 地址栏的内容,但是浏览器并没有重新加载.并且 history里的state也多了一个status属性

replaceState

history.replaceState() 的使用与 history.pushState() 非常相似,区别在于 replaceState() 是修改了当前的历史记录项而不是新建一个。 注意这并不会阻止其在全局浏览器历史记录中创建一个新的历史记录项。

  1. history.replaceState(stateObj, "page 3", "bar2.html");

示例
DOM知识点累计 - 图6
地址栏发生变化

  1. http://www.githuo.com/jsbook/bar.html

历史记录新增了一条
DOM知识点累计 - 图7

location

location 对象存储了当前文档位置(URL)相关的信息
DOM知识点累计 - 图8
属性说明

属性名 含义
origin 返回URL的协议,主机名和端口号
protocol url的协议
host url中的主机名和端口号
hostname 主机名
port 端口号
pathname url地址的路径部分
search 查询部分
hash url中 锚部分
href 文档的完整url地址

protocol 协议头

表示访问资源和服务的协议,

  • http 超文本传输协议 (用于网页传输),默认端口号是 80,不会显示
  • https 超文本安全传输协议.(用于网页传输,比http协议要安全)
  • mailto URL指向E-mail地址
  • file 文件协议,表示一台主机上可以直接访问的文件
  • ftp 文件传输协议.
  • rtsp,rtspu 通过实时流传输协议(Real Time Streaming Protocol)解析的音/视频媒体资源的标识符

    hostname 主机名

    每台电脑在网络上都会有一个唯一的由小于255一组数字组成的地址,我们称之为IP地址.当我们去访问一个网站的时候,实际上是通过IP地址访问这个网站所在的的电脑上的内容.
    查看网站的 主机名
    1. ping www.baidu.com //14.215.177.38
    2. ping www.githuo.com //120.78.135.42
    3. ping www.taobao.com //113.96.109.100
    4. ping www.jd.com //183.60.141.1

    网络访问流程

    DOM知识点累计 - 图9

    port 端口号

    所谓端口号,就像是门牌号一样.你通过我给你的地址,你找到我这栋大楼,由于大楼里有很多个房间,你需要通过门牌号才能找到我.而端口号,就是我们通过ip地址找到互联网上的电脑,但是这台电脑上运行着很多软件,我们就需要根据端口号来找到对应的软件,然后才能进行通信.
    如图
    DOM知识点累计 - 图10

    pathname 路径

    有时候需要访问某个网站的图片,就需要在网址后面加上图片在网站电脑上的位置 例如 上个例子中图片的完整地址就是
    1. http://localhost:4000/images/BOM/10.%E7%AB%AF%E5%8F%A3%E5%8F%B7.png
    其中下面这部分就是图片所在的路径
    1. /images/BOM/10.%E7%AB%AF%E5%8F%A3%E5%8F%B7.png

    search 查询

    获取url地址中 ?以及之后的内容,例如
    1. http://www.githuo.com/jsbook?page=1&&size=20
    我们经常通过search来获取 ?page=1&&size=20 部分内容,然后将 这段内容转换成对象
    1. var str = location.search; //?page=1&&size=20
    2. //去掉问号
    3. str = str.slice(1,str.length);
    4. //拆分字符串成数组
    5. var arr = str.split("&&"); // ["page=1","size=20"]
    6. var result = {}
    7. //遍历数组,
    8. for(var i=0;i<=arr.length-1;i++){
    9. //拆分数组元素
    10. var ele = arr[i].split("=");
    11. result[ele[0]] = ele[1];
    12. }
    输出结果
    1. {page: "1", size: "20"}

    hash 哈希值

    在url地址后面加上以#开头的内容,这些内容就是url的哈希值. 常见于 锚点和调用pushState函数.
    1. http://www.githuo.com/jsbook/%E8%BF%9B%E9%98%B6/05.BOM%E5%AF%B9%E8%B1%A1.html#page1
    DOM知识点累计 - 图11

    href

    完整的url地址
    1. location.href
    2. "http://www.githuo.com/jsbook/%E8%BF%9B%E9%98%B6/05.BOM%E5%AF%B9%E8%B1%A1.html#page1"

    navigator

    包含了浏览器的一些基本信息,但每个浏览器的表现不一.这里以chrome为例,在控制台输入 navigator 得到以下内容:
    DOM知识点累计 - 图12
    以上内容并非是每个浏览器都适用.我们这里只挑选常用的来学习 属性名|含义 —-|:—: appCodeName|浏览器的代码名,chrome,safari,firfox都是”Mozilla” appName | 浏览器的名称,默认值都是Netscape appVersion | 浏览器的版本号(废弃) platform | 浏览器运行所在的平台 language | 当前使用的语言 userAgent | 用户代理(user agent)字符串 geolocation | 定位

    userAgent

    用户代理(user agent)字符串,不同的浏览器或者不同版本的浏览器返回的字符串可能也不一样.
    1. macChrome浏览器
    2. Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5)
    3. AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.
    4. 3987.122 Safari/537.36
    5. 安卓端 Chrome浏览器
    6. Mozilla/5.0 (Linux; Android 9; meizu 16Xs)
    7. AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.
    8. 3987.119 Mobile Safari/537.36
    9. Firfox浏览器
    10. Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:73.0) Gecko/20100101 Firefox/73.0
    11. Safari浏览器
    12. Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5)
    13. AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.
    14. 1 Safari/605.1.15
    15. ios
    16. Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS
    17. X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/
    18. 9A334 Safari/7534.48.3

    Gecko

    Gecko 是 Firefox 的呈现引擎。Gecko 首次开发是作为 Mozilla 浏览器 Netscape 6 的一部分

    WebKit

    Apple 宣布发布首款他们自主开发的 web 浏览器:Safari。它的呈现引擎叫 WebKit

    Chrome

    Chrome浏览器以 WebKit 作为呈现引擎,但是用了其他的javascript引擎.user-agent字符串是在webkit信息的基础上增加一些新的内容

    user-agent的作用

    通过user-agent不能完全准确的判断是属于那款浏览器。
  1. 统计用户浏览器使用情况。有些浏览器说被多少人使用了,实际上就可以通过判断每个IP的UA来确定这个IP是用什么浏览器访问的,以得到使用量的数据。
  2. 根据用户使用浏览器的不同,显示不同的排版从而为用户提供更好的体验。有些网站会根据这个来调整打开网站的类型,如是手机的就打开wap,显示非手机的就打开pc常规页面。用手机访问谷歌和电脑访问是不一样的,这些是谷歌根据访问者的UA来判断的。
    1. //判断是否是pc
    2. function IsPC() {
    3. var userAgentInfo = navigator.userAgent;
    4. var Agents = ["Android", "iPhone","SymbianOS", "Windows Phone","iPad", "iPod"];
    5. var flag = true;
    6. for (var v = 0; v < Agents.length; v++) {
    7. if (userAgentInfo.indexOf(Agents[v]) > 0) {
    8. flag = false;
    9. break;
    10. }
    11. }
    12. if(flag){
    13. location.href = "http://www.githuo.com"
    14. }else{
    15. location.href = "http://m.jd.com";
    16. }
    17. }
    18. //判断是否是移动端
    19. if (/(iPhone|iPad|iPod|iOS|Android)/i.test(navigator.userAgent)) { //移动端
    20. //TODO
    21. location.href = "http://m.jd.com";
    22. }else{
    23. location.href = "http://www.githuo.com"
    24. }

    screen 屏幕

    获取和屏幕相关的属性
    DOM知识点累计 - 图13
属性 说明
availWidth 返回显示屏幕的宽度 (除 Windows 任务栏之外)
availHeight 返回显示屏幕的高度 (除 Windows 任务栏之外)
width 返回显示屏幕的宽度
height 返回显示屏幕的高度
colorDepth 返回目标设备或缓冲器上的调色板的比特深度
pixelDepth 返回显示屏幕的颜色分辨率(比特每像素)
availLeft 和屏幕左侧的距离
availTop 和屏幕顶部的距离
orientation 屏幕旋转的方向

orientation

获取屏幕旋转方向

type属性

type 属性主要通过描述来表达屏幕的旋转方向,type 的返回值总共有四个,对应着四个不同的旋转方向:
portrait-primary:竖屏状态并且旋转角度为 0 度,也就是设备的自然位置
portrait-secondary:竖屏状并且即旋转角度为 180 度,也就是倒着拿的位置
landscape-primary:横屏状态并且旋转角度为 90 度
landscape-secondary:横屏状态并且旋转角度为 180 度

  1. function rotationChange() {
  2. console.log('rotation changed to:', screen.orientation.type);
  3. var screenType = screen.orientation.type;
  4. if(screenType === "portrait-primary"){
  5. alert("竖屏主方向");
  6. }else if(screenType === "portrait-secondary"){
  7. alert("竖屏次方向");
  8. }else if(screenType === "landscape-primary"){
  9. alert("横屏主方向");
  10. }else if(screenType === "landscape-secondary"){
  11. alert("横屏次方向");
  12. }else{
  13. alert("不支持旋转");
  14. }
  15. }
  16. //屏幕发生旋转的时候触发该函数
  17. screen.orientation.addEventListener('change', rotationChange);

锁定屏幕和解锁屏幕

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>Document</title>
  7. </head>
  8. <body>
  9. <button onclick="lockPortrait()">锁屏</button>
  10. <button onclick="unlockPortrait()">解锁</button>
  11. </body>
  12. </html>
  13. <script>
  14. function lockPortrait(){
  15. // 首先进入全屏模式
  16. document.documentElement.requestFullscreen();
  17. // 锁定竖屏方向
  18. screen.orientation
  19. .lock('portrait')
  20. .catch(e => alert(e.message));
  21. }
  22. function unlockPortrait(){
  23. //解锁屏幕方向
  24. screen.orientation.unlock();
  25. }
  26. </script>

window的函数

在这里只列举常用的一些方法进行说明

方法名 函数
alert 弹出警告框
confirm 弹出确认会话框
prompt 弹出对话框
focus 让窗口获得聚焦
blur 让窗口失去焦点
open 打开一一个新的顶级窗口
resizeBy()、resizeTo() 重设窗口大小。
scrollBy()、scrollTo() 滚动当前窗口中的HTML文档。
setTimeout()、clearTimeout() 设置、删除定时器。
setInterval()、clearlnterval() 也是设置重复定时器

open

打开一一个新的顶级窗口,并可以导航到一个特定的URL.
window.open(URL,name,specs,replace)

open('http://www.githuo.com/jsbook');//新建窗口并打开极火网
open('http://www.githuo.com/jsbook','极火网');
open('http://www.githuo.com/jsbook','_blank','width=200,height=100')

scrollTo

scrollTo(x,y);

  • x 横向滚动距离
  • y 纵向滚动距离

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
          body {
              position: absolute;
              top: 0;
              left: 0;
              right: 0;
              bottom: 0;
          }
          .main {
              width: 100%;
              height: 200%;
              background-color: cyan;
          }
      </style>
    </head>
    <body>
      <button onclick="scrollView()">滚动</button>
     <div class="main"></div>
    </body>
    </html>
    <script>
    function scrollView(){
      window.scrollTo(100,300);
    }
    </script>
    

    setTimeout

    设置定时器,在某个时间后执行函数,只执行一次 setTimeout(arg1,arg2)

  • arg1: 要执行的函数

  • arg2: 超时时间(毫秒数)

下面的例子中,是要在1000毫秒之后,打印 “hello”

setTimeout(function(){
        console.log("hello");
    },1000)

clearTimeout

每使用一次setTimeout函数,就会生成一个定时器ID,我们可以通过clearTimeout方法来清除这个定时器.

var timer = null;
    timer = setTimeout(function(){
        console.log("zmt");
    },3000)
    setTimeout(function(){
        console.log("githuo");
        clearTimeout(timer)
    },1000)

上面的最终的执行结果是,在1秒的时候输出 “githuo”,然后取消 3秒的定时器,当时间走到三秒的时候,就不会再输出 “zmt”

setInterval

每隔特定的毫秒数之后,执行函数

var i = 0;
    setInterval(function(){
        console.log("i="+i);
        i++;
    },1000)

上面例子中,每隔一秒就输出i的值,并对i进行加1运算, DOM知识点累计 - 图14

clearInterval

清除循环定时器

var i = 0;
    var intervalTime = null;
    intervalTime = setInterval(function(){
        console.log("i="+i);
        i++;
    },1000)
    //在5秒之后,停止interval定时器
    setTimeout(function(){
        cleartInterval(intervalTime)
    },5000)

使用 setTimeout实现setInterval功能

var timer = null;
    var i = 0;
    function interval(time){
        timer = setTimeout(function(){
            console.log(i);
            i++;
            clearTimeout(timer);
            interval(time);
        },time)
    }
    interval(1000);

思考一下代码的执行顺序

setTimeout(function(){
        console.log("1");
    },1000)
    setTimeout(function(){
        console.log("0");
    },0)
    console.log("3");
    //斐波那契数列函数
    function fbn(n){
        if(n==1 || n==2){
            return 1;
        }
        return fbn(n-1)+fbn(n-2)
    }
    var rs = fbn(42);
    console.log(rs);

同步 Synchronous

同步就是方法一旦调用就必须等到该方法执行结束之后,才会继续往后执行

function f1(){
    console.log("1");
}
function f2(){
    console.log("2");
}
f1();
f2();

调用f1函数
DOM知识点累计 - 图15
执行f1函数的内容
DOM知识点累计 - 图16
f1函数执行完成,从执行栈中离开.调用f2函数
DOM知识点累计 - 图17
执行f2函数 DOM知识点累计 - 图18
所有同步函数执行完毕,执行栈为空
DOM知识点累计 - 图19

异步 Asynchronous

在js中的异步,它必须等所有同步行为都执行完成之后,才会执行异步操作.

function f1(){
    console.log("1");
}
function f2(){
    console.log("2");
}
setTimeout(function(){
    console.log("2");
},0)
f1();
f2();
  1. 调用setTimeout方法

DOM知识点累计 - 图20

  1. 执行setTimeout方法,将setTimeout方法里的函数注册到事件队列中,等待执行

DOM知识点累计 - 图21

  1. 接下来就是调用f1和f2,和同步的方法一样,这里就放图了
  2. 当同步函数f1和f2都执行完成之后,再到事件队列里调用排队等待执行的事件 DOM知识点累计 - 图22

异步事件在JS编程中的地位非常重要,因此你需要好好琢磨它!