CSS
1、css的常见单位有什么,区别是啥?
px像素vw相对于视口的宽度,视口被均分为100单位的vwvh相对于视口的高度,视口被均分为100单位的vh.em相对长度单位。 相对于自身的font-size大小,如果没有设置的话,font-size是可以继承的。rem是一个相对单位(root em, 根em),只相对于html根元素的font-size大小;vmax取视口宽度或高度中最大的那一边,将最大的那一边分成100份vmin取视口宽度或高度中最小的那一边,将最小的那一边分成100份
2、CSS如何实现居中,大概有4-5种?
<div id="father">
<div id="son"></div>
</div>
/* flex 方式 */
<style>
#father{
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
#son {
width: 100px;
height: 100px;
background-color: aqua;
}
</style>
/* 定位 移动 */
<style>
#father {
width: 100vw;
height: 100vh;
position: relative;
}
#son {
width: 100px;
height: 100px;
background-color: aquamarine;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
</style>
/* margin */
<style>
#father {
width: 100vw;
height: 100vh;
position: relative;
}
#son {
width: 100px;
height: 100px;
background-color: aquamarine;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
margin:auto;
}
</style>
/* position + margin 负边距 */
<style>
#father {
width: 100vw;
height: 100vh;
position: relative;
}
#son {
width: 100px;
height: 100px;
background-color: aquamarine;
position: absolute;
left: 50%;
top: 50%;
margin-left: -50px;
margin-top: -50px;
}
</style>
3、CSS如何实现三角形?
<div id="tr"></div>
// 普通三角形
<style>
#tr {
width: 0px;
height: 0px;
border: 100px solid transparent;
border-left-color: green;
}
</style>
//直角三角形
<style>
#tr {
width: 0px;
height: 0px;
border-top: 100px solid black;
border-left: 100px solid transparent;
}
</style>
4、什么是重绘 重排(回流),那些因素会引起重绘重排?
重排一定会引起重绘,重绘不一定会引起重排
重排定义:渲染树中部分或全部元素的尺寸,结构或属性发生变化时,浏览器会重新渲染部分或全部的文档,导致周围Dom元素重新排列引发重排的因素:浏览器的首次渲染,页面的窗口大小、元素位置、元素尺寸、元素内容、字体大小发生变化,激活CSS伪类,或者新增或删除可见的Dom元素,会发生重排
重绘定义:页面中某些元素的样式发生变化,但不会影响其再文档流中的位置,浏览器会对元素进行重新绘制引发重绘的因素:color、background相关属性、outline相关属性、border-radius、visibility、box-shadow,这类样式发生变化的时候,会发生重绘。
避免重绘重排- 操作Dom时,尽量在低层级的Dom节点进行操作
- 不要使用table布局
- 使用CSS表达式
- 不要频繁操作元素的样式
- 使用absolute或fixed,使元素脱离文档流,这样他们发生变化,就不会影响其他元素
- 使用display:none,操作结束后,将它显示出来
- 将Dom的多个读操作/写操作放在一起,而不是读写穿插
5、如何做页面的主题切换?
JavaScript
1、数组的方法中,那些可以做迭代?
map迭代数组每一项,可以给特定条件返回重新组成的新数组every迭代数组每一项,每项都符合条件才返回true,反之返回falsesome迭代数组每一项,只有一项符合条件就返回true,如果全部不符合才返回falsefilter地带数组每一项,可以添加特定的条件过筛选,返回筛选后的新数组forEach迭代数组每一项,返回undefined
2、给定字符串,提取字符串中的数字,并组成数组?
// 不考虑小数
const str = 'd,2f21f-kj231a'
str.match(/\d+/g) //['2','21','231']
// 考虑小数
const strport = 'a.23,q21.3qw2.1a'
strport.match(/-?([1-9]\d*(\.\d*)*|0\.[1-9]\d*)/g) // ['23', '21.3', '2.1']
3、两个数组如何取交集?
const arr1 = [1,2,34,51,3]
const arr2 = [3,2,1,42,54]
const arr3 = arr2.filter(item => arr1.includes(item))
console.log(arr3); // [3, 2, 1]
4、深拷贝和浅拷贝,手写深拷贝?
深拷贝和浅拷贝主要是针对引用数据类型
的。
- 深拷贝会将整个拷贝目标复制一份。
- 浅拷贝只是复制拷贝目标的引用地址。
// 深拷贝的实现方式
// 1、JSON方式
const obj = { a: 1, b: { ba: 11, bb: 12 } };
const arr = [1, { a: 1, b: 2 }, 3]
const cloneDeepObj = JSON.parse(JSON.stringify(obj))
// 2、lodash
const cloneDeepObj1 = _.cloneDeep(obj)
// 3、**手写递归**
const handObj = { a: 1, b: { ba: 11, bb: 12 }, c: [1, 2, 3] };
const cloneDeepFun = (obj) => {
let cloneObj = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj[key] instanceof Object) {
cloneObj[key] = cloneDeepFun(obj[key])
} else {
cloneObj[key] = obj[key]
}
}
return cloneObj
}
// 浅拷贝的实现方式
// 1、直接赋值
const cloneObj = obj;
// 2、展开运算符
const cloneObj1 = {...obj}
// 3、Object 方法
const cloneObj2 = Object.assign({},obj)
//4、concat
const cloneArr = [].concat(arr)
5、谈谈原型、原型链?
原型
- 所有的对象,都可以理解为是用
new 函数创建的,所有的函数,也是对象(函数中有属性) - 所有函数都有个属性:
prototype,称为函数原型,默认情况下,prototype是一个Object对象,prototype中有一个属性constructor,是一个对象,它指向构造函数本身。 - 所有的对象都一个属性:
__proto__,称为隐式原型 - 默认情况下
实例对象.__proto__ = 函数.prototype - 使用
- 我们可以在函数原型中加入属性/方法,以增强其对象的功能,但是会导致原型污染。
原型链
- 当访问一个对象成员时:
- 查找对象自身是否拥有该成员,如果有,直接使用
- 查找该对象的隐式原型是否拥有该成员,如果有,直接使用
- 根据原型链依次查找
Tip
- Function的__proto__指向自身的prototype
- Object的prototype的__proto__指向null
6、讲下事件循环?
传送门🚪
JS代码在运行时,
- 任务被分为
宏任务(MacroTask/Task)和微任务(MircoTask) - 任务队列也被分为
宏任务队列(Task Queue)和微任务队列(MircoTak Queue),遵从先进先出原则 微任务: Promise中的then、catch、finally- MutationObserver(监视 DOM 变动的API,详情参考MDN)
- Process.nextTick(Node环境,通常也被认为是微任务)
宏任务:
除去
微任务的所有任务都归为宏任务 - 网络请求
- 定时器相关
- script的所有代码
- ...
React
1、React的diff算法,谈谈你的理解?
2、setState是同步还是异步的?
- setState本身并不是异步,只是因为react的性能优化机制体现为异步。在react的生命周期函数或者作用域下为异步,在原生的环境下为同步
- 原生的环境:在DOM上绑定原生事件,setTimeOut,setInterval
3、都用过那些React Hook?
-
useState在函数组件中声明状态(state) -
useEffect在函数组件中执行副作用操作副作用数据获取,设置订阅以及手动更改 React 组件中的 DOMuseEffect可以看作是componentDidMount,componentDidUpdate和componentWillUnmount这三个函数的组合- 默认情况下(只有一个参数的情况下),它在第一次渲染之后和每次更新之后都会执行。相当于在componentDidMount和componentDidUpdate中执行相同的代码
useEffect(() => { document.title = `You clicked ${count} times`; });- 第二个参数传递一个
[]时,相当于componentDidMount,它将只执行一次useEffect中的副作用 - 第二个参数传递一个
有依赖项的[]时,会在依赖项变化时,去执行useEffect中的副作用。相当于下方代码
// hook,count变化时,去重新设置title useEffect(() => { document.title = `You clicked ${count} times`; },[count]); //class组件的生命周期函数 componentDidUpdate(prevProps, prevState) { if (prevState.count !== this.state.count) { document.title = `You clicked ${this.state.count} times`; } }- 如果需要清除useEffect中的副作用,需要在useEffect中返回一个清除函数,这样当组件卸载的时候或者重新渲染时,会自动执行这个清除函数
useEffect(() => { const timer = setInterval(() => { console.log('some....'); }, 100); // 组件卸载或者重新渲染时自动执行下方代码 return () => { clearInterval(timer) } }); -
useRef- 访问DOM对象的一种方式,而且无论节点如何改变,React都会将ref对象的.current属性设置为响应的DOM节点
-
useContext- 用于实现简单的传值问题
const testData = { id:1, name:2 } //创建Context const TestContext = React.createContext(testData); //上层组件 function App() { return ( <div className="App"> <TestContext.Provider value={testData}> <Sub /> </TestContext.Provider> </div> ); //下层组件 const Sub = () => { const data = useContext(TestContext); return <>{data.name}</>; }; -
useReducer- useState的替代方案,如果默认值是对象的话,useReducer比useState更合适,使用起来比较像redux
const initialState = {count: 0}; function reducer(state, action) { switch (action.type) { case 'increment': return {count: state.count + 1}; case 'decrement': return {count: state.count - 1}; default: throw new Error(); } } function Counter() { const [state, dispatch] = useReducer(reducer, initialState); return ( <> Count: {state.count} <button onClick={() => dispatch({type: 'decrement'})}>-</button> <button onClick={() => dispatch({type: 'increment'})}>+</button> </> ); } -
useCallback- 用于做性能优化时使用的hook
- 当依赖项改变的时候才去执行内部的回调函数
const memoizedCallback = useCallback( () => { doSomething(a, b); }, [a, b], ); -
useMemo- 用于做性能优化的hook
- 会在渲染期间执行
- 当依赖项改变的时候才去重新计算
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
4、setState可以在没有第二个参数的useEffect中使用吗?
不可以
- 如果setState(12)的是简单数据类型,该state的状态将永远保持为setState(12)的值
- 如果setState({})的是引用数据类型,页面会直接崩溃
TypeScript
1、TS中type和interface的异同?
interface侧重于描述数据结构,type侧重于描述类型- 都可以描述对象或者函数
- 都可以使用extends进行组合
type特有联合类型
type Res = Array | String
2、TS中什么是元组?
- 任意类型,但是长度有限的数组
const tuple:[string,number] = ['tuple',123]
// react 中的useState的返回值就是一个元组
const [state,setState] = useState(0)