css
什么是盒模型
html元素由一个矩形框组成,即盒模型,
盒模型由这些部分组成:
- content box
- 显示内容的区域
- 通过width/height设置大小
- padding box
- 内边框,padding
- border box
- 边框,border
- margin box
- 外边框,margin
介绍一下css的2种盒模型
- box-sizing:content-box
- 标准盒模型
- 元素的宽度、高度只包括内容
- box-sizing:border-box
- IE盒模型
- 元素内容包括内边距和边框
link和@import的区别
- 导入方式不同
- link使用标签的方式
- @import是css的一种语法
- 使用范围不同
- link除了加载css样式,还能用于指定rel属性
- rel属性指定当前文档和被链接文档/资源之间的关系
- link除了加载css样式,还能用于指定rel属性
- 加载方式不同
- link方式:浏览器会一同加载html和css
- @import:浏览器会先加载html,再加载css
- 可以通过js操作dom,插入link
- @import支持ie5以上,link标签不存在兼容性问题
常用的布局方式
- flex布局
- grid网格布局
- 绝对定位布局
- 浮动布局
- 两栏布局
- 左侧宽度固定,右侧自适应
中间有间距,两边没有间距,怎么设置
- 使用flex横向布局,justify-content使用space-between
- 使用flex横向布局,设置flex:1自适应宽度,设置gap
- 左侧元素设置margin-right,右侧元素设置margin-left
position定位有哪些
- static
- top/right/bottom/left/z-index无效
- relative
- 相对于正常文档流的位置
- absolute
- 相对于最近的非static定位祖先元素
- fixed
- 相对于视口
- sticky
js
什么是变量提升
- 将所有var声明的变量和函数提升到代码的头部
- 函数声明的优先级高于变量声明
原型和原型链
- 什么是原型
- 在js中,每定义一个对象,对象中都会包含一些预定义的属性
- 每个函数对象上都有一个prototype属性,这个属性指向函数的原型对象
- 使用原型对象的好处是所有对象实例共享它包含的属性和方法
- 什么是原型链
- 每个对象都有一个原型对象,通过proto指针指向原型对象,并从中继承方法和属性
- 原型对象也可能拥有原型
- 这样一层一层,最终指向null,这种关系就是原型链
- 通过原型链一个对象可以拥有定义在其他对象中的属性和方法
防抖和节流
什么是节流防抖
- 当多次执行某一动作,进行函数调用次数的限制,节省资源
- 防抖
- 在事件触发n秒后执行函数,若在n秒内再次触发,重新计时
- 只有在最后一次事件之后才触发一次函数
- 节流
- 当多次执行某一动作,每隔一段时间,只执行一次函数
- 不管事件触发有多频繁,都能保证在规定时间内一定会执行一次时间处理函数
- 需要在用户触发页面滚动时,请求后台数据
- 应用场景
- 防抖
- 登录、发短信等按钮,防止用户按得太快
- 窗口大小resize事件,希望窗口调整结束后触发
- 鼠标的mousemove、mouseover事件
- 节流
- 列表滚动
- 搜索联想功能
- 表单重复提交
- 防抖
如何实现
- 防抖
1 | var timer; |
- 节流
1 | function debounce(fn,delay){ |
什么是闭包
- 内层函数访问外层函数作用域
结合闭包,说一下防抖是怎么实现的
- debounce函数接受两个参数
- 需要防抖的函数
- 延迟时间
- 使用闭包保存timer变量,确保每次调用返回的函数都能访问到同一个timer
- 每次事件触发,如果timer存在,则清除之前的定时器,设置一个新的定时器
- 延迟时间到达后,执行func函数
this的指向
面试官说,谁调用就指向谁
指向当前执行的上下文
调用模式
- 函数调用
- 方法调用
- 构造器调用
- apply/bind/call
怎么手动改变this
apply、bind、call
call、bind、apply的区别
- apply传参是数组,call是参数列表
- bind返回绑定this之后的函数,apply和call是立即执行
手写call
- 手写call
1 | Function.prototype.myCall = function(context, ...arg){ |
- 手写apply
1 | Function.prototype.apply = function(context,arg){ |
- 手写bind
1 | Function.prototype.myBind = function(context, ...firstarg){ |
箭头函数和普通函数区别
- 写法不同
- 箭头函数都是匿名函数
- 箭头函数不能用于构造函数
- 普通函数this指向调用对象,如果作为构造函数,this指向创建的实例
- 箭头函数的this永远指向上下文的this,并且无法改变
- 箭头函数没有arguments
react
react中性能优化有哪些方法
- React.memo
- react在组件刷新的时候会深度遍历所有子组件,查找所有更新节点,即父组件更新,子组件必会更新
- memo可以在某些情况下避免不必要的组件重新渲染,从而提高应用程序的性能
- 有2种用法
- 直接使用memo包裹组件
- 需要更加精确的控制组件重新渲染,可以传递第二个参数给memo来自定义比较函数,函数接收2个值,分别是前一次的props和当前的props,返回一个布尔值表示是否需要重新渲染组件
- 如果是class组件
- 一般使用shouldComponentUpdate函数或则PureComponent实现
- 列表使用key
- 为了提高diff算法在渲染列表时候的性能
- 有了它,react就能知道相比较上一个渲染周期,当前的渲染周期需要插入、移动或者删除哪些节点
- 复用之前的dom,减少不必要的dom操作所产生的开销,从而提高界面更新的性能
- 合理运用useCallback和useMemo
- useMemo和useCallback只针对重新渲染有帮助
- 需要结合父组件具体情况来看
- 使用懒加载和代码分割
- 使用React.lazy和Suspense,按需加载组件,可以减少初始化加载时间,提高性能
- 使用虚拟化
- 对长列表或大型数据集,使用虚拟化库,仅渲染可见部分
- react-virtualized
- 对长列表或大型数据集,使用虚拟化库,仅渲染可见部分
- 使用Profiler测量性能
useMemo和useEffect的区别
- 执行时机不同
- useMemo
- 会在渲染期间执行,memo在dom更新前触发
- useEffect
- 只能在dom更新后,浏览器渲染完成后再触发
- useMemo
useMemo的原理,为什么要用React.memo包裹起来
- react的渲染过程
- 触发渲染:props或者state发生变化时,react会重新渲染
- render方法:react调用组件的render方法,生成虚拟dom
- 比较虚拟dom
- 更新dom
- useMemo
- 作用:在渲染过程中缓存计算结果,以便在每次渲染时都重新计算
- 实现原理
- useMemo接收两个参数:callback和dependencies依赖数组
- 存储计算结果,和上一次的依赖数组
- 如果数组发生变化,重新计算并更新计算结果和依赖数组
- 如果没有变化,则直接返回上一次计算的结果
React中函数组件如何模仿生命周期(用useEffect)
- componentDidMount
- useEffect传入一个空数组
- componentDidUpdate
- useEffect传入第二个参数,用于监听依赖项的变化
- componentWillUnmount
- useEffect返回的函数会在组件卸载时执行
- shouldComponentUpdate
- 可以使用React.memo对props进行比较
jsx和js的区别
- 标签嵌套
- jsx允许在js中嵌套html标签
- 插值表达式
- jsx支持通过花括号将js表达式插入到jsx中
- 类名和属性命名不同,避免与js关键字冲突
- 使用className代替class
- 使用htmlFor代替for,
babel处理jsx的原理
- 解析
- 将jsx代码分解为标记,构建出一个对应的ast
- ast能够表示源代码的结构和语法
- 转换
- 将jsx语法转换为普通的js代码
- 将ast转换为js代码