BOM是浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是window

BOM有一系列闯关的对象构成,并且为每个对象提供了很多方法和属性,兼容性不好

DOM与BOM的区别(BOM比DOM大)

DOM

BOM

文档对象模型

浏览器对象模型

DOM就是把文档当作一个对象来看待

把浏览器当作一个对象看待

DOM的顶级对象是document

顶级对象是window

DOM主要学习的是操作页面元素

BOM主要学习浏览器窗口交互的对象

DOM是W3C标准规范

BOM是浏览器厂商在各自的浏览器上定义的,兼容性较差

BOM构成

window包含(document,location,navigation,screen,history)

window的双重角色

(1)它是JS访问浏览器窗口的一个接口

(2)他是一个全局对象,定义在全局作用域中的变量,函数都会变成window对象的属性和方法

<body>
  <script>
    //全局变量变成window的属性
    var num = 10;
    console.log(num);
    console.log(window.num)
    //函数变成wwindow的方法
    function fn() {
      console.log(11);
    }
    fn();
    window.fn();
    //查看window对象
    console.dir(window);
  </script>

</body>

1.窗口加载事件(window.onload

window.onload=function(){}
或者
window.addEventListener("load",function(){})

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

注意:有了window.onload就可以把JS代码写在页面元素的上方,因为onload是等页面内容全都加载完毕,再去执行处理函数,但是只执行一次,有多个时,以最后一个window.onload为准

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script>
    window.onload = function () {
      var btn = document.querySelector('button');
      btn.addEventListener('click', function () {
        alert('点击我');
      })
    }
  </script>
</head>
<body>
  <button>点击</button>
</body>
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script>
    window.addEventListener('load', function () {
      var btn = document.querySelector('button');
      btn.onclick = function () {
        alert('hhhh');
      }
    })
  </script>
</head>

<body>
  <button>点击</button>
</body>

</html>

2.窗口加载事件(DOMContentLoaded

DOMContentLoaded事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等,ie9以上支持,适用于图片非常多的情况

document.addEventListener('DOMContentLoaded',function(){})
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script>
    window.addEventListener('load', function () {
      var btn = document.querySelector('button');
      btn.onclick = function () {
        alert('hhhh');
      }
    });
    document.addEventListener('DOMContentLoaded', function () {
      alert('eee');
    })
  </script>
</head>

<body>
  <button>点击</button>
</body>

</html>

区别

(1)load等页面内容全部加载完毕,包含页面dom元素,图片,flash,CSS等等

(2)DOMContentLoaded是DOM加载完毕,不包含图片,flash,css等就可以执行,加载速度比load快一些

3.调整窗口大小事件

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

window.onresize=function(){}

window.addEventListener("resize",function(){})
<body>
  <script>
    window.addEventListener('resize', function () {
      console.log('变化了');
    })
  </script>
</body>

注意:

(1)只要窗口大小发生像素变化,就会触发这个事件

(2)可以用来完成响应式布局,window.innerWidth当前屏幕的宽度

调整窗口大小案例(小于800px隐藏div)

<style>
    div {
      width: 800px;
      height: 800px;
      background-color: blue;
    }
  </style>
<body>
  <script>
    window.addEventListener('load', function () {
      var div = document.querySelector('div');
      window.addEventListener('resize', function () {
        console.log(window.innerWidth);
        if (window.innerWidth <= 800) {
          div.style.display = 'none';
        } else {
          div.style.display = 'block';
        }
      })
    })
  </script>
  <div></div>
</body>

4.定时器

setTimeout()

setInterval()

4.1 setTimeout定时器

window.setTimeout(调用函数,[延迟的毫秒数])

该方法用于设置一个定时器,该定时器在定时器到期后执行调用函数,只调用一次

(1)这个函数延时时间单位是ms,可以省略,默认为0

(2)这个调用函数既可以直接写函数,也可以写函数名,或者写成'函数名()'

(3)页面中可以有很多定时器,可以给定时器加标识符

<body>
  <script>
    // setTimeout(function () {
    //   console.log('时间到了')
    // }, 2000);
    function callback() {
      console.log('到时间安啦');
    }
    // setTimeout(callback, 5000);
    // setTimeout('callback()', 5000);
    var timer1 = setTimeout(callback, 2000);
    var timer2 = setTimeout(callback, 4000);
  </script>
</body>

自动关闭广告案例

<body>
  <img src="https://img1.baidu.com/it/u=158813535,1868369097&fm=253&fmt=auto&app=138&f=JPEG?w=600&h=413" alt="">
  <script>
    var pic = document.querySelector('img');
    setTimeout(close, 5000);
    function close() {
      pic.style.display = 'none';
    }
  </script>
</body>

4.2 停止setTimeout()定时器

window.clearTimeout(timeoutID)
<body>
  <button>点击停止定时器</button>
  <script>
    var btn = document.querySelector('button');
    var timer = setTimeout(function () {
      console.log('到时间啦');
    }, 5000)
    btn.addEventListener('click', function () {
      //点击清除定时器
      window.clearTimeout(timer);
    })
  </script>
</body>

4.3 setInterval()定时器

window.setInterval(回调函数,[间隔的毫秒数]);

setInterval()方法重复调用一个函数,每隔这个时间,就调用一次回调函数,其余特点与setTimeout()相同

<body>
  <script>
    setInterval(function () {
      console.log('shshhsh');
    }, 1000)
  </script>
</body>

倒计时案例

关键点

(1)倒计时不断变化,因此用定时器来自动变化(setInterval)

(2)三个盒子存放时分秒

(3)三个盒子里用innerHTML放入计算的小时,分钟,秒数

<body>
  <div>
    <span class="hour">1</span>
    <span class="minute">2</span>
    <span class="second">3</span>
  </div>
  <script>
    var hour = document.querySelector('.hour');
    var minute = document.querySelector('.minute');
    var second = document.querySelector('.second');
    var inputTime = +new Date('2022-7-9 18:00:00');
    //先调用一次,防止页面刷新有空白
    countDown();
    setInterval(countDown, 1000);
    function countDown() {
      var nowTime = +new Date();
      var times = (inputTime - nowTime) / 1000;
      // var d = parseInt(times / 60 / 60 / 24);
      // d = d < 10 ? '0' + d : d;
      var h = parseInt(times / 60 / 60 % 24);
      h = h < 10 ? '0' + h : h;
      hour.innerHTML = h;
      var m = parseInt(times / 60 % 60);
      m = m < 10 ? '0' + m : m;
      minute.innerHTML = m;
      var s = parseInt(times % 60);
      s = s < 10 ? '0' + s : s;
      second.innerHTML = s;
      // return d + '天' + h + '时' + m + '分' + s + '秒';
    }
  </script>

4.4 停止setInterval()定时器

window.clearInterval(intervalID)

clearInterval()方法取消了先前通过调用setInterval()创建的定时器

<body>
  <div class="start">开启定时器</div>
  <div class="stop"> 关闭定时器</div>
  <script>
    var start = document.querySelector('.start');
    var stop = document.querySelector('.stop');
    var timer = null;
    start.addEventListener('click', function () {
      timer = setInterval(function () {
        console.log('开始');
      }, 1000);
    })
    stop.addEventListener('click', function () {
      clearInterval(timer)
    })
  </script>
</body>

手机发送验证码案例

<body>
  <input type="number"> <button>发送</button>
  <script>
    var btn = document.querySelector('button');
    var time = 10;
    btn.addEventListener('click', function () {
      btn.disabled = true;
      var timer = setInterval(function () {
        if (time === 0) {
          clearInterval(timer);
          btn.disabled = false;
          btn.innerHTML = '发送';
          time = 10;
        } else {
          btn.innerHTML = '还剩下' + time + '秒';
          time--;
        }
      }, 1000);
    })
  </script>
</body>

this指向问题

一般情况下,this的最终指向是调用它的对象

(1)全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this指向window)

(2)方法调用中,谁调用this指向谁

(3)构造函数中,this指向构造函数的实例

<body>
  <button>点击</button>
  <script>
    //1.全局变量或者普通函数中,this指向全局对象window(定时器里面的this指向window)
    console.log(this);//window
    function fn() {
      console.log(this);
    }
    window.fn();//window
    setTimeout(function () { console.log(this) }, 1000);//window
    //方法调用中谁调用this指向谁
    var o = {
      sayHi: function () {
        console.log(this);
      }
    }
    o.sayHi();//this指向o这个对象
    var btn = document.querySelector('button');
    btn.onclick = function () {
      console.log(this);//<button>点击</button>
    }
    //构造函数中this指向构造函数实例
    function FUN() {
      console.log(this);//this指向fun实例对象
    }
    var fun = new Fun();
  </script>
</body>

5.JS执行机制(同步和异步)

5.1 JS是单线程

JS的一大特点就是单线程,同一时间只能做一件事,单线程就意味着所有的任务需要排队,前一个任务结束后,才会执行下一个任务,如果JS执行时间长,会导致页面渲染不连贯

<script>
    console.log(1);
    setTimeout(function () {
      console.log(3);

    }, 3000);
    console.log(2);
  </script>
//如果按照单线程机制,打印完1后,要等待3s才能打印3和2
//实际是异步机制,输出1,2,3

5.2 同步和异步

HTML5提出Web Worker标准,允许JS脚本创建多个线程,于是,JS中出现了同步和异步

同步:前一个任务结束之后在执行后一个任务,程序的执行顺序与任务的排列顺序是一致的,同步的,比如做饭的同步做法:先烧水,水烧好(10h)后,再去切菜,炒菜

异步:做一件事情的同时处理另外一件事情,比如,烧水的时候切菜炒菜

同步任务和异步任务的执行过程

同步任务:同步任务都在主线程上执行,形成一个执行栈

异步任务:通过回调函数实现,异步任务包括

(1)普通事件,click,resize等

(2)资源加载,load,error等

(3)定时器,setInterval,setTimeout等

JS的执行机制为

(1)先执行执行栈中的同步任务

(2)异步任务(回调函数)放入任务队列中

(3)一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行

<body>
  <script>
    console.log(1);//同步任务
    setTimeout(function () {
      console.log(3);//setTimeout()是同步任务,function()属于异步任务
    }, 0);
    console.log(2);//同步任务
    // 执行栈中存放console.log(1),setTimeout(fn,0),console.log(2),这里的任务先按顺序执行
    //任务队列中存放fn,当执行栈中的任务结束,它才停止等待,进入执行栈开始执行
    //结果输出1,2,3
  </script>
</body>

 案例分析(多个异步任务)

<body>
  <script>
    console.log(1);//同步
    document.onclick = function () {//document.click同步,function异步
      console.log('click');
    }
    console.log(2);//同步
    setTimeout(function () {//setTimeout同步,function异步
      console.log(3);
    }, 3000)
  </script>
</body>

以上执行机制如下

异步执行 python 异步执行机制_执行栈