# 认识 BOM

  • JavaScript 有一个非常重要的运行环境就是浏览器,而且浏览器本身又作为一个应用程序需要对其本身进行操作,所以通常浏览器会有对应的对象模型(BOM,Browser Object Model)。
    • 我们可以将 BOM 看成是连接 JavaScript 脚本与浏览器窗口的桥梁。
  • BOM 主要包括一下的对象模型:
    • window:包括全局属性、方法,控制浏览器窗口相关的属性、方法;
    • location:浏览器连接到的对象的位置(URL);
    • history:操作浏览器的历史;
    • document:当前窗口操作文档的对象;
  • window 对象在浏览器中有两个身份:
    • 身份一:全局对象。
      • 我们知道 ECMAScript 其实是有一个全局对象的,这个全局对象在 Node 中是 global;
      • 在浏览器中就是 window 对象;
    • 身份二:浏览器窗口对象。
      • 作为浏览器窗口时,提供了对浏览器操作的相关的 API;

# Window 全局对象

  • 在浏览器中,window 对象就是之前经常提到的全局对象,也就是我们之前提到过 GO 对象:
    • 比如在全局通过 var 声明的变量,会被添加到 GO 中,也就是会被添加到 window 上;
    • 比如 window 默认给我们提供了全局的函数和类:setTimeout、Math、Date、Object 等;
  • 通过 var 声明的变量,全局提供的类和方法:
var message = 'Hello World'
function foo(){
    console.log('foo function')
}
window.console.log(window.message)
window.foo()
window.setTimeout(() => window.console.log('setTimeout'), 1000)
...
  • 这些用法是我们之前讲过的,并且也是作为 JavaScript 语言本身所拥有的一些特性。
    • 那么接下来我们来看一下作为窗口对象,它拥有哪些特性。

# Window 窗口对象

  • 事实上 window 对象上肩负的重担是非常大的:
    • 第一:包含大量的属性,localStorage、console、location、history、screenX、scrollX 等等(大概 60 + 个属性);
    • 第二:包含大量的方法,alert、close、scrollTo、open 等等(大概 40 + 个方法);
    • 第三:包含大量的事件,focus、blur、load、hashchange 等等(大概 30 + 个事件);
    • 第四:包含从 EventTarget 继承过来的方法,addEventListener、removeEventListener、dispatchEvent 方法;
  • 那么这些大量的属性、方法、事件在哪里查看呢?
    • MDN 文档:https://developer.mozilla.org/zh-CN/docs/Web/API/Window
  • 查看 MDN 文档时,我们会发现有很多不同的符号,这里我解释一下是什么意思:
    • 删除符号:表示这个 API 已经废弃,不推荐继续使用了;
    • 点踩符号:表示这个 API 不属于 W3C 规范,某些浏览器有实现(所以兼容性的问题);
    • 实验符号:该 API 是实验性特性,以后可能会修改,并且存在兼容性问题;

# window 常见的属性

  • 我们来看一下常见的 window 属性

# window.screenX

  • 返回浏览器左边界到操作系统桌面左边界的水平距离
  • screeX 是返回相对于当前屏幕的 X 坐标,有多块屏幕以主屏幕为准
screenX = window.screenX
  • screeX 为浏览器左边到系统桌面左边的像素值
  • 不妨将窗口缩小打印试试吧~
if (window.screenX) console.log(window.screenX)

# window.screenY

  • 返回浏览器顶部距离系统桌面顶部的垂直距离。

  • ScreenY 是返回相对于当前屏幕的 Y 坐标,有多块屏幕以主屏幕为准

screenY = window.screenY
  • screenY 距离屏幕顶部的像素值。

  • 不妨将窗口缩小打印试试吧~

if (window.screenY) console.log(window.screenY)

# window.outerHeight

  • Window.outerHeight 获取整个浏览器窗口的高度(单位:像素),包括侧边栏(如果存在)、窗口镶边(window chrome)和窗口调正边框(window resizing borders/handles)
  • 该属性为只读,没有默认值。
  • outWindowHeight 为窗口的外层的高度
outWindowHeight = window.outerHeight;
console.log(outWindowHeight)

# Window.innerHeight

  • 浏览器窗口的视口(viewport)高度(以像素为单位);如果有水平滚动条,也包括滚动条高度
  • window.innerHeight 属性为只读,且没有默认值
  • intViewportHeight 为浏览器窗口的视口的高度
const intViewportHeight = window.innerHeight;
console.log(intViewportHeight)

# Window.scrollX

  • 返回文档 / 页面水平方向滚动的像素值
var x = window.scrollX
  • x 为该文档从左侧开始滚动的像素值
if (window.scrollX) console.log(window.scrollX)
  • pageXOffset 属性是 scrollX 属性的别名
window.pageXOffset === window.scrollX // 总是 true

# Window.scrollY

  • 返回文档在垂直方向已滚动的像素值
var y = window.scrollY
  • y 是文档从顶部开始滚动过的像素值。
if (window.scrollY) console.log(window.scrollY)
  • pageYOffset 属性是 scrollY 属性的别名
window.pageYOffset === window.scrollY // 总是返回 true

# window 常见的方法

  • 我们来看一下常见的 window 方法

# scrollTo()

  • 滚动到文档中的某个坐标
  • x-coord 是文档中的横轴坐标。
  • y-coord 是文档中的纵轴坐标。
  • window.scrollTo(x-coord, y-coord)
window.scrollTo(0, 100) // 向下滚动 100px
  • window.scrollTo(options)
  • options 是一个包含三个属性的对象:
  • left 等同于 x-coord
  • top 等同于 y-coord
window.scrollTo({
  left: 100,
  top: 100
})
  • behavior 类型 String, 表示滚动行为,支持参数 smooth (平滑滚动),instant (瞬间滚动), 默认值 auto
window.scrollTo({
  top: 100,
  behavior: "smooth"
})

# open()

  • Window 接口的 open() 方法,是用指定的名称将指定的资源加载到浏览器上下文(窗口 window ,内嵌框架 iframe 或者标签 tab )。如果没有指定名称,则一个新的窗口会被打开并且指定的资源会被加载进这个窗口的浏览器上下文中。
let windowObjectReference = window.open(strUrl, strWindowName, [strWindowFeatures]);
  • strUrl === 要在新打开的窗口中加载的 URL。
  • strWindowName === 新窗口的名称。
  • strWindowFeatures === 一个可选参数,列出新窗口的特征 (大小,位置,滚动条等) 作为一个 DOMString
  • 详情参考 MDN https://developer.mozilla.org/zh-CN/docs/Web/API/Window/open
window.open("https://nekoaimer.com", "_self") // 当前窗口打开
window.open("https://nekoaimer.com", "_target") // 新窗口打开

# close()

  • Window.close() 方法关闭当前窗口或某个指定的窗口
  • 当直接调用 window 对象的 close() 方法而非在一个 window 实例上调用 close() 时,浏览器会关闭最前面的窗口,无论是不是你的脚本创建的这个窗口。
window.close()
  • 简写也是可以的
close()

# window 常见的事件

  • 我们来看一下常见的 window 事件

# load()

  • 当整个页面及所有依赖资源如样式表和图片都已完成加载时,将触发 load 事件

  • 它与 DOMContentLoaded 不同,后者只要页面 DOM 加载完成就触发,无需等待依赖资源的加载

  • 当页面及资源完全加载后在控制台打印一段信息:

window.addEventListener('load', (event) => console.log('window窗口加载完毕~'))
  • 也可以使用 onload 实现:
window.onload = function() {
  console.log("window窗口加载完毕~")
}

# focus()

  • focus 事件在元素获取焦点时触发。这个事件和 focusin 最大的区别仅仅在于后者会事件冒泡.
  • 当点击屏幕获取焦点打印信息
window.addEventListener('focus', (event) => console.log('window窗口获取焦点~'))
  • 也可以使用 onfocus 实现:
window.onfocus = function() {
  console.log("window窗口获取焦点~")
}

# blur()

  • 将焦点移出顶层窗口
  • window.blur()
  • 当 window 窗口失去焦点打印信息
window.addEventListener('blur', (event) => console.log('window窗口失去焦点~'))
  • 也可以使用 onblur 实现:
window.onblur = function() {
  console.log("window窗口失去焦点~")
}

# Location: hash

  • Location 接口的 hash 属性返回一个 USVString ,其中会包含 URL 标识中的 '#' 和 后面 URL 片段标识符
  • 首次打印应该是为空
console.log(location.hash === ‘‘) // true
  • location.hash 修改为 nekoaimer
console.log(location.hash) // #nekoaimer
console.log(location.hash === '') // false
console.log(location.hash === '#nekoaimer') // true

# EventTarget

  • Window 继承自 EventTarget,所以会继承其中的属性和方法:
    • addEventListener:注册某个事件类型以及事件处理函数;
    • removeEventListener:移除某个事件类型以及事件处理函数;
    • dispatchEvent:派发某个事件类型到 EventTarget 上;

# addEventListener()

  • EventTarget.addEventListener() 方法将指定的监听器注册到 EventTarget 上,当该对象触发指定的事件时,指定的回调函数就会被执行。 事件目标可以是一个文档上的元素 Element , Document Window 或者任何其他支持事件的对象 (比如 XMLHttpRequest )
  • addEventListener() 的工作原理是将实现 EventListener 的函数或对象添加到调用它的 EventTarget 上的指定事件类型的事件侦听器列表中
  • type 表示监听事件类型的字符串
  • listener 当所监听的事件类型触发时,会接收到一个事件通知(实现了 Event 接口的对象)对象。 listener 必须是一个实现了 EventListener 接口的对象,或者是一个函数。有关回调本身的详细信息,请参阅 The event listener callback
  • window 点击了打印 console.log 信息
window.addEventListener("click", () => console.log("window发生了点击"))
  • options 可选 一个指定有关 listener 属性的可选参数对象
    • capture : Boolean ,表示 listener 会在该类型的事件捕获阶段传播到该 EventTarget 时触发。
    • once : Boolean ,表示 listener 在添加之后最多只调用一次。如果是 true, listener 会在其被调用之后自动移除。
    • passive : Boolean ,设置为 true 时,表示 listener 永远不会调用 preventDefault() 。如果 listener 仍然调用了这个函数,客户端将会忽略它并抛出一个控制台警告。查看 使用 passive 改善的滚屏性能 了解更多.
    • signal AbortSignal ,该 AbortSignal abort() 方法被调用时,监听器会被移除。
const clickHandler = () => console.log("window发生了点击")
window.addEventListener("click", clickHandler, {once: true}) // 打印一次
window.addEventListener("click", clickHandler, {once: false}) // 打印多次
  • 返回值是 undefined
const clickHandler = () => console.log("window发生了点击")
const res = window.addEventListener("click", clickHandler, { once: true })
console.log(res) // undefined
  • 详情参考 MDN https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener

# removeEventListener()

  • 删除使用 EventTarget.addEventListener() 方法添加的事件。使用事件类型,事件侦听器函数本身,以及可能影响匹配过程的各种可选择的选项的组合来标识要删除的事件侦听器。
  • type 一个字符串,表示需要移除的事件类型,如 "click"
  • listener 需要从目标事件移除的 EventListener 函数。
  • options 可选 一个指定事件侦听器特征的可选对象
    • capture : 一个 Boolean 表示这个类型的事件将会被派遣到已经注册的侦听器,然后再派遣到 DOM 树中它下面的任何 EventTarget
    • mozSystemGroup : 仅可运行于 XBL 或者 Firefox Chrome,它是一个 Boolean ,用于定义是否将侦听器添加到系统组。
  • 详情参考 MDN https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/removeEventListener
const clickHandler = () => {
  console.log("window发生了点击")
  window.removeEventListener("click", clickHandler)
}
window.addEventListener("click", clickHandler)
  • 点击一次后就取消事件,实现 once 效果
  • 返回值是 undefined
const res = window.addEventListener("click", clickHandler)
console.log(res) // undefined

# dispatchEvent()

  • 向一个指定的事件目标派发一个事件,并以合适的顺序同步调用目标元素相关的事件处理函数。标准事件处理规则 (包括事件捕获和可选的冒泡过程) 同样适用于通过手动的使用 dispatchEvent() 方法派发的事件
cancelled = !target.dispatchEvent(event)
  • event 是要被派发的事件对象
  • target 被用来初始化 事件 和 决定将会触发 目标
window.addEventListener("nekoaimer", (event) => console.log("监听到了nekoaimer 事件"))
window.dispatchEvent(new Event("nekoaimer"))
  • 返回值 当该事件是可取消的 (cancelable 为 true) 并且至少一个该事件的 事件处理方法 调用了 Event.preventDefault() ,则返回值为 false ;否则返回 true
const res = window.dispatchEvent(new Event("nekoaimer"))
console.log(res) // true
  • 详情参考

    • MDN https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/dispatchEvent
    • 阮一峰 JavaScript 教程 https://www.bookstack.cn/read/javascript-tutorial/docs-events-eventtarget.md
  • 更多事件 https://developer.mozilla.org/zh-CN/docs/Web/Events

# Location 对象常见的属性

  • Location 对象用于表示 window 上当前链接到的 URL 信息。

  • 常见的属性有哪些呢?

    • href: 当前 window 对应的超链接 URL, 整个 URL

    • protocol: 当前的协议

    • host: 主机地址

    • hostname: 主机地址 (不带端口)

    • port: 端口

    • pathname: 路径

    • search: 查询字符串

    • hash: 哈希值

    • username:URL 中的 username(很多浏览器已经禁用)

    • password:URL 中的 password(很多浏览器已经禁用)

  • 下面演示几个

console.log(location.protocol) // http:
console.log(location.host) // 127.0.0.1:5500
console.log(location.hostname) // 127.0.0.1
console.log(location.port) // 5500

# Location 对象常见的方法

  • 我们会发现 location 其实是 URL 的一个抽象实现:

url

  • location 有如下常用的方法:
    • assign:赋值一个新的 URL,并且跳转到该 URL 中
    • replace:打开一个新的 URL,并且跳转到该 URL 中(不同的是不会在浏览记录中留下之前的记录)
    • reload:重新加载页面,可以传入一个 Boolean 类型

# assign()

  • Location.assign() 方法会触发窗口加载并显示指定的 URL 的内容
  • url 一个包含了要跳转到的链接的 DOMString
  • location.assign(url)
location.assign("http://nekoaimer.com")
  • 下面这种写法效果与上面是一样的
location.href = "http://nekoaimer.com"

# replace()

  • **Location** .replace() 方法以给定的 URL 来替换当前的资源。 与 assign() 方法 不同的是,调用 replace() 方法后,当前页面不会保存到会话历史中(session History ),这样,用户点击回退按钮时,将不会再跳转到该页面
  • url DOMString 类型,指定所导航到的页面的 URL 地址。
  • object.replace(url)
location.replace("http://nekoaimer.com") // 不能回退

# reload()

  • Location.reload() 方法用来刷新当前页面。该方法只有一个参数,当值为 true 时,将强制浏览器从服务器加载页面资源,当值为 false 或者未传参时,浏览器则可能从缓存中读取页面
object.reload(forcedReload)
  • forcedReload 可选 该参数要求为 布尔 (en-US) 类型,当取值为 true 时,将强制浏览器从服务器重新获取当前页面资源,而不是从浏览器的缓存中读取,如果取值为 false 或不传该参数时,浏览器则可能会从缓存中读取当前页面
// 无缓存刷新页面(但页面引用的资源还是可能使用缓存,
// 大多数浏览器可以通过设置在打开开发者工具时禁用缓存实现无缓存需求)
window.location.reload(true)
  • 详情查看 MDN https://developer.mozilla.org/zh-CN/docs/Web/API/Location/reload

# history 对象常见属性和方法

  • history 对象允许我们访问浏览器曾经的会话历史记录
  • 有两个属性:
    • length:会话中的记录条数
    • state:当前保留的状态值
  • 有五个方法:
    • back ():返回上一页,等价于 history.go (-1)
    • forward ():前进下一页,等价于 history.go (1)
    • go ():加载历史中的某一页
    • pushState ():打开一个指定的地址
    • replaceState ():打开一个新的地址,并且使用 replace
  • 下面举两个栗子

# pushState()

  • history.pushState(state, title[, url])
const state = { 'page_id': 1, 'user_id': 5 }
const title = ''
const url = 'hello-world.html'
history.pushState(state, title, url)
  • 详情查看 MDN -> https://developer.mozilla.org/zh-CN/docs/Web/API/History/pushState

# replaceState()

  • replaceState() 方法使用 state objects , title , 和 URL 作为参数, 修改当前历史记录实体,如果你想更新当前的 state 对象或者当前历史实体的 URL 来响应用户的的动作的话这个方法将会非常有用
history.replaceState(stateObj, title[, url])
  • stateObj 状态对象是一个 JavaScript 对象,它与传递给 replaceState 方法的历史记录实体相关联
  • title 大部分浏览器忽略这个参数,将来可能有用。在此处传递空字符串应该可以防止将来对方法的更改。或者,您可以为该状态传递简短标题
  • url 可选 历史记录实体的 URL. 新的 URL 跟当前的 URL 必须是同源;否则 replaceState 抛出一个异常.
history.replaceState({ foo: "bar" }, "", "bar.html")
  • 详情查看 MDN -> https://developer.mozilla.org/zh-CN/docs/Web/API/History/replaceState
Update on Views times

Give me a cup of [coffee]~( ̄▽ ̄)~*

Nico Niconi WeChat Pay

WeChat Pay

Nico Niconi Alipay

Alipay