Skip to content

前端基础知识


一、Ajax Fetch Axios 三者区别

1. 三者都用于网络请求,但是不同维度

  • Ajax ( Asynchronous Javascript and XML ) ,一种技术统称
  • Fetch ,一个具体的 API
  • Axios ,是一个第三方库

2. 用 XMLHttpRequest 实现 Ajax

js
const xhr = new XMLHttpRequest()
xhr.open('GET', 'https://www.baidu.com', false)
xhr.onreadystatechange = function () {
    if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText)
    }
}
xhr.send(null)

3. Fetch

  • 浏览器原生 API ,用于网络请求
  • 和 XMLHttpRequest 一个级别
  • Fetch 语法更简洁、易用,支持 Promise

4. Axios

  • 最常用的网络请求 lib (随 Vue 火爆起来)
  • 内部可用 XMLHttpRequest 和 Fetch 实现

5. 答案

  • Ajax - 一种技术统称
  • Fetch - 一个原生 API
  • Axios - 一个第三方库

6. 划重点

  • lib 和 API 区别
  • 实际项目中,使用现成的 lib ,尽量不要自己造轮子
  • 但读源码,造轮子是很好的个人学习方式

二、节流和防抖

1. 题目

  • 防抖和节流有什么区别
  • 分别应用到什么场景

2. 防抖

  • 防抖,防止抖动 “ 你先抖动着,什么时候停 ” 再执行下一步
  • 例如:一个搜索输入框,等输入停止之后,再触发搜索

3. 防抖 - 代码

js
const input = document.getElementById('input')
    input.addEventListener('keyup', debounce(function () {
        console.log('提交', this.value)
    }, 300))

function debounce(fun, delay = 200) {
  	let timer = null
  	return function () {
    	if (timer) clearTimeout(timer)
    	timer = setTimeout(() => {
      	fun.apply(this, arguments)  // 透传 this 和 参数
      	timer = null
    	}, delay)
  	}
}

4. 防抖 - 示意图

image-20220313134215722

5. 节流

  • 节流,节省交互沟通。流,不一定至流量
  • “ 别急,一个一个来,按时间节奏来,插队者无效 ”
  • 例如,drag 和 scroll 期间触发某个回调,要设置一个时间间隔

6. 节流 - 代码

js
const div = document.getElementById('div')
    input.addEventListener('drag', debounce(function (e) {
        console.log('拖动', e.offsetX, e.offsetY)
    }, 100))

function debounce(fun, delay = 200) {
  	let timer = null
  	return function () {
    	if (timer) clearTimeout(timer)
    	timer = setTimeout(() => {
      	fun.apply(this, arguments)  // 透传 this 和 参数
      	timer = null
    	}, delay)
  	}
}

7. 节流 - 示意图

image-20220313135926463

8. 答案

  • 节流:限制执行频率,有节奏的执行
  • 防抖:限制执行次数,多次密集的触发只执行一次
  • 节流关注 “过程” ,防抖关注 “结果”

三、px % em rem vw vh 的区别

1. px 和 %

  • px 基本单位,绝对单位(其他的都是相对单位)
  • % 相对父元素的宽度比例

2. em 和 rem

  • em 是根据当前元素的 font-size
  • rem 是根据根节点的 font-size

3. vw 和 vh

  • vw 是屏幕宽度的 1 %
  • vh 是屏幕高度的 1 %
  • vmin 两者间的最小值,vmax 两者间的最大值

四、箭头函数

1. 题目

  • 箭头函数有什么缺点
  • 什么时候不能使用箭头函数

2. 箭头函数缺点

  • 没有 arguments
  • 无法通过 apply call bind 改变 this
  • 某些箭头函数的代码难以阅读

3. 不适用场景

  • 对象方法

    js
    const obj = {
      	name: 'lzz',
      	getName: () => {
          	return this.name
        }
    }
  • 原型方法

    js
    const obj = {
      	name: 'lzz'
    }
    obj.__proto__.getName = () => {
      	return this.name
    }
  • 构造函数

    js
    const Foo = (name, age) => {
      	this.name = name
      	this.age = age
    }
    const foo = new Foo('lzz', 24)  // Foo is not a constructor
  • 动态上下文中的回调函数

    js
    const btn = document.getElementById('btn')
    btn.addEventListener('click', () => {
      	// console.log(this === window)  // true
      	this.innerText = 'clicked'
    })
  • Vue 的生命周期和 method

    js
    {
        data() {
          	return {name: 'lzz'}
        },
        method: {
            getName: () => {
              // 报错 Cannot read properties of undefined (reading 'name')
              return this.name
            }
            // getName() {
            //     return this.name  // 正常
            // }
        },
            mounted:() => {
              // 报错 Cannot read properties of undefined (reading 'name')
              console.log(this.name)
            }
            // mounted() {
            //     console.log(this.name)  // 正常
            // }
    }
    1. Vue 组件本质上是一个 JS 对象
    2. React 组件(非 Hooks)它本质上是一个 ES6 class(可以使用箭头函数)

4. 划重点

  • 要熟练使用箭头函数,也要对函数 this arguments 敏感
  • 传统 Vue 组件是 JS 对象,传统 React 组件是 class ,两者不同

五、请描述 TCP 三次握手四次挥手

1. 建立 TCP 连接

  • 先建立连接(确保双方都有收发消息的能力)
  • 再传输内容(如发送一个 get 请求)
  • 网络连接是 TCP 协议,传输内容是 HTTP 协议

2. 三次握手 - 建立连接

  • Client 发包,Server 接收。Server:有 Client 找我
  • Server 发包,Client 接收。Client:Server 已经接收到消息了
  • Client 发包,Server 接收。Server:Client 要准备发送了

3. 四次挥手 - 断开连接

  • Client 发包,Server 接收。Server:Client 已请求结束
  • Server 发包,Client 接收。Client:Server 已经收到,我等待它关闭
  • Server 发包,Client 接收。Client:Server 此时已经可以关闭了
  • Client 发包,Server 接收。Server:可以关闭了(然后关闭连接)

4. 图解

image-20220313163958377

image-20220313164649894

5. 划重点

  • 握手是连接,挥手是告别

六、for ... in 和 for ... of 的区别

1. key 和 value

  • for ... in 遍历得到 key
  • for ... of 遍历得到 value

2. 适用于不同数据类型

  • 遍历对象:for ... in 可以,for ... of 不可以

  • 遍历 Map Set :for ... of 可以,for ... in 不可以

  • 遍历 generator:for ... of 可以,for ... in 不可以

    js
    // 遍历 generator
    function* foo() {
        yield 10
        yield 20
        yield 30
    }
    for (const y of foo()) {
        console.log(y)  // 10 20 30
    }
    // 拓展:generator 常用场景
    // 为不具备 Iterator 接口的对象提供遍历方法
    function* objectEntries(obj) {
        for (const propKey of Object.keys(obj)) {
            yield [propKey, obj[propKey]];
        }
    }
    const jane = { first: 'Jane', last: 'Doe' };
    for (const [key,value] of objectEntries(jane)) {
        console.log(`${key}: ${value}`);  // first: Jane  last: Doe
    }

3. 可枚举 vs 可迭代

  • for ... in 用于 可枚举 数据,如对象、数组、字符串

  • for ... of 用于 可迭代 数据,如数组、字符串、Map、Set

    image-20220314103330492

4. 答案

  • for ... in 用于 可枚举 数据,如对象、数组、字符串,得到 key
  • for ... of 用于 可迭代 数据,如数组、字符串、Map、Set,得到 value

七、(连环问) for await ... of 有什么用

1. 答案

  • for await ... of 用于遍历多个 Promise

    js
    function createPromise(val) {
        return new Promise(resolve => {
            setTimeout(() => {
                resolve(val)
            }, 3000)
        })
    }
    
    (async function () {
        const p1 = createPromise(100)
        const p2 = createPromise(100)
        const p3 = createPromise(100)
        // const res1 = await p1
        // const res2 = await p2
        // const res3 = await p3
        const list = [p1, p2, p3]
        Promise.all(list).then(res => console.log(res))
        for await (let res of list) {
            console.log(res)
        }
      	// 顺序调用
      	const res1 = await createPromise(100)
        console.log(res1)
        const res2 = await createPromise(200)
        console.log(res2)
        const res3 = await createPromise(300)
        console.log(res3)
        const arr = [100, 200, 300]
        for (let num of arr) {
            const res = await createPromise(num)
            console.log(res)
        }
    })()

八、offsetHeight scrollHeight clientHeight 区别

1. 计算规则

  • offsetHeight / offsetWidth:border + padding + content
  • clientHeight / clientWidth:padding + content
  • scrollHeight / sceollWidth:padding + 实际内容尺寸(包括里面内容)

九、HTMLCollection 和 NodeList 区别

1. Node 和 Element

  • DOM 是一棵树,所有节点都是 Node
  • Node 是 Element 的基类
  • Element 是其他 HTML 元素的基类,如 HTMLDivElement

image-20220314150540547

2. HTMLCollection 和 NodeList

  • HTMLCollection 是 Element 的集合
  • NodeList 是 Node 集合

3. 划重点

  • 获取 Node 和 Element 的返回结果可能不一样
  • 如 elem.childNodes 和 elem.children 不一样
  • 前者会包含 Text 和 Comment 节点,后者不会

4. 扩展:类数组 -> 数组

js
// HTMLCollection 和 NodeList 都不是数组, 而是 "类数组"
const arr1 = Array.from(list)
const arr2 = Array.prototype.slice.call(list)
const arr3 = [...list]

十、Vue computed 和 watch 区别

1. 两者用途不同

  • computed 用于计算产生新的数据
  • watch 用于监听现有数据

2. computed 有缓存

  • computed 有缓存
  • method 没有缓存

十一、Vue 组件通讯有几种方式

1. Vue 组件通讯有几种方式

  • props 和 $emit

  • 自定义事件(Vue3 中要单独引 event-emitter 库)

  • $attr

  • $parent

  • $refs

  • provide / inject

    js
    // 静态
    provide: {
      info: 'aaa'
    }
    // 响应式
    provide() {
      return {
        info: computed(() => this.name)
      }
    }
    // 接收
    inject: ['info']
  • Vuex

2. 不同场景

  • 父子组件
  • 上下级组件(跨多级)通讯
  • 全局组件

十二、Vuex mutation action 区别

1. 区别

  • mutation:原子操作;必须同步代码
  • action:可包含多个 mutation ;可包含异步代码

十三、JS 严格模式有什么特点

1. 开启严格模式

js
'use strict'  // 全局开启
function fn() {
  	'use strict'  // 某函数开启
}

2. 特点

  • 全局变量必须先声明

  • 禁止使用 with

    js
    const obj = { x: 100, y: 200 }
    with (obj) = {
      	console.log(x, y)  // obj.x obj.y
    }
  • 创建 eval 作用域

    js
    'use strict'
    var x = 10
    eval(`var x = 20; console.log('in eval', x);`)  // 20 很不推荐使用 eval
    console.log('out eval', x);  // 10
  • 禁止 this 指向 window

    js
    'use strict'
    function fn() {
      	console.log('this', this)  //undefined
    }
    fn()
  • 函数参数不能重名


十四、HTTP 跨域为何要发送 options 请求

1. 跨域请求

  • 浏览器同源策略
  • 同源策略一般限制 Ajax 网络请求,不能跨域请求 server
  • 不会限制 <link> <img> <script> <iframe> 加载第三方资源

2. JSONP

image-20220315170045485

3. CORS

image-20220315170153791

4. 答案

  • options 请求,是跨域请求前的预检查
  • 浏览器自行发起的,无需我们干预
  • 不影响实际功能

十五、Restful API 常用 method

  • GET 查询
  • POST 新增
  • PATCH 更新
    1. PATCH 很像的还有 PUT 方法,两者有差别
      • PUT 更新全部内容,即替换
      • PATCH 更新部分内容 —— 更加常用
  • DELETE 删除