在 JavaScript 中,BOM(Browser Object Model)指的是浏览器对象模型,它是一种用于表示和操作浏览器窗口、文档、历史记录等对象的模型。BOM 是 JavaScript 在浏览器环境中的核心组成部分,它与 DOM(文档对象模型)一起构成了 Web 开发的基石。


BOM的分类

>Navigator

用来表示浏览器的相关信息

userAgent 返回一个用来描述浏览器信息的字符串

<script>

    // console.log(navigator.userAgent)

    let sBrowser;
    const sUsrAg = navigator.userAgent;

    // The order matters here, and this may report false positives for unlisted browsers.

    if (sUsrAg.indexOf("Firefox") > -1) {
        sBrowser = "Mozilla Firefox";
        // "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0"
    } else if (sUsrAg.indexOf("SamsungBrowser") > -1) {
        sBrowser = "Samsung Internet";
        // "Mozilla/5.0 (Linux; Android 9; SAMSUNG SM-G955F Build/PPR1.180610.011) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/9.4 Chrome/67.0.3396.87 Mobile Safari/537.36
    } else if (sUsrAg.indexOf("Opera") > -1 || sUsrAg.indexOf("OPR") > -1) {
        sBrowser = "Opera";
        // "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 OPR/57.0.3098.106"
    } else if (sUsrAg.indexOf("Trident") > -1) {
        sBrowser = "Microsoft Internet Explorer";
        // "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; Zoom 3.6.0; wbx 1.0.0; rv:11.0) like Gecko"
    } else if (sUsrAg.indexOf("Edge") > -1) {
        sBrowser = "Microsoft Edge (Legacy)";
        // "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299"
    } else if (sUsrAg.indexOf("Edg") > -1) {
        sBrowser = "Microsoft Edge (Chromium)";
        // Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.64
    } else if (sUsrAg.indexOf("Chrome") > -1) {
        sBrowser = "Google Chrome or Chromium";
        // "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/66.0.3359.181 Chrome/66.0.3359.181 Safari/537.36"
    } else if (sUsrAg.indexOf("Safari") > -1) {
        sBrowser = "Apple Safari";
        // "Mozilla/5.0 (iPhone; CPU iPhone OS 11_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Mobile/15E148 Safari/604.1 980x1306"
    } else {
        sBrowser = "unknown";
    }
    alert(`You are using: ${sBrowser}`);
</script>

>Location

表示浏览器地址的详细信息

location.assign( ) 跳转到一个新的地址

location.replace( ) 跳转新的地址(无法回退)

location.reload( ) 刷新页面,可以通过 true 来刷新缓存

location.href( ) 获取当前地址

<button id=“btn”> 点我一下 </button>
<script>
    const btn = document.getElementById("btn")
    btn.addEventListener("click", () => {

        // console.log(location.href)

        // location = "https://w-flac.org.cn"

        // location.assign("https://w-flac.org.cn")

        // location.replace("https://w-flac.org.cn")

        location.reload(true)
    })
</script>

>History

表示浏览器的历史记录

history.back( ) 回退按钮

history.forward ( ) 前进按钮

history.go( ) 向前或向后

<button id=“btn”> 点我一下 </button>
<script>
    const btn = document.getElementById("btn")
    btn.onclick = () => {

        // console.log(history.length)

        // history.back()

        // history.forward()

        history.go(-1)

    }
</script>

>定时器

通过定时器可以使代码在指定时间后执行

setTimeout( ) 代码只执行一次

参数:

  • 回调函数

  • 间隔的时间

关闭定时器:

clearTimeout( )

<script>

const timer = setTimeout(()=>{
    alert("我是定时器中的代码")
}, 3000)

clearTimeout(timer)

</script>

setInterval( ) 代码每间隔一段时间执行一次

参数:

  • 回调函数

  • 间隔的时间

关闭定时器:

clearInterval( )

<h1 id="num"></h1>
<script>

const numH1 = document.getElementById("num");

let num = 0;

const timer = setInterval(() => {
    num++;
    numH1.textContent = num;

    if (num === 200) {
        clearInterval(timer);
    }
}, 30);

</script>

>事件循环(event loop)

在函数每次执行时,都会产生一个新的执行环境;执行环境负责存储函数执行时产生的一切数据。

Q:函数的执行环境要存储到哪里呢?

A:函数的执行环境存储到了一个叫做调用栈的地方。栈,是一种数据结构,特点:后进先出;队列,也是一种数据结构,特点:先进先出。

调用栈(call stack)

<script>
function fn() {
    let a = 10
    let b = 20

    function fn2() {
        console.log("fn2")
    }

    fn2()

    console.log("fn~")
}

fn()

console.log(1111)
</script>

消息列队

<button id=“btn”> 点我一下 </button>
<button id="btn02">点我一下2</button>
</script>
    const btn = document.getElementById("btn")
    const btn02 = document.getElementById("btn02")
    btn.onclick = function () {
        alert(1111)

        const begin = Date.now()

        while (Date.now() - begin < 3000) {}
    }

    btn02.onclick = function () {
        alert(2222)
    }
</script>

event loop.png

而定时器的本质的就是在指定时间后,将函数添加到消息队列中

<script>
    // console.time()
    // setTimeout(function(){
    //     console.timeEnd()
    //     console.log("定时器执行了~")
    // }, 3000)

    // 使程序卡6s
    // const begin = Date.now()
    // while (Date.now() - begin < 6000) {}

    /* 
    setInterval() 每间隔一段时间就将函数添加到消息队列中
    但是如果函数执行的速度比较慢,它是无法确保每次执行的间隔都是一样的
    */

    // console.time("间隔")
    // setInterval(function(){
    //     console.timeEnd("间隔")

    //     // console.log("定时器执行了~~")
    //     alert("定时器执行~")

    //     console.time("间隔")
    // }, 3000)

    /* 
    希望可以确保函数每次执行都有相同间隔
    */

    // console.time("间隔")
    // setTimeout(function fn() {
    //     console.timeEnd("间隔")
    //     alert("哈哈")

    //     console.time("间隔")
    //     // 在setTimeout的回调函数的最后,在调用一个setTimeout
    //     setTimeout(fn, 3000)
    // }, 3000)


    setTimeout(()=>{
        console.log(11111)
    }, 0)

    console.log(222222)
</script>