前端面试题
uni-app
-
uni-app 里没有 div,都是用 view 标签代替
-
使用图片时要用 import 引入,并在 data() 里返回,最后才能绑定到标签上去
-
onLoad()为加载函数
-
页面跳转
- uni.navigateTo:保留当前页面,跳转到应用内的某个页面
- uni.redirectTo:不保留当前页面
- window.location.href:跳转站外
-
内置提示
- uni.showToast():提示框
- uni.showLoading():过渡动画
-
使用uni时尽量使用原生方法
JS
-
js数据类型
-
基本数据类型:
Number
String
Boolean
Null
Undefined
Symbol (可以产生一个独一无二的值,ES6)
bigInt (可以用来表示任意精度整数的基本数据类型) -
引用数据类型:
object
Array
Date
Function
RegExp (正则表达式)
-
-
闭包
- 什么是闭包:函数执行,形成私有的执行上下文,使内部私有变量不受外界干扰,起到保护保存作用
- 应用场景:设计模式中的单例模式,防抖与节流,函数柯里化
- 缺点:出现内存泄露问题
-
map 与 forEach 的区别
- map 方法,它会返回一个新的数组,所以 callback 需要有 return 值,如果没有,会返回 undefined
-
箭头函数与普通函数的区别
- 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象
- 不可以当作构造函数,不可以使用 new 命令
- 不可以使用 argument 对象,可以用rest参数代替
- 不可以使用 yield 命令
-
同源策略
- 同源是指域名、协议、端口号相同
-
如何解决跨域
- jsonp跨域
- document.domain
- location.hash + iframe
- window.name + iframe
- postMessage
- CORS
- nginx代理跨域
- Vue插件设置跨域
- 后端在头部信息里设置安全域名与白名单
-
ES6 新增
- 新增模板字符串 反撇号(`)${}
- 箭头函数 =>
- for-of(用来遍历数据—例如数组中的值)
- 原生 Promise 对象
- let 和 const
- moudle 模块(export,import)
-
let 和 const 的区别是什么
- let 不存在变量提升
- 会形成封闭作用域
- 不允许重复声明
- const 定义常量,不能修改,如果定义是对象,可以修改对象内部数据
-
可能出现的内存泄露原因
- 全局变量
- dom 清空时还在引用
- 定时器未清除
-
script 引入方式
- html 静态 script 引入
- js 动态插入
- script defer :异步加载,元素解析完成后执行
- script async :异步加载,但执行时会阻塞元素渲染
-
数组方法
- map:遍历数组,返回新数组
- forEach:无法break:可以用try/catch 中 throw new Error 来停止
- filter:过滤
- join:通过连接符生成字符串
- push/pop:末尾推入弹出
- unshift/shift:头部推入和弹出,改变原数组,返回操作项
- sort/reverse:排序与反转,改变原数组
- concat:连接数组, 不影响原数组,浅拷贝
- slice:返回截取后的新数组,不改变原数组
- splice:返回删除元素组成的数组
- indexOf/lastIndexOf:查找数组项,返回对应下标
-
深浅拷贝
- 浅拷贝 object.assign
- 深拷贝 JSON.parse(JSON.stringify(object)) ,使用 while
-
异步编程的实现方式
- 回调函数
- 事件监听
- 发布/订阅(观察者模式)
- Promise 对象
- Generator 函数
- async/await
-
项目性能优化
- 减少请求
- 减少DNS查询
- 使用CDN(内容分发网络)
- 避免重定向
- 图片懒加载
- 减少DOM元素数量
- 减少DOM操作
- 使用外部JS与CSS
- 压缩JS,CSS,字体,图片等
- 优化CSS精灵图
- 使用iconfont
- 尽量减少iframe使用
- 避免图片src为空
- 把样式表放在link中
- 把script放在页面底部
-
作用域链是什么
- 每个函数都有一个作用域链,查找变量或者函数时,需要从局部作用域到全局作用域依次查找,这些作用域的集合称为作用域链
-
作用域是什么
- 规定变量和函数的可使用范围称为作用域
-
原型,原型链
- 原型:原型分为隐式原型和显示原型,每个对象都有一个隐式原型,它指向自己的构造函数的显式原型
- 原型链:多个 —proto- 组成的集合称为原型链
所有实例的 —proto- 都指向他们的构造函数的 prototype
所有的 prototype 都是对象,它的 -proto- 指向的 object 的 prototype
所有的构造函数的隐式原型指向的都是 Function() 的显示原型
object 的隐式原型是 null
-
JS垃圾回收方式
- 标记清除:当变量声明变量时,垃圾回收器进行标记,当变量离开环境时,再度标记进行删除
- 引用计数:会引起内存泄露,它的机制就是跟踪某一个值得引用次数,当声明一个变量并且将一个引用类型赋值给变量得时候引用次数加1,当这个变量指向其他一个时引用次数减1,当为0时出发回收机制进行回收。
-
继承的几种方式
- 原型继承:把父类的实例作为子类的原型;缺点:子类的实例共享了父类构造函数的引用属性,不能传参
- 组合继承:调用了两次父类的构造函数,造成不必要的消耗,父类方法可复用,可传承,不共享父类引用属性
- 寄生组合继承
- extend:ES6的新语法,寄生组合继承的语法糖
VUE
-
优点
- 轻量级
- 速度快
- 简单易学
- 低耦合
- 可重用性
- 独立开发
- 文档齐全
-
组件传递
- 父向子:props
- 子向父:$emit
- eventBus
- vuex
-
v-show 与 v-if 的相同点与不同点
- 相同点:都可以控制dom的显示与隐藏
- 不同点:v-show 只是改变 display 属性,dom元素并未消失,切换时不需要重新渲染页面,v-if 直接将dom元素从页面删除,再次切换需要重新渲染页面
-
keep-alive 的作用是什么
- 主要是用于需要频繁切换的组件时进行缓存,不需要重新渲染页面
-
computed 和 watch 的使用场景
- 多条数据影响一条数据使用计算属性,例如场景购物车
- 一条数据影响多条数据使用 watch,例如场景搜索框
-
Vue怎么实现双向数据绑定
- 通过数据的劫持,组合,发布订阅模式来实现
- 核心是 Object.defineProperty() 方法,Vue3更改为 proxy
-
父子组件的生命周期
- 父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted
- 父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
- 父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
-
VUEX 有哪几种属性
- state: 基本数据池
- getters: 基本数据派生出来的数据
- mutations: 提交更改数据的方法,同步
- actions: 装饰器,包裹 mutations,可以异步
- moudles: 模块化Vuex
HTML
-
盒模型
- margin padding border content
- 标准盒模型与IE盒模型
-
本地存储
- localStorage
生命周期:关闭浏览器一直保留,除非手动清除
作用域:相同浏览器的不同标签在同源情况下可以共享 - sessionStorage
生命周期:关闭浏览器或标签后失效
作用域:只在当前标签可用,当前标签所在的窗口同源可以共享 - cookie
大小只有4K
用来储存用户信息
可以设置过期时间且清除只能靠设置过期时间
- localStorage
-
浏览器内核
- Trident内核 - IE
- Gecko内核 - firefox
- webkit内核 - 老谷歌,Safari
- Presto内核 - Opera
- Blink内核 - 新谷歌
-
浏览器输入URL到网页显示的过程
- 域名解析
- 发起TCP三次握手
- 建立TCP连接之后发起http请求
- 服务器端响应http请求,浏览器得到HTML代码
- 浏览器解析HTML代码,并请求HTML代码中的资源
- 浏览器对页面进行渲染呈现给用户
-
网站性能优化
- 减少HTTP请求
- 减少DNS查询
- 减少DOM元素数量
- 使用CDN
- 配置Etag
- Gzip压缩
- 减少cookie大小
- 将样式放到页面顶部
- 将脚本放到页面底部
- 从外部引入js与css
- 减少DOM访问
- 使用精灵图
-
安全性问题
- XSS攻击:cookie 设置 httpOnly
- CSRF:跨站请求伪造,get不修改数据,设置白名单,请求校验
- XSS脚本注入:向页面注入脚本,对用户输入的数据进行编码
- CSRF跨域请求伪造:在未退出A网站的前提下访问B网站,B使用A的cookie去访问服务器,每次提交表单带上token,token不合法则拒绝
- SQL注入
- 失效的身份认证
- 敏感数据泄露
- XML外部实体
- 失效的访问控制
- 安全配置错误
- XSS
- 不安全的反序列化
- 使用含有漏洞的插件
- 不足的日志监控
CSS
-
响应式布局
- 媒体查询@media
- flex弹性布局
- 百分比单位
- rem
- VH,HW
-
回流与重绘
- 当一个元素自身的宽高,布局,显示或隐藏,或元素内部的文字结构发生变化,导致需要重新构建页面的时候,就产生了回流
- 当一个元素自身的宽高,布局,及显示或隐藏没有改变,而只是改变了元素的外观风格的时候,就产生了重绘
-
行内元素与块级元素
- inline 行内元素:span input img textarea label select
- block 块级元素: p h1-h5 div ul li table
uni-app
-
应用生命周期
- onLaunch 初始化完成时触发
- onShow 从后台进入前台显示
- onHide 从前台进入后台
- onError 报错时触发
- onUniNViewMessage 对 nvue 页面发送的数据进行监听
- onUnhandledRejection 对未处理的 Promise 拒绝事件监听函数
- onPageNotFound 页面不存在监听函数
- onThemeChange 监听系统主题变化
-
页面生命周期
- onLoad 监听页面加载
- onShow 监听页面显示
- onReady 监听页面初次渲染完成
- onHide 监听页面隐藏
- onUnload 监听页面卸载
- onResize 监听窗口尺寸变化
- onPullDownRefresh 监听用户下拉动作
- onReachBottom 页面滚动到底部的事件
- onTabItemTap 点击 tab 时触发
- onShareAppMessage 用户点击右上角分享
- onPageScroll 监听页面滚动
- onNavigationBarButtonTap 监听原生标题栏按钮点击事件
- onBackPress 监听页面返回
- onNavigationBarSearchInputChanged 监听原生标题栏搜索输入框输入内容变化事件
- onNavigationBarSearchInputConfirmed 监听原生标题栏搜索输入框搜索事件,用户点击软键盘上的“搜索”按钮时触发
- onNavigationBarSearchInputClicked 监听原生标题栏搜索输入框点击事件
- onShareTimeline 监听用户点击右上角转发到朋友圈
- onAddToFavorites 监听用户点击右上角收藏
WEBPACK
- entry 入口文件
- output 输出文件
- 一般配合node的path模块使用
- mode 设计模式
- module(loader)
- rules 转换规则
- use 加载模式,从上到下执行
- plugin 插件配置
- devServer 热更新
- resolve 配置路径规则
- alias 别名
- babel ES6转ES5
高端题
-
类型转换
- 为什么0.2+0.1>0.3?因为在JS中,浮点数是使用64位固定长度来表示的
- 0.3+0.2=0.5
-
判断数据类型的几种方法
- typeof typeof null 为 object,无法进行分辨
- instanceof 只能判断对象是否存在于原型链上
- constructor
- Object.prototype.toString.call()
-
为什么要模块化
- 防止命名冲突
- 更好的分离,按需加载
- 更好的复用性
- 更好的维护性
-
状态码
- 2表示成功 200
- 3表示重定向
301永久重定向
302临时重定向
304协商缓存 - 4表示客户端错误
403 跨域
404 资源不存在 - 5表示服务端错误
500
-
网络七层模型
- 应用层
- 表示层
- 会话层
- 传输层
- 网络层
- 数据链路层
- 物理层
-
Get 与 Post 的区别
- 幂等/不幂等
get 请求是幂等可以缓存的
post 请求是不幂等不可缓存的 - 传参
get 传参是在URL中的
post 传参是在请求体中的 - 安全性
get 较不安全
post 较为安全 - 参数长度
get 长度有限较小
post 长度不受限制
- 幂等/不幂等
-
tcp 与 udp 的区别
- 连接方面
tcp 需要三次握手四次挥手进行连接
udp 不需要进行连接 - 可靠性
tcp 是可靠传输:一旦传输过程中丢包会进行重新传
udp 是不可靠传输:会尽最大努力交付 - 工作效率
udp 实时性高,工作效率高,不需要握手及算法 - 连接环境
tcp 是点对点
udp 支持一对一,一对多,多对多 - 首部大小
tcp 占20字节
udp 占8字节 - 使用场景
tcp 正常请求,消息传输
udp 视频推拉流
- 连接方面
-
重点----从浏览器输入url后都经历了什么
- 先进行DNS域名解析,先查看本地hosts文件,查看有没有当前域名对应的ip地址,若有直接发起请求,没有的话会在本地域名服务器去查找,该查找属于递归查找,如果本地域名服务器没查找到,会从根域名服务器查找,该过程属于迭代查找,根域名会告诉你从哪个与服务器查找,最后查找到对应的ip地址后把对应规则保存到本地的hosts文件中。
- 如果想加速以上及之后的http请求过程的话可以使用缓存服务器CDN,CDN过程如下:
用户输入url地址后,本地DNS会解析url地址,不过会把最终解析权交给CNAME指向的CDN的DNS服务器
CDN的DNS服务器会返回给浏览器一个全局负载均衡IP
用户会根据全局负载均衡IP去请求全局负载均衡服务器
全局负载均衡服务器会根据用户的IP地址,url地址,会告诉用户一个区域负载均衡设备,让用户去请求它。
区域负载均衡服务器会为用户选择一个离用户较近的最优的缓存服务器,并把ip地址给到用户
用户想缓存服务器发送请求,如果请求不到想要的资源的话,会一层层向上一级查找,知道查找到为止。 - 进行http请求,三次握手四次挥手建立断开连接
- 服务器处理,可能返回304也可能返回200
返回304说明客户端缓存可用,直接使用客户端缓存即可,该过程属于协商缓存
返回200的话会同时返回对应的数据 - 客户端自上而下执行代码
其中遇到CSS加载的时候,CSS不会阻塞DOM树的解析,但是会阻塞DOM树的渲染,并且CSS会阻塞下面的JS的执行
然后是JS加载,JS加载会影响DOM的解析,之所以会影响,是因为JS可能会删除添加节点,如果先解析后加载的话,DOM树还得重新解析,性能比较差。如果不想阻塞DOM树的解析的话,可以给script添加一个defer或者async的标签。
defer:不会阻塞DOM解析,等DOM解析完之后在运行,在DOMContentloaed之前
async: 不会阻塞DOM解析,等该资源下载完成之后立刻运行
进行DOM渲染和Render树渲染
获取html并解析为Dom树
解析css并形成一个cssom(css树)
将cssom和dom合并成渲染树(render树)
进行布局(layout)
进行绘制(painting)
回流重绘
回流必将引起重绘,重绘不一定引起回流
-
防抖与节流
- 防抖:n秒后在执行该事件,若在n秒内被重复触发,则重新计时
- 节流:n秒内只运行一次,若在n秒内重复触发,只有一次生效
-
JS常见的设计模式
- 单例模式
- 工厂模式
- 构造函数模式
- 发布订阅者模式
- 代理模式
- 迭代器模式
-
JS性能优化方式
- 垃圾回收
- 闭包对象写清楚
- 防抖节流
- 分批加载
- 事件委托
- 少用with
- requestAnimationFrame的使用
- script标签中的defer和async
- CDN
算法
-
冒泡排序
- 比较相邻的两个元素大小,如果前一个比后面大则交换位置
- 第一次循环后最后一个元素应该是最大的一个
-
快速排序
- 第一趟排序时将数据分成两部分,一部分比另一部分的所有数据要小
- 递归在两边实行快速排序
-
插入排序
- 默认第一个排好序了
- 如果后面小于前面的直接把后面的插到前边正确位置
-
是否回文
- split reverse join
-
斐波那契数列:使用递归
-
数组去重—重点
- 双重循环
- 基于对象去重
- 利用Set,[…new Set(arr)]
- 利用reduce 循环的一种
RiverGod-致力于每一个还有梦想的前端小白