某课的《高效准备前端技术一面》笔记(更新中...)

102 阅读9分钟

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
如何实现圣杯布局和双飞翼布局?
  • 圣杯布局和双飞翼布局的目的
    • 三栏布局,中间一栏最先加载和渲染(内容最重要)
    • 两侧内容固定,中间内容随着宽度自适应
圣杯布局

image.png

<!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是语法糖

原型和原型链的图示

image.png

属性和方法的执行规则

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)
强制缓存

image.png

cache-control的值

协商缓存

服务器端缓存策略
服务器判断客户端资源,是否和服务端资源一样
—致则返回304 ,否则返回200和最新的资源

image.png

  • 资源标识
    • 在Response Headers中,有两种
    • Last-Modified资源的最后修改时间
    • Etag资源的唯一标识(一个字符串,类似人类的指纹)

image.png

刷新操作方式,对缓存的影响
  • 正常操作:强制缓存有效,协商缓存有效
  • 手动刷新∶强制缓存失效,协商缓存有效
  • 强制刷新∶强制缓存失效,协商缓存失效

十一、开发环境

  • 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)
    } 
}