Object.defineProperty
可以实现创建特定属性:
- enumerable 是否可枚举
- writable 是否可重写
- value 写入的值
- configurable 是否可配置
盒模型
- content-box 怪异盒子,border和padding在盒子外面
- border-box 标准盒子,border和padding算在盒子内
隐式类型转换
内部封装有valueOf()和toString()
实际的逻辑是,先判断两个数本身的值能否做一个运算判断,如果不能就全部转为String再判断,更细节上的toString函数会先判断对比的值是否是基础数据类型,如果是对象类型根据实际情况会把对象转化为[Object Object]字符串。
内存泄漏
变量内存一直在浏览器中无法释放导致内存空间浪费的现象叫做内存泄漏。
一般来说变量有两种清理内存的方案:
- 计数清理->构建外部引用数量,引用减少则减一,但是无法应对循环引用;
- 标记清除->将引用标记标记到外部整体对象上,也就是如果obj的a属性引用b,b属性引用a就会标记在obj上,解决循环应用。
可能造成内存泄漏:
- 全局变量
- 定时器不清除
- 闭包滥用
解决方法:
- 使用完后clear定时器
- 使用let和const关键字
怎么查看是否内存泄漏?
- 浏览器快照,打开浏览器的控制台的memory打一个不同时间点的快照,查看内存变化情况。同理,如果出现了一些内存相关的错误,比如栈溢出都可以查看内存快照,以快速定位。
css的transform属性
translate 平移:
- translateX 水平轴平移
- translateY 垂直轴平移
rotate 旋转:
- 接收xxdeg参数,表示旋转多少度。
scale 缩放:
- 表示水平垂直方向上缩放多少倍
skew 倾斜:
- xxdeg yydeg水平和垂直倾斜多少度
margin
.class{
margin: 10px 2px 30px 4px;
}
逆时针:上右下左的顺序
pageX,clientX,getBoundingClientRect().left的区别
pageX 鼠标事件方法,指的是和浏览器的最左边和最上面的距离,但是受到scroll滚动的影响,会计算滚动隐藏的宽高
clientX 鼠标事件方法,指的是和浏览器的最左边和最上面的距离,不受到scoll滚动的影响,不会计算滚动隐藏的宽高
ele.getBoundingClientRect().left DOM元素方法,和pageX一样是最左边和最上面,并且受Scoll影响
Set和Map、WeakMap和WeakSet
Set能够保持存入数据的唯一性,Map使用键值对存储。
Set是无序存储,也就是不保证存入的数据按照存储顺序输出,Map可使用键值对进行排序实现顺序存储。但是在某些JS引擎下,为了提高效率会内部对Set进行改造,实现顺序存储。
WeakMap和WeakSet存储的是引用对象,也就是浅拷贝的那层,在循环引用下,它会被垃圾回收机制回收掉
Symbol
- 唯一性
- 无法被枚举
- 可以作为对象属性,并且属性唯一,Symbol会遍历obj的所有属性,然后随机生成一个和当前所有属性都不相同的值。
const s = new Symbol()
let obj = {
attr1:s,//创建s属性值
attr2:"a"
}
const uniqueKey = new Symbol()
let obj1 = {
[uniqueKey]:"私有Symbol属性"
}
const uniqueKey2 = new Symbol()
class Obj_{
constructor(data){
this.data = data
}
[Symbol.iterator](){
let index = 0
let data_ = this.data
return {
next(){
if(index<data_.length){
return {
value:data_[index++],
done:false
}
}else{
return {
done:true
}
}
}
}
}
}
Symbol一般用于创建私有变量,保证数据的安全性和唯一性,实现迭代器,避免命名冲突等等场景
@import和link的区别
可以通过这两种方式引入css文件:
- link一般用于在html网页中引入css文件
- @import一般用于css文件中引入另一个css文件
preload和prefetch
- preload主要用于对于一些文件在页面渲染之前需要加载该必要文件
- prefetch主要用于对于后续文件需要用的资源的预加载请求,也就是浏览器可以在空闲的中间加载该资源
css前缀
- webkit chrome和苹果浏览器使用
- moz 火狐
- ms IE浏览器
NodeJS相对于JAVA等服务器的优点
- 异步的处理机制使得NodeJS在处理高并发I/O上的优越性,常应用于实时通讯等项目中
- 轻量化的后端环境,使得搭建成本很低,能够做到快速启动
- 前后端语言的一致性
- 使得服务器端可以实现SSR机制
requestAnimationFrame的优越性
requestAnimationFrame是浏览器的一个API,能够实现浏览器自动按照最佳的时机执行动画,实现性能优化,一般都是在页面绘制前执行动画。 同时减少CPU占用,因为它会在浏览器的绘制周期内执行,而setTimeout等方法不会。 当页面切换到后台时,它会自动停止一个更新,但是setTimeout等方法不会。 同时和CSS动画结合很好,可以实现更加复杂的动画效果。
如何定位错误
如果线上的项目出现了问题,怎么定位错误?
-
首先,是哪里出现的错误,如果是测试的过程中发现了错误,先确定是单测试的环境下出现这个问题还是所有环境下都出现了这个问题?
- 研发可以在自己的本地和线上环境都进行一下测试看是否都出现了问题。
- 如果都出现了问题说明是代码的问题,如果是只在测试所在的那个环境下出现了该问题,可能是兼容性或者是网络等的问题.
- 可以询问测试的网络以及所使用的浏览器的版本等信息,复现相关场景排查究竟是网络还是浏览器兼容性等问题。
- 如果是浏览器兼容性的问题,则考虑做一个兼容性处理,比如css可以添加不同前缀的版本编码。
-
如果是所有环境下都出现了这个问题,说明项目代码可能出现了一个问题,可以通过:
- 前后端请求的一个状态码初步判断是前端的请求问题还是后端服务器的问题,比如404或者500,一般后端错误都会显示有500之类的状态码提示
- 可以通过前端浏览器的控制台看是否有报错信息,如果是前端错误一般控制台会有一些报错信息
- 如果前后端代码分离,可以使用Postman等工具测试是否能正常获得后端请求,如果能说明是前端错误。
-
如果该项目是已经上线的项目出现了类似的错误,那么一般都会有埋点等机制,可以从错误日志系统查看相应的报错信息得知相关的错误
-
如果是怀疑是内存泄漏或者循环栈溢出等问题,可以去浏览器的控制台的memory去打两个快照,观看前后的一个内存的变化情况,如果内存占用不合理大概率是栈溢出,如果是两个时间的中函数的内存占用没有任何变化,有可能没清理定时器或者闭包等文件。
-
如果是首屏加载过慢等问题,可以查看浏览器的网络一栏,看加载文件所需的时间,以及各个文件加载需要的时间,如果是某个文件加载时间过长,可以考虑gzip压缩等方法
如何替换掉上线的错误文件
- 备份旧文件
- 准备新文件
- 使用相应的Git等版本控制软件进行代码管理,方便出现意外的版本回滚
- 替换相应文件
- 进行浏览器原始文件的缓存清除
- 携带一些header等指令实现强制对比文件的内容,如果文件内容不一样,强制刷新页面;或者弹框要求用户刷新。
css的flex布局
- flex:1 - flex-shrink:1+flex-glow:1+flex-basis:auto
- flex:wrap 换行
- justify-content 水平排列 参数center space-between
- align-items 垂直排列 参数center space-between
- flex-direction flex布局的方向,可选row或者column
前端工程化的理解
- 模块化开发-以方便代码的复用与维护
- 使用版本控制工具GIT,方便版本管理、代码管理与版本回溯
- 利用Webpack或者Vite等专业代码打包工具
- 利用npm等yarn等包管理工具(yarn是并行安装+缓存策略+离线安装-速度快-多用于大型项目,npm是一个一个安装-NodeJS官方支持-兼容性更好)
- 使用ESlint等代码检测工具,使用TypeScript进行代码合作
- 集成CI/CD,使用自动化持续集成和部署工具
- 使用Postman等测试接口,实现前后端分离。方便后续代码问题排查。
- 团队具有代码部署日志文档,建立埋点机制,和完善的错误日志。
如果服务器的数据进行了更新,怎么让用户的页面随之立马更新
- 看情况进行决定,WebSocket、长轮询或者SSE等方案都可以实现实时的监听与更新
- 如果是需要用户手动下载更新则可以进行弹窗提示,不然禁止使用该网页,将网页的部分内容进行锁定禁用。
JS数据类型
基础数据类型:
string/number/null/undefined/symbol/boolean
引用数据类型:
object/array/date/function等等
String方法
- split 切割字符串
- join 拼接字符串
- trim 去除字符串两端空格
- replace 替换字符串中的字符
- lastIndexof 查找字符在字符串中的位置,如果字符串中不存在则返回-1
- indexOf 查找字符在字符串中第一次出现的位置,如果字符串中不存在则返回-1
- toUpperCase 转化为大写字符
- toLowerCase 转化为小写字符
- match 匹配
- substring 截取子串
Array方法
- push 末尾插入
- pop 末尾取出
- shift 对于开头的元素进行插入
- unshift 对于开头的元素进行取出
- forEach 遍历的方法
- map 对于数组内部的方法执行函数
- find 对于数组内的元素查找
- reduce 对于函数进行迭代函数执行
- slice 获取子数组
- splice 对于数组进行增删等操作
- includes 查找操作
- filter 过滤操作
- concate 拼接操作
- sort 排序
//对于数组为number进行sort数据
let arr = [1,2,3,4]
//升序
arr.sort((a,b)=>{
return a-b
})
//降序
arr.sort((a,b)=>{
return b-a
})
//对于数组为字符串根据字符在ASCII中的数值进行排序
let arr2 = ["a","b","c"]
arr2.sort((a,b)=>{
return a.localeCompare(b)
})
==和===和Object.is的区别
- == 是会存在一个隐式类型转换
- === 是会判断数据的类型和值是否都相同
- Object.is和===基本相同,但是有略微的区别在于判断Object.is(NaN,NaN)为true以及Object.is(+0,-0)为false,但是===的结果刚好相反
判断数组是否为空
let myarr = []
//方法1
if(myarr.length){/**/}
//方法2
if(lodash.isEmpty(myarr)){/**/}
判断对象是否为空
需要判断其属性是否空
- Object.keys(obj)获取其中的keys和values,确定keys的长度是否为空
- for in判断obj是否存在属性
对象拼接方案
- 通过解构运算符
let obj1 = {a:1,b:2}
let obj2 = {c:3,d:4}
let obj = {...obj1,...obj2}
- 通过object.assign
let obj = Object.assign({},obj1,obj2)
判断数据类型
- typeof 基础数据类型
- instanceof 引用数据类型
- constructor 构造器,但是在某些方式中可以修改构造器导致代码误判
- Object.prototype.toString.call 最为准确的方案
强缓存和协商缓存
之前一直理解错了。。。。。 无语
-
强缓存是一种和浏览器的缓存策略,它通过设置HTTP头来表示浏览器是否在一定的时间内直接使用本地缓存,而不需要再和服务器端进行通信。设置的HTTP头通常有Expires和Cache-control。强缓存通常适用于静态文件。
-
协商缓存也是一种缓存策略,它通过设置HTTP来表示浏览器是否的本地文件是否需要进行更新,需要和服务器端进行通信,通常适用于需要经常进行更改的文件。
css文档流
CSS 脱离文档流是指某个 HTML 元素不再按照默认的布局方式参与文档流中的位置计算,而是以一种特殊的方式进行定位或布局
脱离文档流的方式:
- position的几种方案都可以脱离文档流 absolute relative fixed
- float的几种方案right和left
- display:inline-block
- flex以及grid布局
bfc的理解
bfc指的是块状格式化上下文,也就是会将使用bfc的盒子内部的布局独立为一块区域,内部布局不会影响到盒子外部的样式。
常见的方式实现块状格式化上下文:
- overflow:hidden
- 给父元素设置浮动
- position absolute和relative
const关键字
const定义的数据会指向固定的内存区域,所以const定义的基础数据类型无法被重新赋值,在定义基础数据类型的时候如果不需要重新赋值最好使用const定义
但是const定义的引用数据类型可以重新赋值,只需要保持指向的内存地址不变就行