2022/12/4
前言
课程传授方式
引导型学习, 优先抛出一些面试题, 注意! 主要是学习 知识点,能达到举一反三的效果, 不要局限于题目本身
HTML, CSS面试题
一、 HTML面试题
1.1 如何理解HTML语义化
- 让人更容易读懂(增加代码可读性)
- 让搜索引擎更容易读懂(SEO)
1.2 默认情况下,哪些HTML标签是块级元素、哪些是内联元素?
- display: block/table;有div h1 h2 table ul ol p等
- display: inline/inline-block;有span img input button 等
二、CSS面试题
2.1 布局
盒子模型的宽度如何计算?
- offsetWidth = (内容宽度 + 内边距 + 边框), 无外边距
margin纵向重叠的问题
margin负值的问题
- margin-top和margin-left负值,元素向上、向左移动
- margin-right负值,右侧元素左移,自身不受影响
- margin-bottom负值,下方元素上移,自身不受影响
BFC理解和应用
- BFC: 块级格式化上下文, 一块独立渲染区域,内部元素的渲染不会影响边界以外的元素
- 形成BFC的常见条件
- float不是none
- position是absolute 或 fixed
- overflow 不是 visible
- display 是 flex inline-block
- BFC的常见应用
- 清除浮动
float布局的问题,以及clearfix
如何实现圣杯布局和双飞翼布局?
- 圣杯布局和双飞翼布局的目的
- 三栏布局,中间一栏最先加载和渲染(内容最重要)
- 两侧内容固定,中间内容随着宽度自适应
圣杯布局
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>圣杯布局</title>
<style type="text/css">
body {
min-width: 550px;
}
#header {
text-align: center;
background-color: #f1f1f1;
}
#container {
padding-left: 200px;
padding-right: 150px;
}
#container .column {
float: left;
}
#center {
background-color: #ccc;
width: 100%;
}
#left {
position: relative;
background-color: yellow;
width: 200px;
margin-left: -100%;
right: 200px;
}
#right {
background-color: red;
width: 150px;
margin-right: -150px;
}
#footer {
text-align: center;
background-color: #f1f1f1;
}
/* 手写 clearfix */
.clearfix:after {
content: '';
display: table;
clear: both;
}
</style>
</head>
<body>
<div id="header">this is header</div>
<div id="container" class="clearfix">
<div id="center" class="column">this is center</div>
<div id="left" class="column">this is left</div>
<div id="right" class="column">this is right</div>
</div>
<div id="footer">this is footer</div>
</body>
</html>
双飞翼布局
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>双飞翼布局</title>
<style type="text/css">
body {
min-width: 550px;
}
.col {
float: left;
}
#main {
width: 100%;
height: 200px;
background-color: #ccc;
}
#main-wrap {
margin: 0 190px 0 190px;
}
#left {
width: 190px;
height: 200px;
background-color: #0000FF;
margin-left: -100%;
}
#right {
width: 190px;
height: 200px;
background-color: #FF0000;
margin-left: -190px;
}
</style>
</head>
<body>
<div id="main" class="col">
<div id="main-wrap">
this is main
</div>
</div>
<div id="left" class="col">
this is left
</div>
<div id="right" class="col">
this is right
</div>
</body>
</html>
手写clearfix
.clearfix:after {
content: '';
display: table;
clear: both;
}
2.1.6. flex画色子
2.2 定位
1. absolute和relative 分别依据什么定位?
- relative依据自身定位
- absolute依据最近一层的定位元素定位
2. 居中对齐有哪些实现方式?
- 水平居中:
- inline元素: text-align: center
- block元素:margin: auto
- absolute元素:left: 50%+ margin-left负值
- 垂直居中:
-
inline元素:line-height的值等于height值
-
absolute元素:top: 50% + margin-top 负值
-
absolute元素:transform(-50%,-50%)
-
absolute元素: top, left, bottom, right = 0 + margin: auto
-
2.3 图文样式
line-height如何继承
- 写具体数值,如30px ,则继承该值(比较好理解)
- 写比例,如2/1.5 ,则继承该比例(比较好理解)
- 写百分比,如200%,则继承计算出来的值(考点)
2.4 响应式
1. rem是什么
- 相对长度单位,相对于根元素,常用于响应式布局
2. 如何实现响应式
常用方案
- media-query,根据不同的屏幕宽度设置根元素font-size
- rem,基于根元素的相对单位
- vw/vh, 是网页视口宽度/高度的1/100
2.5 CSS3
关于CSS动画
三、JS基础
3.1 变量类型和计算
typeof能判断哪些类型
常见值类型:
undefined
number
boolean
symbol
常见引用类型:
对象
数组
null(特殊引用类型,指针指向为空地址)
函数 (特殊引用类型,但不用于存储数据,所以没有“拷贝、复制函数"这―说)
typeof能
- 具体识别所有值类型
- 能判断函数
- 能识别引用类型为object(不能再继续)
手写JS深拷贝
function deepClone(obj = {}) {
if(typeof obj !== 'object' || typeof obj == null ) {
return
}
let result
if(typeof obj instanceof Array) {
result = []
} else {
result = {}
}
for(let key in obj) {
if(obj.hasOwnProperty(key)) {
result[key] = deepClone(obj[key])
}
}
return result
}
何时使用 === 何时使用 ==
字符串拼接
100 + '10' = '10010'
==
会将等号两边值转换为boolean,再进行判断
if语句和逻辑运算
值类型和引用类型的区别
3.2 原型和原型链
如何准确判断一个变量是不是数组?
instanceof
手写一个简易的jQuery ,考虑插件和扩展性
class的原型本质,怎么理解?
实际上是函数, class是语法糖
原型和原型链的图示
属性和方法的执行规则
3.3 作用域和闭包
题目
this的不同应用场景,如何取值?
手写bind函数
实际开发中闭包的应用场景,举例说明
- 隐藏数据
- 例如做一个简单的cache工具
相关知识
作用域和自由变量
- 全局作用域
- 函数作用域
- 块级作用域
闭包
作用域应用的特殊情况,有两种表现︰
-
函数作为参数被传递
-
函数作为返回值被返回
this
- 作为普通函数
- 使用call apply bind
- 作为对象方法被调用
- 在class方法中调用
- 箭头函数
3.4 异步
题目
同步和异步的区别是什么?
异步不会阻塞代码,同步会
手写用Promise加载一张图片
function loadImg(src) {
const p = new Promise(
(resolve, reject) => {
const img = document.createElement('img')
img.onload = () => {
resolve(img)
}
img.onerror = () => {
const err = new Error(`图片加载失败 ${src}`)
reject(err)
}
img.src = src
}
)
return p
}
前端使用异步的场景有哪些?
- 网络请求,如ajax图片加载
- 定时任务,如setTimeout
知识点
单线程和异步
JS与异步
- JS是单线程语言,只能同时做一件事儿
- 浏览器和nodejs已支持JS启动进程,如Web Worker JS和DOM渲染共用同一个线程,因为JS可修改DOM结构
- JS和DOM渲染共用同一个线程,因为JS可修改DOM结构
单线程与异步
- 遇到等待(网络请求,定时任务)不能卡住
- 需要异步
- 回调callback函数形式
callback hell 和 Promise
四、JS异步进阶
五、JS-Web-API-DOM
题目
DOM是哪种数据结构
树
DOM操作的常用API
-
const div1 = document.getElementById('div1') -
const divList = document.getElementsByTagName('div') -
const containerList = document.getElementsByClassName('container') // 集合 -
const pList = document.querySelectorAll('p')
attr和 property的区别
- property :修改对象属性,不会体现到html结构中
- attribute :修改html 属性,会改变html结构
- 两者都有可能引起 DOM重新渲染
一次性插入多个DOM节点,考虑性能
涉及知识点
DOM本质
树
DOM节点操作
- 获取DOM节点
- attribute
- property
DOM结构操作
const div1 = document.getElementById('div1')
const div2 = document.getElementById('div2')
// 新建节点
const newP = document.createElement('p')
newP.innerHTML = 'this is newP'
// 插入节点
div1.appendChild(newP)
// 移动节点
const p1 = document.getElementById('p1')
div2.appendChild(p1)
// 获取父元素
console.log( p1.parentNode )
// 获取子元素列表
const div1ChildNodes = div1.childNodes
console.log( div1.childNodes )
const div1ChildNodesP = Array.prototype.slice.call(div1.childNodes).filter(child => {
if (child.nodeType === 1) {
return true
}
return false
})
console.log('div1ChildNodesP', div1ChildNodesP)
div1.removeChild( div1ChildNodesP[0] )
DOM性能
- DOM操作非常“昂贵”,避免频繁的DOM操作
- 对DOM查询做缓存
//缓存DOM查询结果
const pList = document.getElementsByTagName( 'p')
const length = pList.length
- 将频繁操作改为一次性操作
const list = document.getElementById('list')
// 创建一个文档片段,此时还没有插入到 DOM 结构中
const frag = document.createDocumentFragment()
for (let i = 0; i < 20; i++) {
const li = document.createElement('li')
li.innerHTML = `List item ${i}`
// 先插入文档片段中
frag.appendChild(li)
}
// 都完成之后,再统一插入到 DOM 结构中
list.appendChild(frag)
console.log(list)
六、JS-Web-API-BOM
题目
如何识别浏览器的类型
分析拆解url各个部分
知识点
navigator
screen
location
history
七、JS-Web-API-事件
题目
编写一个通用的事件监听函数
// 通用的事件绑定函数
// function bindEvent(elem, type, fn) {
// elem.addEventListener(type, fn)
// }
function bindEvent(elem, type, selector, fn) {
if (fn == null) {
fn = selector
selector = null
}
elem.addEventListener(type, event => {
const target = event.target
if (selector) {
// 代理绑定
if (target.matches(selector)) {
fn.call(target, event)
}
} else {
// 普通绑定
fn.call(target, event)
}
})
}
// 普通绑定
const btn1 = document.getElementById('btn1')
bindEvent(btn1, 'click', function (event) {
// console.log(event.target) // 获取触发的元素
event.preventDefault() // 阻止默认行为
alert(this.innerHTML)
})
// 代理绑定
const div3 = document.getElementById('div3')
bindEvent(div3, 'click', 'a', function (event) {
event.preventDefault()
alert(this.innerHTML)
})
// const p1 = document.getElementById('p1')
// bindEvent(p1, 'click', event => {
// event.stopPropagation() // 阻止冒泡
// console.log('激活')
// })
// const body = document.body
// bindEvent(body, 'click', event => {
// console.log('取消')
// // console.log(event.target)
// })
// const div2 = document.getElementById('div2')
// bindEvent(div2, 'click', event => {
// console.log('div2 clicked')
// console.log(event.target)
// })
描述事件冒泡的流程
无限下拉的图片列表,如何监听每个图片的点击?
知识点
事件绑定
事件冒泡
事件代理
- 代码简洁
- 减少浏览器内存占用
八、JS-Web-API-ajax
题目
手写一个简易的ajax
function ajax(url) {
const p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', url, true)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(
JSON.parse(xhr.responseText)
)
} else if (xhr.status === 404 || xhr.status === 500) {
reject(new Error('404 not found'))
}
}
}
xhr.send(null)
})
return p
}
跨域的常用实现方式
- 加载图片css js可无视同源策略
- jsonp
- CORS-服务器设置http header
知识点
XMLHttpRequest
状态码
- 2xx-表示成功处理请求,如200
- 3xx -需要重定向,浏览器直接跳转,如301 302 304
- 4xx-客户端请求错误,如404 403
- 5xx–服务器端错误
跨域:同源策略
同源策略
ajax请求时,浏览器要求当前网页和server 必须同源(安全)
同源∶协议、域名、端口,三者必须一致
九、JS-Wep-Api-存储
cookie
介绍
- 本身用于浏览器和server通讯
- 被"借用"到本地存储来
- 可用document.cooike = ''来修改
缺点
- 存储大小,最大4KB
- http请求时需要发送到服务端,增加请求数据量
- 只能用document.cookie = '.!来修改,太过简陋
localStorage 和 sessionStorage
介绍
- HTML5专门为存储而设计,最大可存5M
- API简单易用setltem getItem
- 不会随着http请求被发送出去
对比
- localStorage数据会永久存储,除非代码或手动删除
- sessionStorage数据只存在于当前会话,浏览器关闭则清空
- 一般用localStorage会更多一些
描述cookie localStorage sessionStorage区别
- 容量
- API易用性
- 是否跟随http请求发送出去
十、http 面试题
题目
http常见的状态码有哪些?
- 200成功
- 301永久重定向(配合location ,浏览器自动处理)
- 302临时重定向(配合location,浏览器自动处理)
- 304资源未被修改
- 404资源未找到
- 403没有权限
- 500服务器错误
- 504网关超时
关于协议和规范
- 就是一个约定
- 要求大家都跟着执行
- 不要违反规范
http常见的header有哪些?
常见的Request Headers
- Accept浏览器可接收的数据格式
- Accept-Encoding浏览器可接收的压缩算法,如gzip
- Connection: keep-alive 一次TCP连接重复使用
- cookie
- Host
- User-Agent(简称UA)浏览器信息
- Content-type发送数据的格式,如application/json
常见的Response Headers
- Content-type返回数据的格式,如application/json
- Content-length返回数据的大小,多少字节
- Content-Encoding返回数据的压缩算法,如gzip
常见的Response Headers
什么是 Restful API?
- 一种新的API设计方法(早已推广使用)
- 传统API设计∶把每个rl当做一个功能
- Restful API设计:把每个url当做一个唯一的资源
描述一下http的缓存机制(重要)
关于缓存的介绍
- 哪些资源可以被缓存? -- 静态资源(js css img)
强制缓存
cache-control的值
协商缓存
服务器端缓存策略
服务器判断客户端资源,是否和服务端资源一样
—致则返回304 ,否则返回200和最新的资源
- 资源标识
- 在Response Headers中,有两种
- Last-Modified资源的最后修改时间
- Etag资源的唯一标识(一个字符串,类似人类的指纹)
刷新操作方式,对缓存的影响
- 正常操作:强制缓存有效,协商缓存有效
- 手动刷新∶强制缓存失效,协商缓存有效
- 强制刷新∶强制缓存失效,协商缓存失效
十一、开发环境
- git
- 调试工具
- 抓包
- webpack babel
- linux常用命令
十二、运行环境
网页加载的过程
加载资源的形式
加载资源的过程
渲染页面的过程
性能优化
- 多使用内存、缓存或其它方法
- 减少CPU计算量,减少网络加载耗时
- 空间换时间
让加载更快
- 减少资源体积∶压缩代码
- 减少访问次数∶合并代码,SSR服务器端渲染,缓存
- 使用更快的网络:CDN
让渲染更快
- CSS 放在head ,JS放在body最下面
- 尽早开始执行JS,用DOMContentLoaded触发
- 懒加载(图片懒加载,上滑加载更多)
- 对DOM查询进行缓存
- 频繁DOM操作,合并到一起插入DOM结构
- 节流throttle防抖debounce
手写debounce
function debounce(fn, delay = 300) {
let timer = null
return function() {
if(timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay)
}
}