Skip to content

【2023】青训营 - 前端练习题汇总解析

汇总了青训营官方账号每天发布的练习题,并且给出了答案、做了简单解析与知识扩充,有不足之处欢迎一起交流学习。

每天的选择题不同,而编程题是一样的,直接去Leetcode刷题即可。

选择题

DAY 1

题目描述

选择题 1:  
下列哪些是 HTML5 的新特性?  
A. 语义标签  
B. Canvas 绘图  
C. <audio>元素  
D. 增强型表单  
  
选择题 2:  
下面可以继承的属性有哪些?  
A. font-size  
B. background  
C. color  
D. cursor

答案与解析

1. ABCD
2. ACD

HTML5新增内容

  • 语义化标签
    • header nav section article aside footer
    • 使用语义化标签有利于SEO与无障碍
  • <video><audio>标签
    • 支持引入外部视频/音频资源
    • 可以搭配<source>标签实现fallback
  • <canvas>画布
  • <input> <form>元素属性扩展
    • type属性支持了更多的值 内置了更多的样式
  • 全局新增属性data-*
    • 在JavaScript中可以通过DOM元素引用的.dataset直接获取到元素上的data-*属性的值
    • Vue的Scoped Style,Github的贡献墙颜色都是基于[data-*]选择器

CSS属性可继承性

常见的CSS属性都支持继承,不必特别记忆

  • 如果一个属性具备继承性,那么在该元素上设置后,它的后代元素都可以继承这个属性
  • 如果后代元素自己设置有该属性,则会优先使用自己的属性
  • 需要注意的是:子元素从父元素继承来的font-size: 2em;继承的是计算值,而不是原始值
  • 如果父元素设置了font-size: 2em;,此时子元素再设置font-size: 2em;达到的效果实际上是在父元素的基础上的2em,实质上是font-size: 4em;

强制继承

如果某些属性不具备可继承性,我们希望子元素能够继承,则可以使用强制继承:

css
.father {
  border: 2px soild red;
}
.child {
  border: inherit;
}

DAY 2

题目描述

选择题 1:  
对于一条100M的宽带,理论下载速度上限是多少?  
A. 12.5MB/s  
B. 100MB/s  
C. 10MB/s  
D. 10Mb/s  
  
选择题 2:  
关于 for of 和 for in 的描述,正确的是?  
A. for in 可以循环普通对象  
B. for of 可以循环普通对象
C. 都不可以循环数组
D. 都可以循环数组

答案与解析

1. A
2. AD

字节与比特

运营商的100M指的是100Mb,单位是bit,而日常使用中的网速单位是Byte

换算公式是1Byte = 8bit,故100 / 8 = 12.5MB/s

for-in与for-of

  • for-in可以遍历数组与对象 得到的是索引/key
  • for-of可以遍历数组但不能遍历对象 遍历数组得到的是值
js
  const arr = ['abc', 'cba', 'nba']
  const obj = {
    name: 'Ziu',
    age: 18
  }

  // for-in可以遍历数组
  for (const i in arr) {
    console.log(i) // 0 1 2
  }

  // for-of可以遍历数组
  for (const i of arr) {
    console.log(i) // abc cba nba
  }

  // for-in可以遍历对象的key值
  for (const i in obj) {
    console.log(i) // name age
  }

  // for-of不能遍历对象 会报错
  for (const i of obj) {
    console.log(i) // Error
  }

DAY 3

题目描述

选择题 1:  
关于事件冒泡描述正确的是?  
A. 从目标元素向 document 冒泡  
B. 从 document 向目标元素冒泡  
C. 从 document 向目标元素冒泡,再从目标元素向 document 冒泡  
D. 以上都不是  
  
选择题 2:  
以下哪些 script 标签属性会使脚本有可能在 DOMContentLoaded 事件之后加载?  
A. <script async>  
B. <script defer>  
C. <script type="module">  
D. <script type="module" async>

答案与解析

1. A
2. AD

冒泡与捕获

事件冒泡:浏览器从触发事件的目标元素开始向上检查其祖先元素是否注册了此事件的监听器,如果其祖先元素注册了此事件监听回调,则触发回调。此操作会层层向上,直到<html>元素

一文读懂事件冒泡与事件捕获

script的defer async属性

  • defer 延迟加载
    • 不会阻塞DOM Tree的构建过程
    • 下载完成后 总会等待DOM Tree构建完成后执行
    • 一定在DOMContentLoaded事件之前触发
  • async 异步加载
    • 不保证执行顺序 独立下载、独立运行
    • 只要下载完成就立即执行 不保证在DOMContentLoaded之前或之后被执行

被标记为type="module"<script>会被浏览器识别为ES6 Module,当浏览器解析到此<script>时将异步下载此脚本,不会造成堵塞浏览器,其本质上与defer是一致的:

html
<script type="module" src="./foo.js"></script>
<!-- 等同于 -->
<script type="module" src="./foo.js" defer></script>

当然,如果额外添加了async标记,此脚本将在被下载完成后中断渲染,立即执行

Module 的加载实现

DAY 4

题目描述

选择题 1:  
以下哪些是 CSS 块级元素的特性?  
A. 宽度默认由其中的内容决定  
B. 高度默认由其中的内容决定  
C. 可以被分拆到多行  
D. 可以通过 height 属性指定高度  
  
选择题 2:  
以下关于跨域说法错误的是?  
A. http://example.com和https://example.com是相同的域名,属于同源  
B. 跨域资源共享规范中规定了除了 GET 之外的 HTTP 请求,或者搭配某些 MINE 类型的 POST 请求,浏览器都需要先发一个 OPTIONS 请求。  
C. CSS 中通过 @font-face 使用字体也会有跨域问题  
D. Cookie,LocalStorage 和 IndexedDB 都会受到同源策略的限制

答案与解析

1. BD
2. A

块级元素、行内级元素、行内块级元素

块级元素在BFC中布局,行内级元素在IFC中布局,二者具有不同的特性:

常见的块级(block)元素:div h1 p

  • 每个块级元素都是独自占一行
  • 元素的宽度如果不设置的话,默认为父元素的宽度(父元素宽度100%)
  • 高度、行高、外边距(margin)以及内边距(padding)都可以控制
  • 多个块状元素从上至下排列

常见的行内级(inline-level)元素:a span

  • 不能设置宽高,默认宽度就是它本身内容的宽度,不独占一行
  • 高度、行高、外边距以及内边距都可以控制
  • 但是之间会有空白缝隙,设置它上一级的 font-size: 0; 才能消除间隙

常见的行内块级(inline-block)元素:img button input

  • 同时具有块级与行内级元素的特性
  • 可以设置宽高,其默认宽高由其内容决定

跨域资源共享 CORS

CORS是常用的跨域解决办法之一,下面简单列出纲要,详细解析请见 跨域资源共享(CORS)

  • 什么是CORS?可以解决哪些场景下的跨域问题?
  • 满足哪些条件的请求可以被识别为简单请求
  • 什么是预检请求?
  • 附带身份凭证的跨域请求需要注意什么?

简单介绍一下跨域的内容:

  • 跨域的概念
    • 域名由协议://域名:端口号组成
    • 三个部分有任一不同即被浏览器视为跨域
    • 是浏览器的安全行为,跨域请求会被真实发出和处理,但响应会被浏览器拦截
  • 跨域的影响
    • 不同域之间的资源不能共享(Cookie LocalStorage IndexedDB等)
    • 无法接触非同源网页的DOM和js对象
    • 无法向非同源地址发送Ajax请求
  • 跨域的解决方案
    • JSONP
    • CORS
    • 代理服务器

什么是跨域?出现原因及解决方法

DAY 5

题目描述

选择题 1:  
下列哪些可以实现浏览器存储数据?  
A. cookie  
B. localStorage  
C. session  
D. sessionStorage  
  
选择题 2:  
对以下代码说法正确的是?  
let arr = [1,2,3,4,5];  
let arr2 = [1, , 3];  
A. 执行 arr.length = 3,此时数组为 [1,2,3]  
B. 执行 arr[10] = 11,此时 arr.length 为 6  
C. 执行 delete arr[2],此时 arr.length 为 4,数组为 [1,2,4,5]  
D. arr2.length 的长度为 2

答案与解析

1. ABD
2. A

解析Cookie LocalStorage SessionStorage异同

Cookie LocalStorage SessionStorage都是保存在浏览器内部的数据

Session一般是保存在服务器中,用来标识客户端会话信息。

CookieLocalStorageSessionStorage
大小4Kb5MB5MB
兼容H4/H5H5H5
访问任何窗口任何窗口同一窗口
有效期手动设置窗口关闭
存储位置浏览器和服务器浏览器浏览器
与请求一起发送
语法复杂简单简单
  • Cookie是由?key1=value1;key2=value2组成的,可以通过encodeURIComponent()来保证它不包含任何逗号、分号或空格(cookie值中禁止使用这些值).
  • Cookie一般的字段有path domain max-age expires secure
  • 不同的host之间的localStorage、sessionStorage对象是隔离的

代码运行结果

首先定义arrarr2两个数组:

js
let arr = [1, 2, 3, 4, 5]
let arr2 = [1, , 3]

A选项:

js
arr.length = 3
console.log(arr) // [1, 2, 3]

B选项:

js
arr[10] = 11
console.log(arr.length) // 11

C选项:

js
// 当你删除一个数组元素时,数组的长度不受影响。即便你删除了数组的最后一个元素也是如此。
delete arr[2]
console.log(arr[2]) // undefined
console.log(arr) // [1, 2, <empty item>, 4, 5]
console.log(arr.length) // 5

D选项:

js
console.log(arr2.length) // 3

delete 操作符用于删除对象的某个属性;如果没有指向这个属性的引用,那它最终会被释放。

MDN: delete操作符

DAY 6

题目描述

选择题 1:  
在 css 选择器当中,优先级排序正确的是?  
A. id选择器>标签选择器>类选择器  
B. 标签选择器>类选择器>id选择器  
C. 类选择器>标签选择器>id选择器  
D. id选择器>类选择器>标签选择器  
  
选择题 2:  
如以下代码所示,给 body 绑定两个事件后,调用 document.body.click() 输出的结果是?  
document.body.addEventListener('click', () => {  
Promise.resolve().then(() => console.log(1))  
console.log(2);  
}, false);  
document.body.addEventListener('click', () => {  
Promise.resolve().then(() => console.log(3))  
console.log(4);  
}, false);  
A. 2, 4, 1, 3  
B. 2, 1, 4, 3  
C. 1, 2, 3, 4  
D. 1, 3, 2, 4

答案与解析

1. D
2. B

CSS选择器优先级

内联样式 > ID选择器 > 类选择器 > 标签选择器 > 通配符

不同选择器权重值不同,权重值更高的属性值会覆盖更低的值

  • !important 10000
  • 内联样式 1000
  • id选择器 100
  • 类选择器、属性选择器、伪类 10
  • 元素选择器、伪元素 1
  • 通配符 0

事件循环

需要了解浏览器的事件循环机制才能解出此题,以下是一些可能需要掌握的概念:

  • JavaScript是单线程的
  • 浏览器事件循环机制
  • 主线程、宏任务队列、微任务队列、常见的宏任务与微任务
  • 任务执行队列、函数执行栈

DAY 7

题目描述

选择题 1:  
浮动会导致页面的非正常显示,以下几种清除浮动的方法,哪个是不推荐使用的?  
A. 在浮动元素末尾添加一个空的标签例如 <div style=”clear:both”></div>  
B. 通过设置父元素overflow值为hidden;  
C. 给父元素添加clearfix类  
D. 父元素也设置浮动  
  
选择题 2:  
以下代码的运行结果是?  
var f = function () { console.log('1'); } function f() { console.log('2'); }  
f()  
A. undefined  
B. 报错  
C. 2  
D. 1

答案与解析

1. D
2. D

清除浮动的方法及原理

什么是清除浮动?

当容器的高度为auto,且容器的内容中有浮动元素时,容器的高度不能自动伸长以适应内容的高度,这个时候就需要清除浮动,让容器的高度自动伸长以适应浮动元素。

清除浮动常用方法

  • 使用带clear属性的空元素
    • 在浮动元素后使用一个空元素如<div class="clear"></div>
    • 并在CSS中赋予.clear{ clear: both; }属性即可清理浮动
  • 使用CSS的overflow属性
    • 给父元素赋予overflow: visible;,创建一个新的BFC
      • 浮动元素的父元素触发BFC,形成独立的块级格式化上下文
      • 浮动元素的父元素的高度值为auto(height的默认值即为auto)
    • BFC拥有自己的计算高度的方法与规则
  • 给浮动的元素的容器添加浮动
    • 会导致父元素也跟着浮动 不常用 也不推荐
  • 使用邻接元素处理
    • 给浮动元素后面的兄弟元素添加clear属性
  • 使用CSS的::after伪元素
    • 给浮动元素的父元素末尾添加一个看不见的块元素(Block element)
    • 给这个伪元素添加clear属性清理浮动

变量提升

题目涉及JavaScript的变量提升知识,详细解析见:

MDN 变量提升

彻底解决JS变量提升的面试题

DAY 8

题目描述

选择题 1:  
下列说法正确的有哪些?  
A. visibility:hidden 表示所占据的空间位置仍然存在,仅为视觉上的完全透明  
B. display:none 不为被隐藏的对象保留其物理空间  
C. visibility:hidden 与display:none 两者没有本质上的区别  
D. visibility:hidden 回流与重绘  
  
选择题 2:  
若主机甲与主机已已建立一条 TCP 链接,最大段长(MSS)为 1KB,往返时间(RTT)为 2 ms,则在不出现拥塞的前提下,拥塞窗口从 8KB 增长到 32KB 所需的最长时间是?  
A. 4ms  
B. 8ms  
C. 24ms  
D. 48ms

答案与解析

1. AB(D)
2. D

回流与重绘

  • 重绘不一定引起回流,而回流一定会引起重绘,所以回流是一件很消耗性能的事情
  • 什么情况下会触发回流?
    • DOM 结构发生改变(添加新的节点或者移除节点)
    • 改变了布局(修改了width height padding font-size等值)
    • 窗口resize(修改了窗口的尺寸等)
    • 调用getComputedStyle方法获取尺寸、位置信息
  • 什么情况会触发重绘?
    • 修改背景色、文字颜色、边框颜色、样式等

元素的几种不同显示状态:

  • display: none 指的是元素完全不陈列出来,不占据空间,涉及到了DOM结构,故产生reflow与repaint
  • visibility: hidden 指的是元素不可见但存在,保留空间,不影响结构,故只产生repaint,但不可触发绑定事件
  • opacity: 0 指的是元素不可见但存在,保留空间,不影响结构,并且,如果该元素已经绑定一些事件,如click事件,那么点击该区域,也能触发点击事件的

拥塞窗口调整

拥塞窗口调整有两种模式,一种是以指数增长的慢启动模式,另一种是以线性增长的拥塞避免模式

开始传输时是以慢启动模式调整拥塞窗口,当窗口大小达到名为ssthresh的阈值时,改用拥塞避免模式调整。

问“最长时间”,应该就是指ssthresh非常小以至于一开始就是拥塞避免模式,使得窗口调整的速度较慢,每一个RTT会增加1个MSS(这里是1KB)

从8KB到32KB有24KB的调整空间,就需要24个RTT x 每个RTT的2ms,共计48ms

WikiPedia: TCP拥塞控制

DAY 9

题目描述

选择题 1:  
以下对HTML标签的使用,哪些是符合语义的?  
A. 使用 table 展示表格数据  
B. 使用 span 表示按钮  
C. 使用 article 展示文章内容  
D. 使用 p 标签展示文章标题  
  
选择题 2:  
包过滤防火墙对数据包的过滤依据不包括哪些?  
A. 源IP地址  
B. 源端口号  
C. MAC 地址  
D. 目的 IP 地址

答案与解析

1. AC
2. C

HTML5语义化标签

解析略

包过滤

包过滤是在IP层实现的,包过滤根据数据包的源IP地址、目的IP地址、协议类型(TCP包、UDP包、ICMP包)、源端口、目的端口等包头信息及数据包传输方向等信息来判断是否允许数据包通过

编程题

题目 1

**题目**

给定一个十进制整数字符串,判断它是否是 4 的幂。

**示例 1**

输入:"16",输出:true

**示例 2**

输入:"101",输出:false

**示例 3**

输入:"70368744177664",输出:true

**限定语言:** C、 C++、Java、Python、JavaScript V8

题解

TypeScript

ts
// LeetCode 342
function isPowerOfFour(n: number): boolean {
  return n > 0 && (n & (n - 1)) === 0 && n % 3 === 1
}

题目 2

**题目**

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略空格、字母的大小写。

**示例**

输入:"A man, a plan, a canal: Panama",输出:true

**限定语言:** C、 C++、Java、Python、JavaScript V8

题解

TypeScript

ts
// LeetCode 125
function isPalindrome(s: string): boolean {
  let checkStr = ''
  let revStr = ''
  // 遍历原字符串
  // 1.将原串转为仅剩数字与小写字母 2.生成反转串
  for (let i = 0; i < s.length; i++) {
    if (isAlnum(s[i])) {
      checkStr += s[i].toLocaleLowerCase()
      revStr = s[i].toLocaleLowerCase() + revStr
    }
  }
  return checkStr === revStr
}

/**
 * 检查字符串是否仅由数字与小写字母组成
 * @param s 待检查字符串
 */
function isAlnum(s: string): boolean {
  return /^[a-z0-9]+$/i.test(s)
}

题目 3

**题目**

给定一个字符串,找出该字符串中最长回文子串的长度。

**示例 1**

输入:"abc",输出:0

**示例 2**

输入:"abcbe",输出:3

**示例 3**

输入:"acdcecdcf",输出:7

**限定语言:** C、 C++、Java、Python、JavaScript V8

题解

TypeScript

ts
// LeetCode 5
function longestPalindrome(s: string): string {
  const len = s.length
  if (len < 2) return s

  let maxLength = 1
  let begin = 0

  for (let i = 0; i < len - 1; i++) {
    // 头指针 从0遍历到len-1
    for (let j = i + 1; j < len; j++) {
      // 尾指针 从1遍历到len
      if (j - i + 1 > maxLength && validPalindrome(s, i, j)) {
        // 子串更长 且为回文字符串
        maxLength = j - i + 1 // 更新长度
        begin = i // 更新头指针位置
      }
    }
  }

  return s.substring(begin, begin + maxLength)

  function validPalindrome(str: string, begin: number, end: number) {
    while (begin < end) {
      if (str[begin] !== str[end]) return false
      begin++
      end--
    }
    return true
  }
}

Released under the MIT License.