中鸡前端面试精选
一、JavaScript
1.数据类型
值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol。
引用数据类型(对象类型):对象(Object)、数组(Array)、函数(Function),还有两个特殊的对象:正则(RegExp)和日期(Date)。
2.数组方法
原数组变化
- Array.push() 末尾添加元素
- Array.pop() 末尾删除元素
- Array.unshift() 开头添加元素
- Array.shift() 开头删除元素
原数组不变并生成新数组
- Array.concat(Arr1,Arr2,…) 合并两个或多个数组
- Array.join() 将数组每一项使用自定字符连接,并形成一个字符串,可用到数组转字符串
- Array.map() 遍历数组每一项
- Array.slice(m,n) 指定查找,从m-n,不传第二个参数默认到末尾
- Array.forEach() 与map类似,不改变原数组
- Array.filter() 过滤符合条件的数组
3.Array.forEach() 和 Array.map()区别
- 都可以接收三个参数(item,index,Array)
- map方法存在返回值,而forEach返回值是undefined
- map方法不改变原数组并返回新数组,forEach可以通过其索引改变原数组
4.闭包
含义:定义在一个函数内部的函数,并且能被被函数外部所引用。
函数A被定义在内部的函数B引用时,函数A被函数B闭包,当函数A被执行完时,函数A的作用域不会被释放。
本质:函数外部和内部连接的桥梁。
优点:可以实现对象的私有属性和私有方法。让局部变量持久化保存,防止变量污染。
变量污染:变量被重复定义,后面的会覆盖前面的。
缺点:由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。
内存泄漏:程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
解决:在函数执行完,将不使用的局部变量删除:局部变量=null。
5.栈和堆
**栈:**栈会自动分配内存空间,会自动释放,存放基本类型,简单的数据段,占据固定大小的空间.
堆:动态分配空间,大小不定,也不会释放,存放引用数据类型,指哪些可能由多个值构成的对象,保存在堆内存中,包含引用类型的变量本身,实际上保存的不是变量本身,而是指向该对象的指针。
6.同步异步
JavaScript是单线程语言,分为同步任务和异步任务
同步任务:直接进入执行栈,在主线程上排队执行的任务,只有前一个任务执行完毕才会执行下一个任务
异步任务:不进入主线程,而进入任务队列的任务,只有等主线程任务全部执行完毕,任务队列才会进入主线程执行
而异步任务分为宏任务和微任务,其主要区分有:
- 宏任务:setTimeout、setInterval、AJAX、DOM事件
- 微任务:Promise、async 、await
执行顺序:开始新的宏任务 => 宏任务执行 => 宏任务执行完毕 => 判断有没有可执行的微任务
有可执行微任务 => 执行所有微任务 => 微任务执行完毕 => 开始新的宏任务
没有可执行微任务 => 执行新的宏任务
由此可见:JavaScript的执行机制是Event Loop(事件循环)
二、Vue
1.watch和computed
-
共性:
- watch和computed都是以Vue的依赖追踪机制为基础
- 它们都试图处理这样一件事情:当某一个或多个数据(称它们为依赖数据)发生变化的时候,所有依赖这些数据的 “相关” 数据 “自动” 发生变化,也就是自动调用相关的函数去实现数据的变动。
-
区别:
- computed支持缓存,只有依赖数据发生变化,才会重新计算
- computed不支持异步
- computed是依赖某个值或通过props计算得来的数据;watch是通过监听某个数据,进行相应的操作
- watch可以接收两个参数(newVal,oldVal)
用人话说:多个值影响一个值,用计算属性;一个值影响多个值,用watch
2. diff算法
diff算法就是虚拟节点之间进行对比,并返回一个patch对象用来存储两个节点不同的地方,然后通过path记录的消息去局部更新DOM
在Vue中,diff作用于虚拟 dom 渲染成真实 dom 的新旧 VNode 节点比较
简单来说:diff的过程就是重复调用名为patch的函数,比较新旧节点,一边比较一边给真实的DOM打补丁
diff算法步骤:
- 通过JavaScript对象结构表示DOM树的结构,然后用这个树构建一个真实的DOM,并插入到文档中
- 当状态变更的时候,重新构造一颗新的对象树,然后用新的树和旧的树进行比较(diff),记录两棵树的差异
- 把第二棵树记录的差异应用到第一颗树所构建的真实DOM树上(patch),视图就更新了
diff特点:
- 只会在同层级比较,不会跨级比较
- 在diff比较过程中,循环由两边向中间靠拢
3. v-for为什么要加key
源码:
function sameVnode (a, b) {
return (
a.key === b.key && a.tag === b.tag //就地复用
)
}
也就是说,判断两个节点是否为同一个节点(也就是是否可复用),标准是key相同且tag相同。
- 当不加key时,key都是undefined,默认相同,此时也会按照diff算法的就地复用来进行比较
- diff算法默认使用“就地复用”的策略,是一个首尾交叉对比的过程。
- 不要使用index作为key,如果不加key,默认采用“就地复用”的策略,推荐用id作为key
- 将与元素唯一对应的值作为key,可以最大化利用dom节点,提升性能
4.Vuex
Vuex 是为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件状态,并以相应的规则保证状态以一种可预测的方式发生变化。
store中主要有五个对象:state、mutations、actions、getters、modules
- state:相当于data,用于存放公共数据
- mutations相当于methods,可在此改变state中数据的值,但不可调用异步方法
- actions在此函数调用异步方法,并通过context.commit调用mutations中的方法修改state中的值
- getters相当于计算属性,不会改变state中的值,并通过return返回新值
- modules模块化思想,在modules中的state值,必须通过getters包装返回,否则为undefined
5.Vue过滤器
src目录下新建filters/index.js
模块化思想,不同模块过滤器放到不同文件夹下
filters目录下新建formatLongText.js
// 过滤器
export default (val) => {
if (val.length > 10) return val.slice(0, 10) +'...'
return val
}
filters/index.js引入过滤器并导出
import formatLongText from './formatLongText'
export {
formatLongText
}
全局使用:
main.js注册过滤器
import * as filters from '@/filters'
Object.keys(filters).forEach(key =>{
Vue.filter(key,filters[key])
})
局部使用:
import {formartLong} from '@/filters'
// data同级新建filters对象
filters:{formartLong}
使用
<a-checkbox @change="(e)=>{handleChangeCheckBoxVal(e,item.id)}">{{ item.info | formatLongText }}</a-checkbox>
6.Vue打包优化
- 路由懒加载
component: () => import('../views/Login')
- 使用
terser-webpack-plugin
插件移除console语句 - 在
webpack.config.js
中的externals
对象下声明需要使用CDN的资源,并在index.html
中引入CDN连接,减少包的体积 - 使用
webpack-bundle-analyzer analyzer
图片压缩工具,减少图片大小 - 多环境打包配置
package.json
定义脚本,并在.env
文件配置baseURL