web前端复习提纲

web前端复习提纲+2023回忆

参考自 zhy 的博客 2020-Web前端开发-Exam01-Summary - SpriCoder的博客

feat: 新增若干内容

1. 基础知识

1.1. Internet

Internet 是在一个通信网络中连接的计算机的大规模集合,通过装置连接起来,相互之间可以通信。

1.1.1. IP

根据端到端的设计原则,IP 只为主机提供一种无连接、不可靠的、尽力而为的数据包传输服务。

1.1.2. URI、URL、URN

  1. URI(统一资源标识符,Uniform Resource Identifier) 允许资源驻留在 Internet 上的任何位置

  2. URL(统一资源定位符,Uniform Resource Locator) 显示资源副本的位置

  3. URN(统一资源名称,Uniform Resource Name) 是资源的唯一名称

  4. URL、URN 是 URI 的子集,其中 URL 和 URN 有交集。

1.1.3. DNS

  1. DNS 之前,转换是通过 FTP 到中央服务器上下载 hosts.txt 文件

  2. DNS(Domain Name System) 是一个分布式数据库,本地负责控制整个数据库的部分段,客户向 DNS 服务器请求,得到从域名到 IP 地址的转化。

  3. DNS 是唯一同时使用 TCP 和 UDP 的

    • 在 DNS 域中的主备冗余机制中,进行同步通信时使用 TCP 协议,原因在于其可靠性
    • 在用户通过浏览器访问 DNS 服务器请求 IP 地址时使用 UDP 协议
  4. 工作过程:

    1. 客户向域名服务器发起查询请求
    2. 域名服务器本地查询结果
      1. 如果找到,则返回
      2. 如果未找到则发送到根域名服务器,根域名服务器查询根域名解析,将包含下一级域名信息的 DNS 地址返回给客户的域名服务器。
    3. 客户的域名服务器根据根域名服务器解析的地址访问下一级 DNS,如此递归逐级查询,直到找到位置。【迭代查询和递归查询】
    4. 客户的域名 DNS 服务器将查询结果返回客户机。
    5. 客户根据 IP 地址访问目标机。

1.1.4. Http1.1、/2、/3 协议

阶段 描述
HTTP1.0 非持续连接,每一次请求/响应建立并拆除一次连接,即短链接,2 个 RTT 时间,使用 TCP 链接;http 1.0中默认是关闭的,需要在http头加入**“Connection: Keep-Alive”**,才能启用Keep-Alive
HTTP1.1 支持 keepalive 持久连接,即长连接,在相同 TCP 上通讯,http 1.1中默认启用Keep-Alive,如果加入**"Connection: close ",才关闭;支持流水线请求,可以不等反馈发送很多信息,不应该与任何服务器或代理保持超过2个连接,目前的主要版本
报文
头部不会被压缩**【body 可以】,即使两个 header 非常相似也在重复传输
HTTP2.0 ⼆进制协议而不是⽂本协议;支持 HTTP1.1,在数据如何封装成帧上有区别头部压缩,请求和响应多路复用
HTTP3.0 和 HTTP2 完全不同,使用 UDP 协议,通过重传保证效率
**为什么需要 3:**TCP队头阻塞问题;TCP握手时长;IP地址会发生变化 TCP 协议是根据四元组来确定⼀个连接的,需要重新建立连接

1.1.4.1. 结构

HTTP 请求和响应具有相似的结构,由以下部分组成:

  1. ⼀行起始行用于描述要执行的请求类型,或者是对应的状态,成功或失败。这个起始行总是单行的。

  2. ⼀个可选的 HTTP 头集合指明请求或描述消息正文。

  3. ⼀个空行指示所有关于请求的元数据已经发送完毕

  4. ⼀个可选的包含请求相关数据的正文 (比如 HTML 表单内容),或者响应相关的文档。正文的大小有起始行的 HTTP 头来指定。

  5. image-20230223163423238

1.1.4.2. 请求方法

  • GET :从服务器获取URL对应的资源

  • HEAD :除了服务器响应中不能包含消息体,该方法与GET⼀样。HEAD请求方法作用是只请求头部

  • POST :被设计用来注解、修改URL所对应的资源

  • PUT :被设计用来修改或创建资源。当URL对应的资源存在时,则提交的作为新版本,否则新建资源

    • 区别:PUT 方法是幂等的:连续调用一次或者多次的效果相同(无副作用)。连续调用同一个 POST 可能会带来额外的影响,比如多次提交订单。
  • DELETE :被设计用来删除URL对应的资源

  • TRACE :主要用来测试。服务器将最终接收到的请求本身发送回来,作为客户端诊断依据

  • OPTIONS :客户端查询服务器对与某 URL 允许的通信选项

  • CONNECT :保留的方法名,用于代理切换隧道

1.1.4.3. HTTP 头域/头部

  • 通用头标:即可用于请求,也可用于响应,是作为⼀个整体而不是特定资源与事务相关联。

  • 请求头标:允许客户端传递关于自身的信息和希望的响应形式。

  • 响应头标:服务器和于传递自身信息的响应。

  • 实体头标:定义被传送资源的信息。即可用于请求,也可用于响应。

1.1.4.4. 响应状态行

  • http协议版本

  • 状态码(三位数字)

  • 状态描述

HTTP/1.1 200 OK

状态码

  • 信息响应 (100–199)

  • 成功响应 (200–299)

  • 重定向消息 (300–399)

  • 客户端错误响应 (400–499)

  • 服务端错误响应 (500–599)

常用状态码

  • 200 OK

  • 301 Moved Permanently 搜索引擎会删除原页面,收录重定向的页面,并转移权重

  • 302 Found 是一种临时性的重定向,大部分搜索引擎把它作为内部的重定向,不会缓存重定向的结果

  • 400 Bad Request

  • 401 Unauthorized

  • 403 forbidden

  • 404 Not Found 搜索引擎放弃对该链接的索引

  • 500 Internal Server Error

1.2. 网络机器人

  1. 网络爬虫是以自动方式爬取万维网上信息的计算机程序;主要是用来从网页搜集信息/支持搜索引擎/开展数据分析等等

  2. 传统爬虫:传统爬虫从一个或若干初始网页的 URL 开始,获得初始网页上的 URL ,在抓取网页的过程中不断从当前页面上抽取新的 URL 放入队列 直到满足系统的一定停止条件

  3. 网络爬虫排除标准

    Robots Exclusion Protocol,网站通过 Robots 协议告诉搜索引擎哪些页面可以抓取,哪些不能抓取。

    robots 是一个协议。robots.txt 文件是一个文本文件,放置在网站根目录下

1.3. web

1.3.1. Web 的发展

  1. Web x.0 表示 的是一个阶段,是促成这个阶段的各种技术和相关产品服务的一个称呼

  2. Web1.0 网站提供给用户的内容是网站编辑进行编辑处理后提供的,用户阅读网站提供的内容。这个过程是网站到用户的单向行为,比如搜狐等,静态网页为主。

  3. Web2.0 则是以加强了网站与用户之间的互动,网站内容基于用户提供,网站的诸多功能也由用户参与建设,实现了网站与用户双向的交流与参与,比如博客中国等。

  4. web3.0 是以主动性、数字最大化、多维化等为特征的,以服务为内容的第三代互联网系统。

1.3.2. Web 前端的发展趋势

  1. 静态页面 到 动态页面

  2. Ajax 到 JIT(即时编译),REST,SPA(单页Web应用)

  3. 交互、UI、逻辑 到 Nodejs 大前端、同构(同一份代码在浏览器端和服务器端都可以运行)趋势

1.3.3. MEAN

  1. Mean:Mongo Express Angular Node,是一个 Javascript 平台的现代 Web 开发框架总称

    1. MongoDB 是一个使用JSON 风格存储的数据库,非常适合 javascript。(JSON 是 JS 数据格式 )
    2. ExpressJS 是一个 Web 应用框架,提供有帮助的组件和模块帮助建立一个网站应用。
    3. AngularJS 是一个前端 MVC 框架。
    4. Node.js 是一个并发异步 事件驱动的 Javascript 服务器后端开发平台。

2. 浏览器端

2.1. HTML/XHTML

  1. HTML:标记语言,结构化特征。

  2. 优雅降级与渐进增强

    1. 渐进增强(Progressive Enhancement):一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。
    2. 优雅降级(Graceful Degradation):一开始就构建站点的完整功能,然后针对浏览器测试和修复。比如一开始使用 CSS3 的特性构建了一个应用,然后逐步针对各大浏览器进行 hack 使其可以在低版本浏览器上正常浏览。
    3. 向上兼容向下兼容的概念。渐进增强相当于向上兼容,而优雅降级相当于向下兼容

2.1.1. 结构、表现、行为

结构:

  1. DOCTYPE:声明了使用的文档类型定义(DTD)

  2. Head:包含元数据,一般只需要 title 标签

  3. Body:需要渲染的文本

HTML 工作流程

  1. HTML 通过标记符标记要显示的网页的各个部分,通过添加标记符来确定内容格式,从而令浏览器知道如何显示网页

  2. 浏览器按顺序阅读 HTML 文件,然后根据 HTML 标记符解释和显示各种内容,这就是语法分析过程

  3. HTML 中的超链接功能使得网页之间能够链接起来从而提供跳转功能

2.1.2. 基本语法、常用标记

常用标记

块级元素<h1>~<h6>,<p>,<div>,<ul>,<ol>,<li>

行内元素<a>,<strong>,<b>,<em>,<del>,<span>

  1. 注释

    1
    <!-- 注释 -->

    上线产品不要包含注释:

    • 注释(明文传播)会提高页面被解读的风险

    • 注释会增加传输带宽消耗

  2. title

    1
    <title></title>
    • 描述网页标题

    • 位于 head 标签之间

    • 精简且语义化强的描述能吸引爬虫

  3. meta

    1
    <meta>
    • 描述网页元数据

    • 位于 head 标签之间

    • 其 Charset 属性在实际中非常重要

  4. p

    1
    <p></p>
    • 用于表示段落,位于 body 之间

  5. br

    1
    <br>
    • 在 HTML 中,<br>标签没有结束标签。

    • 在 XHTML 中,<br> 标签必须被正确地关闭,比如这样:<br />。

  6. a

    1
    <a href=""></a>
    • 指向其他页面的链接

    • 使用 href 属性来指定目的 url,可以是绝对路径或相对路径

    • 行级元素,要在 p 或 h1 等块级元素中

  7. img

    1
    <img src="" alt="">
    • 向页面中插入图片

    • src 属性指定了图片 url

    • xhtml 还需要 alt 属性

    • 在 a 标签之间放置会变为链接

    • .git 和 .png 无损,.jpeg 和 .webp 有损

  8. table,tr,td,th,caption

    • table 代表表体
    • caption 是标题
    • tr 表示一行,th 表示表头,td 表示值
  9. quotation

    • blockquote 是段落引用,可以用于 p 标签外将段落变为引用格式(斜体)
    • q 是行内引用,可以用于单词两边,效果是添加上双引号

    为什么不直接用引号而用 <q>

    1. XHTML 不应该包含字面引号字符,它们应该被写成 &quot

    2. 用 <q> 能让我们将 CSS 样式应用于引号

  10. form

    1
    <form action="" method="" target=""></form>
    • 用于在网页上创建 GUIs,目的通常是向用户请求信息

    • 其参数指定 js 如何将信息传至服务器

      • action 指定 submit 按下后数据送往的地点
      • method 默认为 GET,能以 ?{form_data} 形式传出,data 全为 ASCII 码且不超过 100 字符;POST 将 data 放置于 body 部分
      • target 指定响应页面的打开方式(当前或新窗口)
    • form 元素有 button,checkbox,text,radio

  11. input

    1
    <input type="text" hidden>
    • 强大,但从语义化角度讲不是好的设计,因为具体样式渲染要等读到 type 属性值才能确定

    • 不需要 JS,H5 新增原生日期、颜色选择器以及其他新类型,提供客户端表单验证机制和旋转框、滑块

  12. canvas

    1
    <canvas></canvas>
    • 提供本地绘画功能

    • 可用于图表、图像、动画和像素处理等

    • 支持 2D 和 3D 效果

  13. video&audio

    • 提供非插件式视频&音频支持,可以用 JS 进行操作,CSS 进行渲染
    • 能像添加图片一样添加
    • 可以使用内容,有完整的 JS API 供使用

2.1.3. html 语义化

  1. 语义化:根据结构化内容选择合适标签

    1. 简单来说就是用特定的标签体现相对应的功能
    2. 将内容和功能展示分离
  2. 为什么?

    1. 有利于 SEO(Search Engine Optimization)
    2. 开发维护体验好
    3. 用户体验好
    4. 更好的可访问性,方便任何设备对代码解析。

2.1.4. html5 新特性——为什么选择 H5

  1. 语义化的元素(如header,nav,article,aside,footer标签)

  2. 表单验证功能:<input type=email required>

  3. 语法简化:简化了解析的标题<!DOCTYPE html>

  4. 统一:支持所有语言。

  5. 减少对外部插件的需求 ( 比如 Flash):支持很多复杂的特性 ( 视频音频图像 ) 而不需要安装插件,原生支持

    1. 插件可能安装失败、被禁用、被屏蔽,或者成为被攻击的对象。
  6. 默认的安全性:HTML 为 iframe 元素添加了 sandbox 属性,防止不信任的 Web 页面某些操作。

  7. 平滑降级:旧浏览器中新的表单控件会平滑降级,将 input $\rightarrow$ text

  8. 不建议过多的使用 div,因为其是无语言元素

  9. 新输入类型-color、date

  10. audio&video 标签

  11. Canvas 像素级操作,放大缩小会变形

  12. SVG 矢量量图

  13. 新元素:article section footer nav mark

  14. 更优秀的错误处理

  15. 早前本地存储使用的是 cookie,但是Web 存储更加的安全与快速

    客户端存储数据的两个对象为:【js可以从这里面获取需要的数据】

    • localStorage - 用于长久保存整个网站的数据,保存的数据没有过期时间,直到手动去除。

    • sessionStorage - 用于临时保存同一窗口(或标签页)的数据,在关闭窗口或标签页之后将会删除这些数据。

    HTML5 引⼊了应用程序缓存,这意味着 web 应用可进行缓存,并可在没有因特网连接时进行访问。通过创建 cache manifest 文件,可以轻松地创建 web 应用的离线版本

2.1.5. 向前兼容 IE

越来越多的站点开始使用HTML5标签。但情况是还有很多人在使用IE6,IE7,IE8。为了让所有网站浏览者都能正常的访问网站,有两种解决办法:

  1. 网站创建多套模板,通过程序对User-Agent的判断给不同的浏览器用户显示不同的页面,比如优酷网就是采用的这种模式。

  2. 使用Javascript使不支持HTML5的浏览器支持HTML标签。很多网站采用的这种方式。

针对IE浏览器比较好的解决方案是html5shivhtml5shiv主要解决HTML5提出的新的元素不被IE6-8识别

2.2. CSS

Cascading Style Sheets

$css \rightarrow css2 \rightarrow css2.1 \rightarrow css3$

css 由选择器+声明块组成。

2.2.1. CSS 优势

  1. 丰富的样式定义

  2. 灵活:易于使用和修改

  3. 简洁、清晰

  4. 多页面应用

  5. 多设备兼容性:样式表允许针对多种不同类型的设备进行优化内容。

  6. 减少开发成本与维护成本

  7. 提高页面性能

2.2.2. CSS 2.1,3 新特性

  1. CSS 2.1:选择器、媒体类型、盒模型、tables、分级媒体。

  2. CSS 3:模块化、使用特定于浏览器的前缀[确保这种属性只在特定的浏览器渲染引擎下才能识别和生效]、web字体、显著提高性能,比如圆角、渐变、变换和过渡等。

2.2.3 选择器

  1. id选择器

  • 标有特定 id 的 HTML 元素指定特定的样式。

    • 下面的样式规则将应用于有属性id=“para1"的元素
      • #para1 {text-align:center;color:red;}
      • <p id='para1'></p>
  1. class选择器

    • class 选择器在 HTML 中以 class 属性表示, 在 CSS 中,类选择器以一个点 . 号显示

      • 在以下的例⼦中,所有拥有 center 类的 HTML 元素均为居中
        • .center {text-align:center;}
    • 可以在前面加上标签限定

      • span.classy {} 就只作用于下面的 HTML 代码

        1
        <span class="classy">Here's a span with some text.</span>
  2. 标签选择器

    • 指定所有的该标签的样式
    • p{color:red;text-align:center;}选择 p 标签

  3. 属性选择器

    • 这组选择器根据一个元素上的某个标签的属性是否存在以选择元素的不同方式:

      • [title]{color:blue;}
    • 或者根据一个标签的特定属性是否存在来选择:

      • <h1 title=“Hello world”>Hello world</h1>
  4. 伪类选择器

    • 使用 :

    • CSS伪类是用来添加一些选择器的特殊效果(如 hover、点击等)

    • 如下设置不同状态的链接的颜色

      • a:link {color:#000000;} /* 未访问链接*/
      • a:visited {color:#00FF00;} /* 已访问链接 */
      • a:hover {color:#FF00FF;} /* ⿏标移动到链接上 */
      • a:active {color:#0000FF;} /* ⿏标点击时 */
  5. 伪元素选择器

    • 使用 ::

    • 伪元素,选择一个元素的某个部分而不是元素自己。例如,::first-line是会选择一个元素(下面的情况中是<p>)中的第一行。

      1
      2
      3
      4
      5
      /* 每一个 <p> 元素的第一行。 */
      p::first-line {
      color: blue;
      text-transform: uppercase;
      }
  6. 组合选择器

    • 后代选择器(以空格分隔),所有的后代

      1
      2
      3
      4
      div p
      {
      background-color:yellow;
      }

      image-20230222163406345

    • 子元素选择器(以大于号分隔)【标签元素的第一代子元素

      image-20221126211305232

      div input后代选择器会把放在

      中的 input 也选中,而div>input子元素选择器只会选中 input type=text

    • 相邻兄弟选择器(以加号分隔)

      image-20230222163629160
    • 后续兄弟选择器(波浪号分隔)

      image-20230222163638709

    相邻只选择后面的一个,后续则选择后续的所有

2.2.4 层叠

  1. 样式表的三个层次,按照从底层到高层的顺序,分别为

    1. 行内样式表
    2. 嵌入样式表
    3. 外部样式表
  2. 浏览器能够像获取其他文档那样获取样式表文件。标签<link>用于指定外部样式表。

  3. 规则

    1. 使用建议:外部 > 内部 > 内联
    2. 一般不使用内联,因为只能声明一个元素,不能复用
    3. 外部样式表是最好的,可复用
  4. CSS 来源优先级:【从上到下是由低到高】

    1. 用户代理样式表中的常规声明(例如,浏览器的默认样式,在没有设置其他样式时使用
    2. 用户样式表中的常规声明(由用户设置的自定义样式
    3. 作者样式表中的常规声明(这些是我们 web 开发人员设置的样式)。
    4. 作者样式表中的 !important 声明
    5. 用户样式表中的 !important 声明
    6. 用户代理样式表中的 !important 声明
  5. 样式冲突的处理规则

    1. 资源顺序

      • 当优先级与多个 CSS 声明中任意一个声明的优先级相等的时候,CSS 中最后的那个声明将会被应用到元素上
    2. 优先级

      • 优先级就是分配给指定的 CSS 声明的一个权重,它由匹配的选择器中的每一种选择器的类型的数值决定。

      • 左面的最大,数位之间没有进制,级别之间不可超越。

      • ID属性的数量——属性选择器伪类的数量——元素名伪元素的数量

      • image-20221128151322960

        (上图最后::not() 伪类的优先级将由其逗号分割的参数中优先级最高的选择器指定)

      • 每个!important值:无穷大

        内联样式和 !important 都被认为是非常不好的做法,但是有时你可以在 CSS 文件里用 !important 去覆盖内联样式。

  6. 继承

    可以被继承: colortext-alignfont-family

    不会被继承:widthmarginpaddingborder

2.2.5. CSS 盒模型

  1. 所有元素都是一个盒子

    image-20221123110911988

  2. 元素总宽度 $=width + border_{left} + border_{right} + magin_{left} + magin_{right} + padding_{left} + padding_{right}$

  3. 元素总高度 $=height + border_{top} + border_{bottom} + magin_{top} + magin_{bottom} + padding_{top} + padding_{bottom}$

  4. Internet Explorer 默认使用的怪异盒模型,与上面的不同的是 height 和 weight 包含了填充和边框。

    通过设置 box-sizing: border-box 可以告诉浏览器使用怪异盒模型

2.2.6. 布局

正常流:

  • 从左到右,从上到下

  • 如果两个相邻的元素都设置了 margin 并且两个 margin 有重叠,那么更大的设置会被保留,小的则会消失 — 这被称为外边距叠加。

脱离正常流

  1. absolute:相对最近绝对定位的祖先,如果没有那么选择文档主体

  2. relative:相对其正常流中的位置进行定位

  3. fixed:相对视口定位,滚动页面也不改位置

  4. static:HTML 元素默认 static,静态定位元素不受 top 等的影响

  5. sticky:它的行为就像 position:relative; 而当页面滚动超出目标区域时,它的表现就像 position:fixed;,它会固定在目标位置。

  6. float:

    image-20230222174237171

2.2.7. Formatting Context 格式化上下文

页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作 用。

  1. Block Formatting Context 块级格式化上下文 ref:什么是BFC

    BFC是一个完全独立的空间(布局环境),让空间里的子元素不会影响到外面的布局

    1. 触发BFCCSS属性

      • overflow 值不为 visible、clip 的块元素
      • display: inline-block
      • position: absolute
      • position: fixed
      • display: table-cell
      • display: flex
    2. BFC 规则

      • BFC内部块级元素会在垂直方向一个接一个的排列

      • BFC就是页面中的一个隔离的独立容器,容器里的标签不会影响到外部标签

      • 垂直方向的距离由margin决定, 属于同一个BFC的两个相邻的标签外边距会发生重叠

      • 计算BFC的高度时,浮动元素也参与计算

      • BFC的区域不会与float box重叠

    3. 用途

      • 高度塌陷:将父元素设置为 BFC【如设置 display: inline-block】可以解决了父元素未设置高度,而子元素设置浮动后,造成子元素脱离文档流无法把父元素撑开,父元素高度为 0 的问题。
      • 外边距重叠:如果想要消除两个相邻标签的外边距重叠,那么可以为其中一个元素包裹一个盒子形成一个完全独立的空间【如用 div 包裹】,里面元素不受外面布局影响
      • 排开外部浮动,避免重叠【实现多栏布局】:由于 BFC 不会和浮动块重叠,当一个块浮动时会覆盖原本在那个位置的,把原本那个位置的块设置为 BFC【如 display:flex】可以使原来的块移动到浮动元素的右边而不重叠
  2. Inline Formatting Contexts 行内格式化上下文 ref:IFC

    1. 触发条件:块级元素中仅包含行内元素

    2. 规则:

      1. 横向的margin、border、padding属性对于这些行内元素都是有效的
      2. 一个IFC内的元素都是⽔平排列的
    3. IFC中时不可能有块级元素的,当插入块级元素时(如p中插入div)会产生两个匿名块与div分隔开,产生两个IFC,每个IFC对外表现为块级元素,与div垂直排列。

    4. 用途:

      1. 水平居中:当一个块要在环境中水平居中时,设置其为inline-block则会在外层产生IFC,通过text-align则可以使其水平居中。

      2. 垂直居中:创建一个IFC,用其中一个元素撑开父元素的高度,然后设置其vertical-align:middle,其他行内元素则可以在此父元素下垂直居中。如下面的文本就能和图片垂直居中

        image-20230222190957264

2.2.8. 响应式网页设计,主要手段

  1. 响应式网页设计 (RWD,Responsive Web Design),可以自动识别屏幕宽度、并作出相应调整网页。

  2. 曾经流行,不再是必不可少,原因:

    • 公司研发⼈员越来越充足,可以在pc端和移动端实现两套布局,分项目进行维护。

    仍有存在的价值:

    • 物联网领域,任何设备界面的响应布局。

    • 体现了CSS的灵活性

  3. 优点:网站可用性大大提升、简化服务器端、易维护、只提供给搜索引擎一个入口、可支持未知设备。

  4. 缺点兼容设备导致性能低下、代码冗余 ( 加载时间变长 ),限制应用复杂性 ( 折衷的设计方案 )、用户混淆 ( 改变了网站布局 )

  5. 主要手段:

    1. CSS 媒体查询 ( 不同屏幕分辨率,不同 CSS 规则 )
    2. 不使用绝对大小,而使用相对大小:width:20%/autopx/em【em 相对于当前对象内文本的字体尺寸。如当前对文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸 16px。】
    3. 流动布局
    4. 图片自动缩放

2.3. javascript 重要

2.3.1. 基本语法

可以写在 body 中、head 中或外部文件中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- body -->
<body>
<script>
document.write("<h1>This is a heading</h1>");
document.write("<p>This is a paragraph.</p>");
</script>
</body>
<!-- head -->
<head>
<script>
function myFunction(){
document.getElementById("demo").innerHTML="My First JavaScript Function";
}
</script>
</head>
<!-- 外部文件 -->
<script src="url" type="text/javascript">
! script commands and comments
</script>
  1. JavaScript 拥有动态类型:这意味着相同的变量可用作不同的类型

  2. 大小写敏感 (HTML 大小写不敏感)

  3. 不指定类型,但有类型:Number, Boolean, String, Array, Object, Function, Null, Undefined

    • typeof()可以知道类型
  4. Number

    • 数值在内部都是通过IEEE 754 64位双精度浮点型的形式表示的 (没有 int double 的区别)
    • 运算符有自动的类型转换,Ex. “2” * 3 is 6
  5. String

    1. 没有 char 类型,一个字符也是存成 String
    2. +可以用来连接字符串
    3. 1+1 is 2, but “1”+1 is “11”
    4. image-20221130104151749
  6. Boolean

    • 任何值都可以用作布尔值

      • false:0, -0, 0.0, NaN, “”, null, undefined

      • true:其他的所有

    • 将值显式转换为布尔值

      • var boolValue = Boolean(otherValue);

      • var boolValue = !!(otherValue);

  7. image-20221130104636619

  8. 逻辑运算符

    • 大多数逻辑运算符会自动转换类型

      image-20221130104954720

      平常业务中比较建议尽量不要使用 == 和 !=。这两个比较的时候会做一些强制的类型转换

      务必使用 === 和 !==。【严格的相等检查,不会进行类型转换,同时比较类型和值

      • Ex. “5.0” === 5 is false

  9. Arrays

    1. 两种初始化方式
      • var empty=[];
      • var mycars=new Array();
        • var mycars=new Array(1, ‘22’, true);也可以直接赋值,且数组中元素的类型可以不一样
    2. 不需要指定长度,在添加元素时根据需要自动增加
  10. Function

    1. function functionName(parameters) { // }

    2. 箭头=>函数,如:

      (arg1, arg2) => {// code}

    3. 匿名方法

      (function (x,y) {return x+y}) (2,3);

2.3.2. 严格模式

  1. 脚本或函数头使用添加use strict;的目的是指代码在严格条件下执行。

  2. 为什么使用严格模式

    1. 消除 js 语法的一些不合理、不严谨的地方,减少怪异的行为
    2. 消除代码运行的不安全
    3. 提供编译器效应,增加运行效率
    4. 未来版本的 js 做好铺垫
  3. 严格模式限制:

    1. 变量必须声明后使用
    2. 函数参数不可以同名
    3. 不可以使用 with 语句
    4. 不能对只读属性赋值
    5. 不能使用前缀 0 表示八进制
    6. 不可以删除不可删除属性
    7. 不可以使用 delete prop 删除变量,只能删除属性 delete global[prop]
    8. eval 不会从它的外层作用域引入变量
    9. eval 和 arguments 不可以被重新赋值
    10. arguments 不会自动反应函数参数变化
    11. 不能使用 arguments.callee.caller
    12. 禁止this指向全局对象
    13. 不能使用 fn.caller.arguments获取函数调用的堆栈
    14. 增加了保留字protectedstaticinterface

2.3.3. 函数

  1. 头等函数 (first-class function) 是指在程序设计语言中,函数被当作头等公民。

  2. 函数可以作为别的函数的参数、函数的返回值,赋值给变量或存储在数据结构中。在这样的语言中,函数的名字没有特殊含义,它们被当作具有函数类型的普通的变量对待。

  3. image-20230223102211209
  4. 匿名函数

    1. 匿名函数就是声明一个函数不起名字。

    2. 如果匿名函数只要一处调用,那么在调用处声明,调用完就销毁了

      1
      2
      3
      4
      5
      6
      // 例子:声明
      var double = function(x){return 2 * x;}
      // 声明后立即调用
      (function(x, y){
      alert(x + y);
      })(2, 3);

2.3.4. 事件驱动编程

  1. JavaScript 事件允许脚本响应用户与网页上元素的交互,通过回调编程。JS 是采用事件驱动的机制来响应用户操作的

  2. 事件驱动编程是一种编程范式,其中程序流由事件决定,诸如用户操作(鼠标点击、按键)、传感器输出或来自其他程序/线程的消息

  3. 在事件驱动应用中,会有 listener 主循环监听事件【事件需要注册才会被监听】,并且在被触发时调用一个 **callback **方法

  4. 语法

    • element.addEventListener(event, function, useCapture);

      • 第⼀个参数是事件类型 (如"click" 或"mousedown").
      • 第⼆个参数是我们想在事件发生时调用的回调函数.
      • 第三个参数是⼀个布尔值,是否在捕获时执行事件处理函数【详见 DOM】,是可选参数,默认 false 表示在事件冒泡阶段调用事件处理函数;如果参数为true,则表示在事件捕获阶段调用处理函数。
    • removeEventListener() 方法删除已由 addEventListener() 方法注册的事件处理程序

    • document.getElementById("myDiv").addEventListener("click",  myFunction, true); document.getElementById("myDiv").removeEventListener("mousemove", myFunction);
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31

      ### 2.3.5. 面向对象

      <img src="https://wbl-z-pic.obs.cn-east-3.myhuaweicloud.com/image-20230223104423246.png" alt="image-20230223104423246" style="zoom:50%;" />

      1. 用 JavaScript 实现类 JavaScritpt 没有专门的机制实现类,这里是借助**它的函数允许嵌套**的机制来实现类的。一个函数可以包含变量,又可以包含其它函数,这样,变量可以作为属性,内部的函数就可以作为成员方法了。因此外层函数本身就可以作为一个类了。
      2. 类声明:`function myClass() { //此处相当于构造函数 }`,这里 myClass 就是一个类。其实可以把它看成类的构造函数。至于非构造函数的部分,以后会详细描述。
      3. 类新建:`var obj1 = new myClass();`,JavaScript 提供了一个方法可以获得对象实例。即 new 操作符。其实 JavaScript 中,类和函数是同一个概念,当用 new 操作一个函数时就返回一个对象。
      4. 对象的成员的引用在 JavaScript 中引用一个类的属性或方法的方法有以下三种。
      1. 点号操作符:这是一种最普遍的引用方式,就不累赘。即如下形式:`对象名.属性名; 对象名.方法名;`
      2. 方括号引用:JavaScript 中允许用方括号引用对象的成员。如下:`对象名["属性名"]; 对象名["方法名"];`
      1. 这里方括号内是代表属性或方法名的字符串,不一定是字符串常量。也可以使用变量。这样就可以使用**变量**传递属性或方法名。为编程带来了方便。在某些情况下,代码中不能确定要调用那个属性或方法时,就可以采用这种方式。否则,如果使用点号操作符,还需要使用条件判断来调用属性或方法。
      2. 另外,使用方括号引用的属性和方法名还可以以**数字**开头,或者出现**空格**,而使用点号引用的属性和方法名则遵循标示符的规则。但一般不提倡使用非标示符的命名方法。
      3. 迭代器遍历:`for item in obj`
      5. prototype 属性:每个构造函数有一个`prototype`属性,指向另一个**原型对象**,这个对象的所有属性和方法会被**所有对象实例所共享**

      ```js
      // 每个实例对象的 type 和 eat 都是一样的,每次生成一些示例其实是重复的内容,多占用内存
      functlon Cat(name,color){
      this.name = nane;
      this.color = color;
      this.type = "猫科动物";
      this.eat = function(){alert("吃老鼠");
      };
      // 使用 prototype 对象,那么创建的每个对象就不会重复相同的内容
      function Cat(name ,color){
      this.name = name;
      this.color = color ;
      )
      Cat.prototype.type = "猫科动物";
      Cat.prototype.eat = function(){alert("吃老鼠");

2.3.6. 作用域、作用域链、闭包及其用途

  1. 作用域是在运行时代码中的某些特定部分中变量、函数和对象的可访问性子作用域可以访问父作用域, 反过来则不行

    1. 最大作用:隔离变量,不同作用域下同名变量不会有冲突。

    2. JS 作用域类型

      1. 全局作用域

        • 最外层函数和最外层函数外声明的变量
        • 所有未定义直接赋值的变量,即自动全局
        • 所有 window 对象的属性
      2. 模块作用域

        • 模块模式中运行代码的作用域
      3. 函数作用域

        • 只能在函数中访问

        • 函数中可以访问全局等外部的,但是外部不可以访问内部的

        • ES6 之前块语句(大括号“{}”中间的语句),如 if 和 switch 条件语句或 for 和 while 循环语句,不像函数,它们不会创建一个新的作用域。在块语句中定义的变量将保留在它们当前存在的作用域中。即 变量提升

          1
          2
          3
          4
          5
          6
          7
          if(true){
          var name1 = 'Tim';// 是在全局作用域中的
          }
          console.log(name1);// 'Tim'
          function f(){
          var name2 = 'Ray';// 是在函数作用域中的
          }
        • 函数提升函数声明会被提升到顶部,但函数表达式不会,只是函数表达式左边的变量会被提升,在声明之前访问 baz 是 undefined,因此报错不是一个函数

          • /* 函数声明 */
            foo(); // "bar"
            function foo() {
             console.log("bar");
            }
            /* 函数表达式 */
            baz(); // 类型错误:baz 不是⼀个函数
            var baz = function() {
             console.log("bar2");
            };
            
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            26
            27
            28
            29
            30
            31
            32
            33
            34
            35
            36
            37
            38
            39
            40
            41
            42
            43
            44
            45
            46
            47
            48
            49
            50
            51
            52
            53

            4. **ES6**出现:**块级作用域**:{}创建

            - 块级作用域可通过**新增命令 let 和 const 声明**,所声明的变量在指定块的作用域外无法被访问。

            - **TDZ 暂时性死区**(英temporal dead zone),即代码块开始到变量声明语句完成之间的区域,不像 var,let 拥有暂时性死区,在这个区域内不能使用这个变量。

            - ```js
            //1. TDZ
            {
            console.log(bar); // undefined,可以访问但是是未定义的,因为当前没有赋值
            console.log(foo); // ReferenceError,不能访问,有暂时性死区
            var bar = 1;
            let foo = 2; // End of TDZ (for foo)
            }
            // 但下面这样是可以的,即暂时性的意思是取决于执行的顺序,而不是编写代码的顺序,func在暂时性死区外执行,因此可以
            {
            // TDZ starts at beginning of scope
            const func = () => console.log(letVar);
            let letVar = 3; // End of TDZ (for letVar)
            func();
            }

            //2. 声明变量不会提升到代码块顶部
            function getValue(condition) {
            if (true) {
            let value = "blue";
            return value;
            } else {
            // value 在此处不可用
            return null;
            }
            // value 在此处不可用
            }

            //3. 禁止重复声明,如果一个标识符已经在代码块内部被定义,那么在此代码块内使用同一个标识符进行 let 声明就会导致抛出错误,而声明var则可以
            var count = 30;
            let count = 40; // Uncaught SyntaxError: Identifier 'count' has already been declared

            // 在嵌套作用域中不会抛出错误
            var count = 30;
            var condition = 1;
            if (condition) {
            let count = 40;
            // 其他代码
            }

            //4. 循环中的绑定块作用域的妙用,如果使用 var 声明 i 的话,就会导致 i 成为全局变量,点击任何按钮都是输出4,因为i都变成了 4
            for (let i = 0; i < 4; i++) {
            button[i].onclick = function () {
            console.log('第' + (i + 1) + '个')
            }
            }
  2. 作用域链

    1. 自由变量:当前的作用域没有定义的变量,找值则需要向(创建函数的)父级作用域查找,一直往上。

      注意:无论函数将在哪里调用,要到创建函数的那个父作用域中取

    2. 这种一层一层的查找父作用域的关系,就是作用域链

    3. // 例 1
      var x = 10
      function fn() {
        console.log(x)
      }
      function show(f) {
        var x = 20
        (function() {
          f() //10,而不是 20
        })()
      }
      show(fn)
      // 例 2
      var a = 10
      function fn() {
        var b = 20
        function bar() {
          console.log(a + b) //30
        }
        return bar
      }
      var x = fn()
      b = 200
      x() //bar()
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43

      4. > 作用域和执行上下文之间最大的区别是:
      >
      > **执行上下文在运行时确定,随时可能改变;作用域在定义时就确定,并且不会改变**。

      3. **闭包**

      1. 是可以读取其他函数内部变量的函数

      2. 由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"**定义在一个函数内部的函数**"。

      3. ```js
      function f1(){
        var n=999;
      // 匿名函数,本质也是闭包,nAdd是全局变量
        nAdd=function(){n+=1;}
      // f2 闭包函数
      function f2(){
         alert(n);
        }
      return f2;
      }
      // f2 被赋值被全局变量,因此 f2 一直在内存中,而 f2 依赖于 f1,于是 f1 也在内存中,而不会在调用结束后被垃圾回收机制回收。
      var result=f1();
      result(); // 999
      nAdd();
      result(); // 1000

      // 关于 this 的例子
      // this 和调用时有关,而不是创建时
      var name="XL";
      var person={
      name:"xl",
      showName:function(){
      console.log(this.name);
      }
      }
      person.showName();// xl
      //这里是 person 对象调用 showName 方法,很显然 this 关键字是指向 person 对象的,所以会输出 name

      var showNameA=person.showName;
      showNameA(); //输出 XL
      //这里将 person.showName 方法赋给 showNameA 变量,此时 showNameA 变量相当于 window 对象的一个属性,因此 showNameA() 执行的时候相当于 window.showNameA(),即 window 对象调用 showNameA 这个方法,所以 this 关键字指向 window
    4. 闭包用途

      1. 实现私有成员

      2. 保护命名空间

      3. 避免污染全局变量

      4. 变量需要长期驻留内存

  3. with——不使用

    1. 不推荐使用with,在 ECMAScript 5 严格模式中该标签已被禁止。【出现 with js 引擎不进行任何优化,性能差,且可能会导致数据泄露问题】

      推荐的替代方案是声明⼀个临时变量来承载你所需要的属性,如下面例子中的重复写 obj

    2. with 语句的原本用意是为逐级的对象访问提供命名空间式的速写方式

    3. with 代码块内部,每个变量首先被认为是一个局部变量,如果局部变量与 obj 对象的某个属性同名,则这个局部变量会指向 obj 对象属性

    4. // 例子
      var obj = {
      	a: 1,
      	b: 2,
      	c: 3
      };
      // 重复写了3次的“obj”
      obj.a = 2;
      obj.b = 3;
      obj.c = 4;
      // 如果使用with,则可以不用写
      with (obj) {
      	a = 3;
      	b = 4;
      	c = 5;
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69

      5. **this**:

      **显式绑定**:通过call、apply、bind、new 确定指向

      > **call、apply、bind 都是用来改变 this 的指向的,第一个参数都是 this 要指向的对象。**
      >
      > - call 只是临时改变一次 this 指向,并立即执行函数。但后面参数形式是 `obj.myFun.call(db,'成都','上海');`
      > - apply 只是临时改变一次 this 指向,并立即执行函数。但后面参数是 `obj.myFun.apply(db,['成都','上海']); `
      > - bind 返回一个永久改变 this 指向的函数,不会立即执行函数,它的参数形式和 call 一样。

      **隐式绑定**:根据调用关系确定this指向

      - 在函数体中,非显式或隐式地简单调用函数时,在**严格**模式下,函数内的this会被绑定到 **undefined **上,在**非严格模式下则会被绑定到全局对象 window **上【例子1,2】

      - ⼀般通过上下文对象调用函数时,函数体内的 this 会被绑定到该对象上【例子3,4】

      ```js
      // 例子1
      function f1() {
      console.log(this);
      }
      function f2() {
      "use strict";
      console.log(this);
      }
      f1(); // window
      f2(); // undefined

      // 例子2
      var foo = {
      bar: 10,
      fn: function() {
      console.log(this)
      }
      }
      var fn1 = foo.fn
      fn1()// window,因为是用window来调用的

      // 例子3
      var foo = {
      bar: 10,
      fn: function() {
      console.log(this)
      console.log(this.bar)
      }
      }
      foo.fn()// {bar:10,fn:f},这里是由foo调用

      // 例子4
      var o1 = {
      text: 'o1',
      fn: function() {
      return this.text
      } }
      var o2 = {
      text: 'o2',
      fn: function() {
      return o1.fn()
      } }
      var o3 = {
      text: 'o3',
      fn: function() {
      var fn = o1.fn
      return fn()
      } }
      console.log(o1.fn())// o1,o1调用
      console.log(o2.fn())// o1,在o2中o1进行调用,因此o1中的this指向o1
      console.log(o3.fn())// undefined,return fn(),直接调用函数,不指名this,则this默认指向window,即fn就是由window来调用的,而window中没有text属性,因此是undefined
    • 通过 call/apply/bind 方法显示调用函数时,函数体内的 this 会被绑定到指定参数的对象上。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      const foo = {
      name: 'Tim',
      logName: function() {
      console.log(this.name)
      }
      }
      const bar = {
      name: 'mike'
      }
      foo.logName.call(bar)// mike
    • ⼀般使用 new 方法调用构造函数时,构造函数内的 this 会被绑定到新创建的对象上

      1
      2
      3
      4
      5
      function Foo() {
      this.bar = "Tim"
      }
      const instance = new Foo()
      console.log(instance.bar)// Tim
    • 箭头函数不适用上面的规则,而是根据外层(函数或者全局)上下文来决定 this 的指向,始终指向外部对象,因为箭头函数没有this,因此它自身不能进行new实例化,同时也不能使用call, apply, bind等方法来改变this的指向

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      // 匿名类似上面的例子2
      var foo = {
      fn: function(){
      (function() {
      console.log(this)
      })()// 匿名函数直接执行,因此是window
      }
      }
      console.log(foo.fn())// window
      // 取决于外层上下文,箭头函数位于foo内,那么this指向foo
      var foo = {
      fn: function(){
      (() => {
      console.log(this)
      })()// 箭头函数立即执行
      }
      }
      console.log(foo.fn())// {fn:f}

      注意

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      function foo() {
      return () => {
      console.log(this.a)
      };
      }
      var obj1 = {
      a: 1
      }
      var obj2 = {
      a: 2
      }
      var bar = foo.call(obj1)
      console.log(bar.call(obj2))// 1 undefined

foo.call(obj1) 使得使得 foo 中的 this 指向 obj1【因此箭头函数的 this 指向 obj1】,并立即执行 foo,因此 foo.call(obj1) 会返回一个箭头函数即 a => {console.log(this.a)},并保存在 bar 中,而箭头函数不能直接对其修改 this 指向,因此 bar.call(obj2) 执行时,this 仍然是 指向 obj1。另外 call 不返回函数,因此 console.log(bar.call(obj2)) 输出 undefind

ref

  1. 作用域、作用域链

  2. 学习 Javascript 闭包 (Closure)

  3. JS中this关键字详解

  4. JavaScript中 with的用法

  5. 彻底弄懂bind,apply,call三者的区别

  6. JavaScript 中 call()、apply()、bind() 的用法

2.4. DOM BOM

2.4.1. XHTML/XML 与 DOM 树

2.4.1.1. XHTML/XML

  1. HTML 语法要求比较松散,这样对网页编写者来说,比较方便,但对于机器来说,语言的语法越松散,处理起来就越困难,对 于传统的电脑来说,还有能力兼容松散语法,但对于许多其他设备,比如手机,难度就比较大。因此产生了由 DTD 定义规则,语法要求更加严格的 XHTML。
  2. 最大的变化在于所有标签必须闭合,也就是说开始标签要有相应的结束标签。另外,XHTML 中所有的标签必须小写。在 XHTML 中,所有的参数值,包括数字,必须用双引号括起来

2.4.1.2. DOM

  1. 当一个网页被加载时,浏览器会创建一个页面的文档对象模型(Document Object Model,DOM)

    HTML DOM模型被构造成一个对象树

  2. 在应用程序中,基于 DOM 的 XML/HTML 分析器将一个 XML/HTML 文档转换成一个对象模型的集合 ( 通常称 DOM 树 ),应用程序正是通过对这个对象模型的操作,来实现对 XML/HTML 文档数据的操作

  3. XML DOM 定义了所有 XML 元素的对象和属性,以及访问它们的方法。

  4. HTML DOM 定义了所有 HTML 元素的对象和属性,以及访问它们的方法。

  5. HTML DOM 是关于如何获取、修改、添加或删除 HTML 元素以及处理和新建 HTML 事件的标准。

  1. DOM编程接口

    • HTML DOM可以使用JavaScript

    • 所有 HTML 元素被定义为对象

    • 编程接口是每个对象的属性和方法

      • 属性是可以获取或设置的值(如更改HTML元素的内容)。

        使用 objectName.attributeName 访问/修改 DOM 对象的属性

      • 方法是可以执行的操作(如添加删除HTML元素)。

  2. 找元素

    • by id
      document.getElementById("intro");
    • by tag name
      document.getElementsByTagName("p");
    • by class name
      document.getElementsByClassName("intro");
    • by CSS selectors
      document.querySelectorAll("p.intro");
    • by HTML object collections
      document.forms["frm1"];
  3. DOM 树节点类型

    1. 每个节点都有 nodeType,nodeName,nodeValue

    2. nodeType: Element、Text、Attr(属性节点)、Comment(注释节点)、Document(文档节点)

    3. image-20230222200728788

      DOM 树就是:

      image-20230222200950221

2.4.2. DOM0,DOM2 事件流 ( 捕获、目标和冒泡 )

2.4.2.1. DOM0

  1. 将一个函数赋值给一个事件处理属性。为所有浏览器所支持。

    1. 优点:简单高效,移除事件非常简单只要 element.onclick=null即可但
    2. 缺点:多次赋值会覆盖之前的回调函数,如 onclick=f;onclick=g,因此一个事件处理程序只能对应一个处理函数。
  2. onxxxonclickDOM0 级别的事件

1
2
3
4
5
6
var btn = document.getElementById("btn");
btn.onclick = function(){
alert(this.id);
}
// 取消绑定
btn.onclick = null;

2.4.2.2. DOM2

  1. DOM2 事件引进了一种全新的绑定事件方法,添加了一些新的事件。现在的浏览器都支持这种绑定方式,也建议使用这种绑定方式。

  2. addEventListener添加的事件处理程序,并通过removeEventListener来删除。

1
2
3
4
5
6
var btn = document.getElementById("btn");
var hander = function(){
}
// 参数:事件处理属性名称、处理函数、是否在捕获时执行事件处理函数
addEventListener("click",handler,false/true);
removeEventListener("click",handler,false/true);
  1. DOM2 级的事件规定事件流包含三个阶段 ref:JS中的事件冒泡、事件捕获、事件委托 推荐阅读

    当一个 HTML 元素产生一个事件时,该事件会在元素节点与根结点之间的路径传播,路径所经过的结点都会收到该事件,这个传播过程可称为 DOM 事件流

    1. 捕获阶段:事件从Document节点自上而下向目标节点传播的阶段。

    2. 目标阶段:找到了被触发事件的元素对象,触发事件函数

    3. 冒泡阶段:从被触发事件的元素对象向上冒泡传递事件*(注意这里传递的仅仅是事件,而不是绑定的事件函数)*

  2. 事件处理过程

    1. document 首先接收到 click 事件,然后顺着 DOM 树逐级向下传递事件,如果在途中经过的节点定义了相同事件的处理函数且 addEventListener 第 3 个参数设定为 true【即在事件捕获阶段处理调用处理函数】,那么会调用这个节点的处理函数

    2. 事件最终传递到目标节点,调用处理函数

    3. 事件逐级向上传播回 document。同捕获阶段,但是第 3 个参数要设置为 false,默认 false

      有些时候我们不希望产生事件冒泡,所以可以在子事件中加入 e.stopPropagation() 取消冒泡

      image.png

    4. 事件委托

      1. 就是利用事件冒泡,把子元素的事件都绑定到父元素上。如果子元素阻止了事件冒泡,那么委托就无法实现。

      2. 比如给 1000 个按钮注册点击事件,可以采用给这个 1000 个按钮的父节点添加点击元素,并利用事件的 target 获取按钮的相关信息。

        image.png

        image.png

2.4.3. 观察者模式

  1. 察者模式定义了一种一对多的依赖关系,让多个观察者 Observer 对象同时监听某一个主题 Subject 对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。它主要用于实现分布式事件处理系统。

2.4.4. BOM

ref: 浏览器对象模型(BOM)是什么?推荐阅读

浏览器对象模型(Browser Object Model,简称 BOM)是 JavaScript 的组成部分之一,BOM 赋予了 JavaScript 程序与浏览器交互的能力

能利用BOM做什么?

  • BOM提供了一些访问窗口对象的一些方法,我们可以用它来移动窗口位置改变窗口大小打开新窗口和关闭窗口弹出对话框,进行导航以及获取客户的一些信息如:浏览器品牌版本,屏幕分辨率。但BOM最强大的功能是它提供了一个访问HTML页面的一入口——document对象,以使得我们可以通过这个入口来使用DOM的强大功能!

DOM对象和BOM对象的关系?

  • DOM对象是BOM对象的大儿子。所以DOM对象的那些操作都是浏览器来执行的

BOM中的顶级对象是什么,代表什么意思?

  • BOM中的顶级对象是window,代表的是浏览器打开的一整个窗口

每个浏览器的 Javascript 程序都可以引用以下全局对象:document、history、location、navigator、screen、window

img

document

  • 每个载入浏览器的 HTML 文档都会成为 Document 对象

  • Document 对象是 HTML 文档的根节点

window

  • 所有浏览器都支持window对象。

  • 它表示浏览器的窗口所有JavaScript全局对象、函数和变量都自动成为窗口对象的成员。window 也是全局对象,可以直接使用

location

  • Location 对象包含有关当前 URL 的信息

navigator

  • navigator 对象包含有关浏览器的信息

  • 来自navigator对象的信息通常会产生误导,不应该用于检测浏览器版本:因为所有者可以任意更改

screen

  • screen对象包含有关客户端显示屏幕的信息

history

  • history对象包含用(在浏览器窗口中)访问过的 URL

不考——2.5. Ajax

2.5.1. RIA Rich Internet Applications 富互联网应用

  1. 是一种具有近似于传统桌面应用软件系统功能和特性的网络应用系统。

  2. RIA 系统最大的特点是将大部分处理任务都从用户界面端移植到客户端,仅保留一些必要数据与服务器端进行信息交互。

  3. RIA 系统的特性:

    1. 运行于浏览器中,不需要额外安装支持软件
    2. 在本地运行时,受安全沙箱全程保护。
  4. 优点

    1. 无需安装
    2. 容易升级
    3. 可以通过 Internet/intranet 轻易获得
    4. 更加丰富的用户界面
    5. 响应速度更快的用户界面
    6. 客户端/服务端 负载平衡
    7. 异步通讯
    8. 网络效率
  5. 缺点

    1. 搜索引擎不可见
    2. 专有 ( 与开放标准相反 )
    3. 完整性丧失 (RIA 通常无法与 HTML 很好地融合在一起 )
    4. 软件开发的复杂性 ( 什么东西要被缓存或不缓存再客户端计算机中?)
    5. RIA 体系结构打破了网页范例
    6. 受限于安全沙箱
  6. 实现方式

    1. 浏览器插件
      • Flash/Flex, Java Swing, Silverlight
      • 潜在的更强的交互性,更⾼的应用障碍
      • 关注开放/控制
    2. 在浏览器中,不需要插件
      • AJAX
      • 更低的采用门槛
      • 跨浏览器问题?

2.5.2. 同步、异步通信

2.5.2.1. 同步

  1. 同步请求/响应通信模型中,总是浏览器 ( 与 Web 服务器、应用服务器或 Web 应用程序相对 ) 发起请求 ( 通过 Web 用户 )。接着,Web 服务器、应用服务器或 Web 应用程序响应进入的请求。在处理同步请求/响应对期间,用户不能继续使用浏览器。

  2. 基本上所有新数据都需要刷新页面

  3. image-20230223160754341

2.5.2.2. 异步

  1. Web 用户在当前异步请求被处理时还可以继续使用浏览器。一旦异步请求处理完成,异步响应就被通信 ( 从 Web 服务器、应用服务器或 Web 应用程序 ) 回客户机页面。典型情况下,在这个过程中,调用对 Web 用户没有影响;他们不需要等候响应。

  2. 交换数据并修改页面但是不需要刷新页面

  3. image-20230223160809598

2.5.3. Ajax 请求

Asynchronous JavaScript And XML 是⼀种使用 XMLHttpRequest 技术构建更复杂,动态的网页的编程实践。

尽管 X 在 Ajax 中代表 XML,但由于JSON的许多优势,比如更加轻量以及作为 Javascript 的⼀部分,目前 JSON 的使用比 XML 更加普遍。JSON 和 XML 都被用于在 Ajax 模型中打包信息

  1. 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

  2. 传统的网页 ( 不使用 AJAX) 如果需要更新内容,必需重载整个网页面。

2.5.4. Ajax 优缺点

  1. 优点

    1. 更好的交互性和响应能力,使用起来更让人愉快。
    2. 由于部分渲染,减少了与 Web 服务器的连接。
    3. 因为只加载需要更新页面的数据,而不是刷新整个页面,所以可以节省带宽,减少网络流量。
  2. 缺点

    1. 返回和刷新按钮变得无用。
    2. 为此页面添加书签将变得无用。
    3. 需要在 Web 浏览器上启用 JavaScript。
    4. 网络延迟可能会破坏可用性。
    5. 通过 AJAX 加载的数据不会被任何主要的搜索引擎索引。因此,使 SEO 不友好。违背 URL 和资源定位的初衷

2.5.5. XMLHttpRequest

  • XMLHttpRequest 对象是 AJAX 最重要的组件

  • 用于使用 HTTP 在 Web 服务器之间传输和操作 XML/JSON/文本数据

  • 执行操作:

    • 在后台从客户端发送数据
    • 从服务器接收数据
    • 更新网页,无需重新加载

2.5.6. Ajax请求流程

  • 客户端事件发生,如按钮点击

  • 创建 XHMHttpResquest 对象

    1
    2
    xmlhttp = new XMLHttpRequest();
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");//老版本IE
  • 创建 XMLHttpRequest 对象后,需要决定在收到服务器对请求的响应后要做什么。

    设置 XHMHttpResquest 回调函数

    1
    2
    3
    xmlhttp.onreadystatechange = function(){
    //process the server response
    };
  • XHMHttpResquest 发送异步请求给服务器端,需要调用 XMLHttpRequest 对象的 open() 和 send() 方法

    open() 方法的参数:

    • 第⼀个参数是 HTTP 请求方法,例如 GET、POST 和 HEAD。

    • 第⼆个参数是请求的 Web 页面的 URL。

    • 第三个参数(可选)设置请求是否是异步的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //HTTP GET request without querystring
    xmlhttp.open(‘GET’,’serverpage.php’,true);
    xmlhttp.send(null);
    //HTTP GET request with querystring
    xmlhttp.open(‘GET’,’serverpage.php?
    username=’+Math.random(),true);
    xmlhttp.send(null);

    xmlhttp.open(‘GET’,’serverpage.php?
    username=user1&pass=password’,true);
    xmlhttp.send(null);
    //HTTP POST request
    xmlhttp.open(‘POST’,’serverpage.php’,true);
    xmlhttp.send(‘username=user1&pass=password’);
  • 服务器端发送结果

  • XHMHttpResques t传送结果给客户端:

    首先,响应函数需要检查请求的就绪状态。如果就绪状态的值为 4,则可以进⼀步执行。

    接下来,需要检查HTTP服务器响应的响应代码。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    xmlhttp.onreadystatechange = function(){
    if (xmlhttp.readyState === 4) {
    // everything is good, the response is received
    }if (xmlhttp.status === 200) {
    // process the response
    }else {
    // request encountered some problem,
    // for example, the response may contain a HTTP
    404 (Not Found) response code
    } else {
    // still not ready
    }
    };

2.5.7. 安全相关,SOP,跨域

2.5.7.1. 安全相关

XSS 威胁

  1. 跨站脚本 (Cross site scripting,通常简称为 XSS) 是一种网站应用程序的安全漏洞攻击,是代码注入的一种。 它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。指攻击者在网页中嵌入客户端脚本 ( 例如 JavaScript),当用户浏览此网页时,脚本就会在用户的浏览器上执行,从而达到攻击者的目的.这类攻击通常包含了 HTML 以及用户端脚本语言。

  2. AJAX 无法从本地存储的网页上运行,只能在存储在 Web 服务器上的网页上运行

2.5.7.2. SOP

  1. 同源政策:限制浏览器可以获取的资源,只能从同源网站获取内容 ( 除了资源文件 ) 同源政策规定,AJAX 请求只能发给同源的网址,否则就报错。"同源政策"越来越严格。目前,如果非同源,共有三种行为受到限制。

    1. Cookie、LocalStorage 和 IndexDB 无法读取。
    2. DOM 无法获得。
    3. AJAX 请求不能发送。

2.5.7.3. 跨域问题

  1. 协议、域名、端口号中任意一个不同时,都算作不同域

  2. 实现跨域的方法

    1. CORS:服务器设置 HTTP 响应头中 Access-Control-Allow-Origin 值,解除跨域限制。
    2. nginx:反向代理
    3. Docker

2.5.6. 数据格式

2.5.6.1. JSON

  1. 由 Douglas Crockford 形式化和推广,它是一种轻量级的、易于简化的数据格式,使用 JavaScript 对象和数组文本语法编写。

2.5.6.2. JSON-P JSON with Padding

  1. 带填充的 JSON

  2. 当使用动态脚本标记插入时,JSON 数据被视为另一个 JavaScript 文件,并作为本机代码执行。为了实现这一点,数据必须包装在回调函数中。

  3. 由于数据被当作原生 JS,因此它以原生 JavaScript 的速度被解析

  4. 避免使用与性能无关的 JSON-P 有一个原因:由于 JSON-P 必须是可执行的 JavaScript,因此任何人都可以调用它,并使用动态脚本标记插入将其包含在任何网站中。

  5. 不要在 JSON-P 中对任何敏感数据进行编码,因为您无法确保它保持私有,即使使用随机 url 或 cookie。

3. 服务器端

3.1. Node.js 重要

  1. Node.js 不是⼀个web框架,也不是⼀种语言,而是一个运行时环境(类比 JVM)

  2. Node.js 使用事件驱动非阻塞异步 I/O 模型,在单⼀进程中可以处理成千上万的并发连接,非常适合处理高并发。Node所针对的应用程序有⼀个专门的简称:DIRT,表示数据密集型实时(data-intensive real-time)程序【但都对 cpu 使用少】

3.1.1. 特点,应用场景

3.1.1.1. 优缺点/适用不适用场景

  1. 优点:

    1. 高并发(最重要的优点)
    2. 适合I/O密集型应用
    3. 同样是 js 客户端和服务端切换成本低
    4. npm 丰富
    5. 可移植到不同平台
  2. 缺点:

    1. 不适合CPU密集型应用;CPU密集型应用给Node带来的挑战主要是:由于JavaScript 单线程的原因,如果有长时间运行的计算(比如大循环),将会导致CPU时间片不能释放,使得后续I/O无法发起
    2. 大内存的应用:由于 V8 引擎有内存设计的限制,32 位环境中最大堆是 1G,64 位环境中最大堆也不到 2G
    3. 静态服务器,和 Nginx 的处理静态资源还是有很大的差距
    4. 不需要异步的应用,Nodejs 的异步调用可能会给编程带来⼀些麻烦

3.1.1.2. 应用场景

  1. 网站

  2. 聊天应用程序是最能体现 Node.js 优点的例子

  3. HTTP 代理

  4. 前端构建工具 ( 脚手架 )

  5. 写操作系统 (NodeOS)

  6. 跨平台打包工具

3.1.2. 基本原理

ref:深入理解Nodejs单线程实现高并发原理

nodejs运行环境 = 主线程(单线程,包括事件队列) + 线程池(工作线程池,执行其他工作-多线程)

  1. 运行机制

    • V8 引擎解析 JavaScript 脚本。
    • 解析后的代码,调用 Node API。
    • libuv 库负责Node API 的执行。它将不同的任务分配给不同的 worker 线程,形成一个 Event Loop(事件循环),以异步的方式将任务的执行结果返回给V8引擎。
    • V8 引擎再将结果返回给用户。
    • img
    • 具体执行:事件机制都是用设计模式中观察者模式实现。
      • 维护了一个事件队列(Event queue),事件到来就加入事件队列。主线程从事件队列中取出事件,再从线程池中分配一个线程去执行这个事件,当有事件执行完毕后,会通知主线程,主线程把要执行回调的事件也加入事件队列,后续再执行,线程归还给线程池。
      • 异步操作是由线程池完成的,node 将所有的阻塞操作都交给了内部的线程池去实现,本身只负责不断的往返调度,并没有进行真正的I/O操作,从而实现异步非阻塞 I/O
  2. 4 个层次

    • 应用层: 即 JavaScript 交互层,常见的就是 Node.js 的模块,比如 http,fs
    • V8 引擎层: 即利用 V8 引擎来解析JavaScript 语法,进而和下层 API 交互
    • NodeAPI 层: 为上层模块提供系统调用,一般是由 C 语言来实现,和操作系统进行交互 。
    • LIBUV 层: 是跨平台的底层封装,实现了 事件循环、文件操作等,是 Node.js 实现异步的核心
  3. 单线程

    1. Node 遵循的是单线程单进程的模式,node 的单线程是指js的引擎只有一个实例,且在 nodejs 的主线程中执行,同时 node 以事件驱动的方式处理 IO 等异步操作。node的单线程模式,只维持一个主线程,大大减少了线程间切换的开销,但是会有多个 worker 线程,用于执行异步操作

    2. 但是 node 的单线程使得在主线程不能进行CPU密集型操作,否则会阻塞主线程

  4. 异步 I/O

  1. 事件循环驱动

  1. 网上解释

    1. Node.js:单线程,异步 I/O,事件驱动
    2. 应用程序的请求过程可以分为俩个部分:CPU 运算和 I/O 读写
      1. CPU 计算速度通常远高于磁盘读写速度,这就导致 CPU 运算已经完成,但是不得不等待磁盘 I/O 任务完成之后再继续接下来的业务。
      2. 所以 I/O 才是应用程序的瓶颈所在,在 I/O 密集型业务中,假设请求需要 100ms 来完成,其中 99ms 花在 I/O 上。
    3. 如果需要优化应用程序,让他能同时处理更多的请求,我们会采用多线程,同时开启 100 个、1000 个线程来提高我们请求处理,当然这也是一种可观的方案。但是由于一个 CPU 核心在一个时刻只能做一件事情,操作系统只能通过将 CPU 切分为时间片的方法,让线程可以较为均匀的使用 CPU 资源。
    4. 操作系统在内核切换线程的同时也要切换线程的上下文,当线程数量过多时,时间将会被消耗在上下文切换中。所以在大并发时,多线程结构还是无法做到强大的伸缩性。那么是否可以另辟蹊径呢?!
    5. 我们先来看看单线程,《深入浅出 Node》一书提到"单线程的最大好处,是不用像多线程编程那样处处在意状态的同步问题,这里没有死锁的存在,也没有线程上下文切换所带来的性能上的开销",那么一个线程一次只能处理一个请求岂不是无稽之谈,先让我们看张图:

  1. Node.js 的单线程并不是真正的单线程,只是开启了单个线程进行业务处理 (cpu 的运算 ),同时开启了其他线程专门处理 I/O。当一个指令到达主线程,主线程发现有 I/O 之后,直接把这个事件传给 I/O 线程,不会等待 I/O 结束后,再去处理下面的业务,而是拿到一个状态后立即往下走,这就是"单线程"、“异步 I/O”。

  2. I/O 操作完之后呢?Node.js 的 I/O 处理完之后会有一个回调事件,这个事件会放在一个事件处理队列里头,在进程启动时 node 会创建一个类似于 While(true) 的循环,它的每一次轮询都会去查看是否有事件需要处理,是否有事件关联的回调函数需要处理,如果有就处理,然后加入下一个轮询,如果没有就退出进程,这就是所谓的"事件驱动"。这也从 Node 的角度解释了什么是"事件驱动"。在 node.js 中,事件主要来源于网络请求,文件 I/O 等,根据事件的不同对观察者进行了分类,有文件 I/O 观察者,网络 I/O 观察者。事件驱动是一个典型的生产者/消费者模型,请求到达观察者那里,事件循环从观察者进行消费,主线程就可以马不停蹄的只关注业务不用再去进行 I/O 等待。

3.2. 模块

两种模块规范

  1. ES6 模块,简称 ESM Node.js

  2. CommonJS 模块,简称 CJS

  3. CommonJS 模块是 Node.js 专用的,与 ES6 模块不兼容。而ES6模块化在浏览器和node.js中都可以用。

3.2.1. 差异

  1. 语法

    • CommonJS 模块使用 require() 加载和 module.exports 输出
    • ES6 模块使用 importexport
  2. 机制

    • 输出:CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用

    • 加载:CommonJS 模块是同步加载,ES6 模块是静态解析

      • 原因:CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成
    • // 例子
      // CJS
      // lib.js
      var counter = 3;
      function incCounter() {
       counter++;
      }
      module.exports = {
       counter: counter,
       incCounter: incCounter,
      };
      // main.js
      var mod = require('./lib');
      console.log(mod.counter); // 3
      mod.incCounter();
      console.log(mod.counter); // 3,值没有变化,因为是拷贝
      
      // ES6
      // lib.mjs
      export let counter = 3;
      export function incCounter() {
       counter++;
      }
      // main.mjs
      import { counter, incCounter } from ‘./lib.mjs’;
      console.log(counter); // 3
      incCounter();
      console.log(counter); // 4,增加,因为是值的引用
      

3.2.2. 循环加载

“循环加载”(circular dependency)指的是,a脚本的执行依赖b脚本,而b脚本的执行又依赖a脚本。

对于 JavaScript 语言来说,目前最常见的两种模块格式 CommonJS 和 ES6,处理“循环加载”的方法是不一样的,返回的结果也不一样。

  • CommonJS 模块遇到循环加载时,返回的是当前已经执行的部分的值,而不是代码全部执行后的值,两者可能会有差异

  • ES6 模块是动态引用,如果使用import从一个模块加载变量(即import foo from 'foo'),那些变量不会被缓存,而是成为一个指向被加载模块的引用,需要开发者自己保证,真正取值的时候能够取到值

  • 详细解释见:[24. Module 的加载实现 - 循环加载 - 《阮一峰 ECMAScript 6 (ES6) 标准入门教程 第三版》 - 书栈网 · BookStack](https://www.bookstack.cn/read/es6-3rd/spilt.4.docs-module-loader.md#:~:text=ES6 模块的循环加载 ES6 处理“循环加载”与 CommonJS 有本质的不同。 ES6,模块是动态引用,如果使用 import 从一个模块加载变量(即 import foo from ‘foo’ ),那些变量不会被缓存,而是成为一个指向被加载模块的引用,需要开发者自己保证,真正取值的时候能够取到值。)

4. 优化 重要

4.1. 基准测试/性能分析

  1. 通过设计科学的测试方法、测试工具和测试系统,实现对一类测试对象的某项性能指标进行定量和可对比的测试

  2. 延迟(传播、传输、处理、排队) 和带宽

  3. Web 性能要点

    1. 延迟和带宽对 Web 性能的影响
    2. 传输协议 (TCP) 对 HTTP 的限制
    3. HTTP 协议自身的功能和缺陷
    4. Web 应用发展趋势及性能需求
    5. 浏览器局限性和优化思路
  4. 浏览器渲染过程:渲染页面:浏览器的工作原理 - Web 性能 | MDN (mozilla.org)

  5. 性能监控指标

    1. FP:First Paint 首次绘制,页面第一次绘制的时间点:只要出现视觉变化,无论什么
    2. FCP:First Contentful Paint 首次内容绘制,完成对 DOM 中的一部分内容渲染的时间点:首次绘制来自 DOM 的内容。
      • 注意:只有首次绘制文本、图片(包含背景图)、非白色的 canvas 或 SVG 时才被算作 FCP
      • FP和FCP可能是相同的时间,也可能是先FP后FCP
    3. FMP:First Meaningful Paint 首次有意义绘制,页面关键元素的渲染时间,没有标准定义,由开发者自行定义
    4. 首屏时间:应用渲染完整个屏幕的时间
    5. 用户可交互时间: Time to Interactive DOMReady 时间,即可以进行交互的时间点,如果涉及交互的 JS 没有加载好,那么就不能交互
    6. 总下载时间:页面所有资源加载完成的时间,一般统计 window.onload 时间,也可以是异步渲染全部完成的时间。
    7. 第一个字节加载时间
    8. 页面渲染时间:瀑布流中两个指标 Start Render 和 msFirstPaint
      1. Start Render:通过捕获页面加载的视频,实验室测量。
      2. msFirstPaint:是浏览器本身报告的测量。
    9. 自定义指标
  6. 相关工具

image-20230223174846570

4.2. 基本原理

  1. 浏览器核心优化策略

    1. 资源预取和排定优先次序:声明每种资源的优先级
    2. 推测性优化:
      1. DNS 预解析:对可能的域名进行提前解析。
      2. TCP 预连接:DNS 解析之后,浏览器可以根据预测的 HTTP 请求,推测性地打开 TCP 连接。
      3. 页面预渲染:某些浏览器可以让我们提示下⼀个可能的目标,从而在隐藏的标签页中预先渲染整个页面。
  2. web 性能优化两个准则

    1. 消除或减少不必要的网络延迟
    2. 将需要传输的数据压缩至最少

4.3. 优化思路,技术,方法

4.3.1. 优化思路

  1. 减少 DNS 查找

  2. 重用 TCP 连接

  3. 减少 HTTP 重定向

  4. 使用内容分发网络

  5. 避免不必要的资源请求

  6. 在客户端缓存部分资源

  7. 资源传输前先压缩

  8. 避免不必要的请求字节

  9. 并行处理请求和响应

  10. 针对协议版本采取优化措施

4.3.2. 具体的优化方法

  1. CSS:CSS 放置在 HTML 顶部,减少 CSS 文件,避免绝对 CSS。

  2. Image:合适的图片大小,而不是浏览器调整

  3. js:将 js 放在 html 的底部,尽量用外部 js

  4. 服务器优化:减少域名查找,数据压缩

  5. html:标准兼容、去除空白符、结构尽量简单、做到浏览器和移动端的兼容

  6. 针对 HTTP1.x 的优化

    1. 利用 http 管道
    2. 域名分片:将资源分散到多个来源
    3. 打包资源以减少 HTTP 请求
    4. 父文档中嵌入小资源:从而减少请求数量
  7. HTTP2 优化

    1. 少发数据,减少请求,减少传输数据量和不必要网络延迟,调整资源供给
    2. 每个来源一个链接 ( 多个链接会抵消新协议中首部压缩和请求优先级的作用,域名分区在 HTTP2 下是反作用的 )
    3. 去掉不必要资源打包 (资源打包不利于缓存,单个文件比较大 )
    4. 利用服务器推送 ( 充分使用缓存的机制,即还没有收到浏览器的请求,服务器就把各种资源推送给浏览器;比如,浏览器只请求了index.html,但是服务器把index.htmlstyle.cssexample.png全部发送给浏览器。这样的话,只需要一轮 HTTP 通信,浏览器就得到了全部资源,提高了性能。 )

5. 前端鉴权

5.1. 术语

  • 认证(Identification): 是指根据声明者所特有的识别信息确认声明者的身份。如用户名密码,身份证

  • 授权(Authorization): 在信息安全领域是指资源所有者委派执行者,赋予执行者指定范围的资源操作权限,以便对资源的相关操作。如 session,cookie,token

  • 鉴权(Authentication):在信息安全领域是指对于⼀个声明者所声明的身份权利,对其所声明的真实性进行鉴别确认的过程。如确认 token 是否合法、是否到期

    • 鉴权是⼀个承上启下的⼀个环节,上游它接受授权的输出,校验其真实性后,然后获取权限(permission),这个将会为下⼀步的权限控制做好准备。
  • 权限控制(Access/Permission Control):将可执行的操作定义为权限列表,然后判断操作是否允许/禁止。如通过 web 后端服务,来控制接口访问,允许或拒绝访问请求

    image-20230223192856091

5.2 方案

一文教你搞定所有前端鉴权与后端鉴权方案

6. 登录注册

7. 前端主题切换

前端主题切换方案

方案/主题样式
方案1:link标签动态引入(js 修改引入 css 的 link 标签;文件过大,切换延时,不推荐,但首屏时间短)
方案2:提前引入所有主题样式,做类名切换(要为变换主题的每个内容写 css)
方案3:CSS变量+类名切换(使用 css 变量,要用到的地方使用 var(–color)即可,不用给每个内容都写 css)【建议】
方案4:Vue3新特性(v-bind)
方案5:SCSS + mixin + 类名切换
方案6:CSS变量+动态setProperty

6. 题型

6.1. 基本概念 ( 所有课件中涉及的,不限于总结 )

6.2. 简答题

6.3. 问答题

7. 2023 web回忆

7.1. 基本概念

  • URN

  • CSSOM

  • SVG

  • CANVAS

  • render tree

  • WebAssembly

7.2. 简答题

  • web3.0 特点

  • 箭头函数和普通函数的区别

  • NodeJs高并发原因

  • js 数据类型

  • 前端智能的理解,前端智能的典型应用

  • 闭包的定义,优缺点,应用场景

  • 状态码含义:200、301、303,404,500

7.3. 问答题

  • 列举前端流行框架,什么是 Vanilla JS,为什么要推广 Vanilla JS

  • http1——http3的发展,各自特点,http3 解决了前面什么问题

  • 前端鉴权 4 种方式,优缺点(20 分)

  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
  • Copyrights © 2022-2024 zzb
  • RZ
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信