JavaScript的BOM模型

news2024/9/22 9:50:44

一、浏览器环境概述(BOM)

JavaScript 是浏览器的内置脚本语言,一旦网页内嵌了 JavaScript 脚本,浏览器加载网页,就会去执行脚本,从而达到操作浏览器的目的,实现网页的各种动态效果

二、script 元素工作原理

浏览器加载 JavaScript 脚本,主要通过<script>元素完成。

正常的网页加载流程是这样的:

  • 浏览器一边下载 HTML 网页,一边开始解析。也就是说,不等到下载完,就开始解析
  • 解析过程中,浏览器发现<script>元素,就暂停解析,把网页渲染的控制权转交给 JavaScript 引擎
  • 如果<script>元素引用了外部脚本,就下载该脚本再执行,否则就直接执行代码
  • JavaScript 引擎执行完毕,控制权交还渲染引擎,恢复往下解析 HTML 网页

加载外部脚本时,浏览器会暂停页面渲染,等待脚本下载并执行完成后,再继续渲染。

原因是 JavaScript 代码可以修改 DOM,所以必须把控制权让给它,否则会导致复杂的线程竞赛的问题。 如果外部脚本加载时间很长(一直无法完成下载),那么浏览器就会一直等待脚本下载完成,造成网页长时间失去响应,浏览器就会呈现“假死”状态,这被称为“阻塞效应”。

为了避免这种情况,较好的做法是将<script>标签都放在页面底部, 而不是头部。这样即使遇到脚本失去响应,网页主体的渲染也已经完成了,用户至少可以看到内容,而不是面对一张空白的页面。

2.1 defer 属性

为了解决脚本文件下载阻塞网页渲染的问题,一个方法是对<script>元素加入 defer 属性。它的作用是延迟脚本的执行,等到 DOM 加载生成后,再执行脚本

有了 defer 属性,浏览器下载脚本文件的时候,不会阻塞页面渲染

2.2 async 属性

解决“阻塞效应”的另一个方法是对<script>元素加入 async 属性

async 属性的作用是,使用另一个进程下载脚本,下载时不会阻塞渲染

async 属性可以保证脚本下载的同时,浏览器继续渲染。需要注意的是,一旦采用这个属性,就无法保证脚本的执行顺序。哪个脚本先下载结束,就先执行那个脚本。

一般来说,如果脚本之间没有依赖关系,就使用 async 属性,如果脚本之间有依赖关系,就使用 defer 属性。如果同时使用 async 和 defer 属性,后者不起作用,浏览器行为由 async 属性决定。

三、回流和重绘

渲染树转换为网页布局,称为“布局流”(flow);布局显示到页面的这个过程,称为“绘制”(paint)。它们都具有阻塞效应,并且会耗费很多时间和计算资源。 页面生成以后,脚本操作和样式表操作,都会触发“回流”(reflow) 和“重绘”(repaint)。

3.1 什么是回流和重绘?

回流:当节点树中的一部分因为元素的规模尺寸,布局,隐藏等改变而需要重新构建

重绘:当节点数中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的

3.2 什么时候会造成回流和重绘?

四、定时器

JavaScript 提供定时执行代码的功能,叫做定时器(timer),主要由 setTimeout() 和 setInterval() 这两个函数来完成。它们向任务队列添加定时任务

4.1 setTimeout() 

setTimeout 函数用来指定某个函数或某段代码,在多少毫秒之后执行。 它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器。

setTimeout 函数接受两个参数,第一个参数 func|code 是将要推迟执行的函数名或者一段代码,第二个参数 delay 是推迟执行的毫秒数。

解决方案

定时器可以进行取消

4.2 setInterval()

setInterval 函数的用法与 setTimeout 完全一致,区别仅仅在于 setInterval 指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行

通过setInterval方法实现网页动画


定时器可以进行取消

五、防抖(debounce)

防抖严格算起来应该属于性能优化的知识,但实际上遇到的频率相当高,处理不当或者放任不管就容易引起浏览器卡死。

从滚动条监听的例子说起:

先说一个常见的功能,很多网站会提供这么一个按钮:用于返回顶部。

这个按钮只会在滚动到距离顶部一定位置之后才出现,那么我们现 在抽象出这个功能需求-- 监听浏览器滚动事件,返回当前滚条与顶部的距离这个需求很简单,直接写

在运行的时候会发现存在一个问题:这个函数的默认执行频率, 太!高!了!。 高到什么程度呢?以chrome为例,我们可以点击选中一个页面的滚动条,然后点击一次键盘的【向下方向键】,会发现函数执行了8-9次!

然而实际上我们并不需要如此高频的反馈,毕竟浏览器的性能是有限的,不应该浪费在这里,所以接着讨论如何优化这种场景。 基于上述场景,首先提出第一种思路:在第一次触发事件时,不立 即执行函数,而是给出一个期限值比如200ms,然后

效果:如果短时间内大量触发同一事件,只会执行一次函数

实现:既然前面都提到了计时,那实现的关键就在于setTimeout这 个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现


到这里,已经把防抖实现了

六、节流(throttle)

节流严格算起来应该属于性能优化的知识,但实际上遇到的频率相当高,处理不当或者放任不管就容易引起浏览器卡死

继续思考,使用上面的防抖方案来处理问题的结果是如果在限定时间段内,不断触发滚动事件(比如某个用户闲着无聊,按住滚动不断的拖来拖去),只要不停止触发,理论上就永远不会输出当前距离顶部的距离但是如果产品同学的期望处理方案是:即使用户不断拖动滚动条,也能在某个时间间隔之后给出反馈呢? 其实很简单:我们可以设计一种类似控制阀门一样定期开放的函数,也就是让函数执行一次后,在某个时间段内暂时失效,过了这 段时间后再重新激活(类似于技能冷却时间) 效果:如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效

实现

这里借助setTimeout来做一个简单的实现,加上一个状态位valid来表示当前函数是否处于工作状态


如果一直拖着滚动条进行滚动,那么会以300ms的时间间隔,持续输出当前位置和顶部的距离讲完了这两个技巧,下面介绍一下平时开发中常遇到的场景:

七、window 对象

浏览器里面, window 对象(注意, w 为小写)指当前的浏览器窗口。 它也是当前页面的顶层对象,即最高一层的对象,所有其他对象都是它的下属

7.1 属性

①window.screenX,window.screenY

window.screenX window.screenY 属性,返回浏览器窗口左上角相对于当前屏幕左上角的水平距离和垂直距离(单位像素)。这两个属性只读 

②window.innerHeight,window.innerWidth

window.innerHeight window.innerWidth 属性,返回网页在当前窗口中可见部分的高度和宽度,即“视口”(viewport)的大小(单位像素)。这两个属性只读

③window.outerHeight,window.outerWidth

window.outerHeight window.outerWidth 属性返回浏览器窗口的高度和宽度, 包括浏览器菜单和边框(单位像素)。这两个属性只读

④window.scrollX,window.scrollY

window.scrollX 属性返回页面的水平滚动距离, window.scrollY 属性返回页面的垂直滚动距离,单位都为像素。这两个属性只读

⑤window.pageXOffset,window.pageYOffset

window.pageXOffset 属性和 window.pageYOffset 属性,是 window.scrollX window.scrollY 别名

7.2 方法

①window.alert(),window.prompt(),window.confirm()

window.alert() 、 window.prompt() 、 window.confirm() 都是浏览器与用户互动的全局方法。它们会弹出不同的对话框,要求用户做出回应。注意,这 三个方法弹出的对话框,都是浏览器统一规定的式样,无法定制

②window.alert()

window.alert() 方法弹出的对话框,只有一个“确定”按钮,往往用来通知用户某些信息

③window.prompt()

window.prompt() 方法弹出的对话框,提示文字的下方,还有一个输入框,要求用户输入信息,并有“确定”和“取消”两个按钮。它往往用来获取用户输入的数据

④window.confirm()

window.confirm() 方法弹出的对话框,除了提示信息之外,只有“确定”和 “取消”两个按钮,往往用来征询用户是否同意

confirm 方法返回一个布尔值,如果用户点击“确定”,返回 true ;如果 用户点击“取消”,则返回 false

⑤window.open()

window.open 方法用于新建另一个浏览器窗口,类似于浏览器菜单的新建窗口选项。它会返回新窗口的引用,如果无法新建窗口,则返回 null

八、Navigator 对象

window.navigator 属性指向一个包含浏览器和系统信息的 Navigator 对象。脚本通过这个属性了解用户的环境信息

①Navigator.userAgent

navigator.userAgent 属性返回浏览器的 User Agent 字符串,表示用户设备信息,包含了浏览器的厂商、版本、操作系统等信息

过 userAgent 可以大致准确地识别手机浏览器,方法就是测试是否包含 mobi 字符串

②Navigator.plugins

Navigator.plugins 属性返回一个类似数组的对象,成员是 Plugin 实例对象,表示浏览器安装的插件,比如 Flash、ActiveX 等

③Navigator.platform

Navigator.platform 属性返回用户的操作系统信息,比如 MacIntel 、 Win32 、 Linux x86_64 等

④Navigator.language,Navigator.languages

Navigator.language 属性返回一个字符串,表示浏览器的首选语言。该属性只读

Navigator.languages 属性返回一个数组,表示用户可以接受的语言

九、Screen 对象

Screen 对象表示当前窗口所在的屏幕,提供显示设备的信息。 window.screen 属性指向这个对象

①Screen.height

浏览器窗口所在的屏幕的高度(单位像素)。除非调整显示器的分辨率,否则这个值可以看作常量,不会发生变化。显示器的分辨率与浏览器设置无关,缩放网页并不会改变分辨率

②Screen.width

浏览器窗口所在的屏幕的宽度(单位像素)

③Screen.availHeight

浏览器窗口可用的屏幕高度(单位像素)。因为部分空间可能不可用,比如系统的任务栏或者 Mac 系统屏幕底部的 Dock 区,这个属性等于 height 减去那些被系统组件的高度

④Screen.availWidth

浏览器窗口可用的屏幕宽度(单位像素)

⑤Screen.pixelDepth

整数,表示屏幕的色彩位数,比如 24 表示屏幕提供24位色彩

⑥Screen.orientation

返回一个对象,表示屏幕的方向。该对象的 type 属性是一个字符串,表示屏幕的具体方向, landscape-primary 表示横放, landscape-secondary 表示颠倒的横放, portrait-primary 表示竖放, portrait-secondary 表示颠倒的竖放。

十、History 对象

window.history 属性指向 History 对象,它表示当前窗口的浏览历史 History 对象保存了当前窗口访问过的所有页面网址

①History.back()

History.back() :移动到上一个网址,等同于点击浏览器的后退键。对于第一个访问的网址,该方法无效果 

②History.forward()

History.forward() :移动到下一个网址,等同于点击浏览器的前进键。对于最后一个访问的网址,该方法无效果

③History.go()

History.go() :接受一个整数作为参数,以当前网址为基准,移动到参数指定的网址,比如 go(1) 相当于 forward() , go(-1) 相当于 back() 。如果参数超过实际存在的网址范围,该方法无效果;如果不指定参数,默认参数为 0 ,相当于刷新当前页面

十一、Cookie 对象

Cookie 是服务器保存在浏览器的一小段文本信息,每个 Cookie 的大小一般不能超过4KB。浏览器每次向服务器发出请求,就会自动附上这段信息

Cookie 的目的就是区分用户,以及放置状态信息,它的使用场景主要如下:

Cookie 不是一种理想的客户端存储机制。它的容量很小(4KB), 缺乏数据操作接口,而且会影响性能。客户端存储建议使用 Web storage API 。只有那些每次请求都需要让服务器知道的信息,才应该放在 Cookie 里面。

每个 Cookie 都有以下几方面的元数据:

  • Cookie 的名字
  • Cookie 的值(真正的数据写在这里面)
  • 到期时间(超过这个时间会失效)
  • 所属域名(默认为当前域名)
  • 生效的路径(默认为当前网址)

不同浏览器对 Cookie 数量和大小的限制,是不一样的。一般来 说,单个域名设置的 Cookie 不应超过30个,每个 Cookie 的大小不 能超过 4KB。超过限制以后,Cookie 将被忽略,不会被设置

读取cookie

①Expires

Expires 属性指定一个具体的到期时间,到了指定时间以后,浏览器就不再保留这个 Cookie。它的值是 UTC 格式,可以使用 Date.prototype.toUTCString() 进行格式转换

如果不设置该属性,或者设为 null ,Cookie 只在当前会话 (session)有效,浏览器窗口一旦关闭,当前 Session 结束,该 Cookie 就会被删除。另外,浏览器根据本地时间,决定 Cookie 是否过期,由于本地时间是不精确的,所以没有办法保证 Cookie 一定会在服务器指定的时间过期。

②Max-Age

Max-Age 属性指定从现在开始 Cookie 存在的秒数,比如 60 * 60 * 24 * 365 (即一年)。过了这个时间以后,浏览器就不再保留这个 Cookie 如果同时指定了 Expires 和 Max-Age ,那么 Max-Age 的值将优先生效

③Domain

Domain 属性指定 Cookie 属于哪个域名,以后浏览器向服务器发送 HTTP 请求时,通过这个属性判断是否要附带某个 Cookie

④Path

Path 属性指定浏览器发出 HTTP 请求时,哪些路径要附带这个 Cookie。只要浏览器发现, Path 属性是 HTTP 请求路径的开头一部分,就会在头信息里面带上这个 Cookie。比如, Path 属性是 / ,那么请求 /docs 路径也会包含该 Cookie。当然,前提是 Domain 属性 必须符合条件

⑤Secure

Secure 属性指定浏览器只有在加密协议 HTTPS 下,才能将这个 Cookie 发送到服务器。另一方面,如果当前协议是 HTTP,浏览器 会自动忽略服务器发来的 Secure 属性。该属性只是一个开关,不需要指定值。如果通信是 HTTPS 协议,该开关自动打开

⑥HttpOnly

HttpOnly 属性指定该 Cookie 无法通过 JavaScript 脚本拿到,主要是 document.cookie 属性、 XMLHttpRequest 对象和 Request API 都拿不到该属性。这样就防止了该 Cookie 被脚本读到,只有浏览器发出 HTTP 请求时,才会带上该 Cookie

⑦封装cookie操作


⑧apply、call和bind函数

无论是apply、call还是bind其实都是改变this的指向,我们先来看一个例子

下面我们来看一下通过他们来改变this指向

由此得出结论,bind 返回的是一个新的函数,你必须调用它才会被执行

我们再来看一下apply和call的区别

第一个参数:this的指向,第二个参数为方法传递参数

常见应用场景

null代表指向window对象,这里是因为Array本身时候window对象的子元素

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2101703.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络编程 0903作业

作业 1、将TCP的CS模型再敲一遍 tcpserver.c #include <myhead.h> #define SERPORT 1111 #define SERIP "192.168.58.128" #define BACKLOG 40 int main(int argc, const char *argv[]) {int oldfd socket(AF_INET,SOCK_STREAM,0);//1、产生一个原始套接字…

pikachu文件包含漏洞靶场

File inclusion(local) 创建1.php 步骤一&#xff1a;选择一个球员提交 ../../../../1.php File Inclusion(remote)&#xff08;远程文件包含&#xff09; 步骤一&#xff1a;更改参数 php.ini ⾥有两个重要的参数 allow_url_fopen 、allow_url_include &#xff1b; 步骤二…

玩机进阶教程-----如何通过boot查看当前机型版本号 型号以及启动分区 提升保资料写固件成功率

在玩机过程中我们会遇到一些无法开机进系统的机型。而有需要其中的数据。如果简单的写入固件。可能会由于与当前机型版本不符或者版本差别太大的缘故而导致资料无法保存。如果当前机型有版本仿回滚机制。那么有可能误刷系统也会不开机。那么如何通过简单的操作来查看当前机型的…

GAMES202——作业5 实时光线追踪降噪(联合双边滤波、多帧的投影与积累、À-Trous Wavelet 加速单帧降噪)

任务 1.实现单帧降噪 2.实现多帧投影 3.实现多帧累积 Bonus:使用-Trous Wavelet 加速单帧降噪 实现 单帧降噪 这里实现比较简单&#xff0c;直接根据给出的联合双边滤波核的公式就能实现 Buffer2D<Float3> Denoiser::Filter(const FrameInfo &frameInfo) {int heigh…

科研小白教程|如何远程连接实验室服务器跑代码?

博主简介&#xff1a;努力学习的22级计算机科学与技术本科生一枚&#x1f338;博主主页&#xff1a; Yaoyao2024往期回顾&#xff1a; 【计算机系统架构】从0开始构建一台现代计算机|时序逻辑、主存储器|第3章每日一言&#x1f33c;: 总之岁月漫长&#xff0c;然而值得等待。—…

国内可以免费使用的gpt网站【九月持续更新】

GPT Hub 是我最近使用的一款智能文本生成工具平台&#xff0c;它支持多种AI模型&#xff0c;包括最新的GPT-4模型&#xff0c;并且可以在国内网络环境中直接访问。以下是我在使用过程中发现的一些特点&#xff1a; 多功能支持&#xff1a;不仅支持代码生成&#xff0c;还涵盖了…

【主机入侵检测】Wazuh解码器之JSON解码器

前言 Wazuh 是一个开源的安全平台&#xff0c;它使用解码器&#xff08;decoders&#xff09;来从接收到的日志消息中提取信息。解码器将日志信息分割成字段&#xff0c;以便进行分析。Wazuh 解码器使用 XML 语法&#xff0c;允许用户指定日志数据应该如何被解析和规范化。解码…

Java基础(10)- 学生管理系统项目

一、JavaBean编写 public class Student {private int id;private String name;private int age;private String sex;public Student() {}public Student(int id, String name, int age, String sex) {this.id id;this.name name;this.age age;this.sex sex;}public int g…

绝对定位导致内容自动换行问题解决

今天在做一个定位元素的时候遇到一个嵌套定位之后&#xff0c;使用绝对定位的元素的内容自动换行的问题&#xff0c;希望不换行只在一行显示。 可以通过添加 white-space: nowrap; 样式控制不换行 <div class"box"><div class"box1"><div …

深入剖析:中国国际大学生创新大赛中不可忽视的12个扣分点

深入剖析&#xff1a;中国国际大学生创新大赛中不可忽视的12个扣分点 前言1. 项目名称&#xff1a;第一印象的力量2. 项目逻辑&#xff1a;清晰的思路是关键3. 问题分析&#xff1a;深入挖掘痛点4. 需求分析&#xff1a;解决方案的导向5. 科研课题与评审维度的匹配6. 团队介绍&…

DataWhale AI夏令营-《李宏毅深度学习教程》笔记-task3

DataWhale AI夏令营-《李宏毅深度学习教程》笔记-task2 第五章 循环神经网络5.1 独热编码5.2 RNN架构5.3 其他RNN5.3.1 Elman 网络 &Jordan 网络5.3.2 双向循环神经网络 第五章 循环神经网络 循环神经网络RNN&#xff0c;RNN在处理序列数据和时间依赖性强的问题上具有独特…

渗透测试靶机--- DC系列 DC-6

渗透测试靶机— DC系列 DC-6 开启靶机&#xff0c;登录页面&#xff0c;平平无奇 扫描ip&#xff0c;端口&#xff0c;服务等信息 访问80&#xff0c;发现这里是WordPress站点 直接wpscan扫描一下用户名wpscan --url http://wordy -e u 这里可以将扫出来的五个用户名保存&…

WPF性能优化之UI虚拟化

文章目录 前言一、VirtualizingStackPanel1.1 虚拟化功能介绍1、在Window中添加一个ListBox控件。2、在设计视图中用鼠标选中ListBox控件并右健依次单击“编辑其他模板”&#xff0d;“编辑项的布局模板”&#xff0d;“编辑副本”。3、查看生成的模板代码。 1.2 虚拟化参数介绍…

如何提升网站权重?

提升网站权重的方法有很多&#xff0c;常规的方法包括内容优化、关键词研究、页面结构调整、提高用户体验等。但这些方法往往需要时间来见效。如果你希望在短时间内看到显著的提升&#xff0c;发外链是一个非常有效的策略。 外链是提升网站权重的有效方法&#xff0c;但需要注…

9月3c++

封装栈和队列 队列 #include <iostream> #include <cstring> using namespace std; class Myqueue { private:int data[256];int size0; public:Myqueue(){}//无参构造~Myqueue(){}//析构//拷贝赋值Myqueue & operator(const Myqueue &other){if(this!&a…

C++ ─── List的模拟实现

一&#xff0c; List的模拟实现 List 是一个双向循环链表,由于List的节点不连续&#xff0c;不能用节点指针直接作为迭代器&#xff0c;因此我们要对结点指针封装&#xff0c;来实现迭代器的作用。 迭代器有两种实现方式&#xff0c;具体应根据容器底层数据结构实现&#xff1…

15、VSCode自定义Markwown编辑环境

前言 &#xff1a;Visual Studio Code (VSCode) 是微软推出的一款开源编辑器&#xff0c;使用 Electron 打造&#xff0c;与 Atom 齐名&#xff0c;不过随着 Atom 社区的渐渐缩小&#xff0c;VSCode 的影响力开始越来越大了。VSCode 内置了 Markdown 语言及预览的支持&#xff…

每周12600元奖金池,邀你与昇腾算力共舞,openMind开发者盛宴启幕!

小伙伴们&#xff0c;是否瞬间被这个标题唤醒了在OpenI启智社区“我为开源打榜狂”黄金时代的温馨记忆&#xff1f;打榜活动虽已谢幕&#xff0c;但大家相伴度过12期的那份激情与创新的共鸣&#xff0c;促使OpenI启智社区在国产算力崛起的浪潮中勇立潮头&#xff0c;推出了“芯…

JavaScript是什么

前言 初始JavaScript JavaScript是什么 JavaScript (简称 JS) 是世界上最流行的编程语言之一 是一个脚本语言, 通过解释器运行 主要在客户端(浏览器)上运行, 现在也可以基于 node.js 在服务器端运行. JavaScript 最初只是为了完成简单的表单验证(验证数据合法性), 结果后…

git 回滚的三种方式

按照从旧到新的顺序 你依次提交了 1 2 3 4 5 现在你想回到1 如何操作 第一种方法 hard reset git reset --hard 执行命令后 你会发现 效果实现了 东西都回到了那次更改 但是2345的更改都没了 并且你会发现 你有更新 这是因为这个hard reset 只会改本地的 远程的不改 一更新就…