持续更新中...
记录一下面试被问到的技术问题,顺便回顾一下知识点。
由于是按面试顺序汇总,问题之间无相关性,就不做目录了,直接翻阅右下角的系统目录吧
>> 02.25 12:00 --------------------------------------------
vue和react中父子传值的方式
- vue:父向子传值props、子向父传值$emit
- react:props
react中父获取子组件中的方法
- 使用refs,他是使用 React.createRef() 创建的,并通过 ref 属性附加到 React 元素,再通过current来访问节点(或者使用回调的形式)
this.XXX = React.createRef()
this.XXX.current //节点
<Demo ref={this.XXX}></Demo>
//回调形式
<Demo ref={element => this.XXX = element}></Demo>
- 当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 接收底层 DOM 元素作为其 current 属性。
- 当 ref 属性用于自定义 class 组件时,ref 对象接收组件的挂载实例作为其 current 属性,这时就可以调用子组件的方法和属性,也是一种传值方式。
- 你不能在函数组件上使用 ref 属性,因为他们没有实例,但是可以再函数组件内部使用,只要它指向一个 DOM 元素或 class 组件。
- 【扩展】refs转发,使函数组件也能获取到ref
- 第二个参数 ref 只在使用 React.forwardRef 定义组件时存在
- 这种转发还经常用在高阶组件中,将ref传递到高阶组件返回的组件中
const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>
));
// 你可以直接获取 DOM button 的 ref:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;
key的作用
- 每个key对应一个组件,相同的key react认为是同一个组件,这样后续增加或删除或改变顺序时,相同的key对应组件都不会被重新创建,提升了性能
前端加密
- 参考
- 利用插件 js-md5
- base64加密 利用 window.btoa("XXX"); 编码;window.atob();解码
vue和react的区别
- 参考
- react整体是函数式的思想,把组件设计成纯组件,状态和逻辑通过参数传入,所以在react中,是单向数据流;vue则是响应式的,也就是基于是数据可变的,通过对每一个属性建立Watcher来监听,当属性变化的时候,响应式的更新对应的虚拟dom。
- react的思路是all in js,vue则是单文件组件,可以把html、css、js写到一个文件中,html提供了模板引擎来处理
浏览器存储方式及其不同
- 存储大小限制也不同,cookie数据不能超过4K,sessionStorage和localStorage可以达到5M
- sessionStorage:仅在当前浏览器窗口关闭之前有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,本地存储,因此用作持久数据;cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
- sessionStorage:不在不同的浏览器窗口中共享,即使是同一个页面;localstorage:在所有同源窗口中都是共享的;也就是说只要浏览器不关闭,数据仍然存在;cookie: 也是在所有同源窗口中都是共享的.也就是说只要浏览器不关闭,数据仍然存在
301 302 状态码是什么
- 状态码一般由3位构成: 1xx : 表示请求已经接受了,继续处理。 2xx : 表示请求已经处理掉了。 3xx : 重定向。 4xx : 一般表示客户端有错误,请求无法实现。 5xx : 一般为服务器端的错误。
- 常见的状态码
- 200 OK 客户端请求成功
- 301 Moved Permanently 请求永久重定向
- 302 Moved Temporarily 请求临时重定向
- 304 Not Modified 文件未修改,可以直接使用缓存的文件
- 403 Forbidden 服务器收到请求,但是拒绝提供服务。服务器通常会在响应正文中给出不提供服务的原因。
- 404 Not Found 请求的资源不存在,比如输入了错误的URL
- 500 Internal Server Error 服务器发生不可预期的错误,导致无法完成客户端的请求
componentWillRecieveProps 不再推荐?
- 以下生命周期钩子将在React17之后的版本中删除:componentWillMount、componentWillUpdate、componentWillRecieveProps,取而代之的是在16.3版本中带有UNSAFE_前缀的这三个钩子
- 新的生命周期:
- 挂载阶段:constructor() => render() => 更新DOM和refs => componentDidMount()
- 更新阶段:新的props、setState()、forceUpdate() => render() => 更新DOM和refs => componentDidUpdate()
- 卸载阶段:componentWillUnmount()
for 和 forEach 区别 哪个性能更优
- 个人认为 从日常业务开发中来说 for 性能更优 因为for可以使用 break 或者 continue 在适当的时机跳出 而 forEach 是没有办法的 看网上有人进行来性能测试 貌似同样的循环次数 也是for更优
vuex和redux区别
- 参考
- 改进了Redux中的Action和Reducer函数,以mutations变化函数取代Reducer, 无需switch,只需在对应的mutation函数里改变state值即可
- 由于Vue自动重新渲染的特性,无需订阅重新渲染函数,只要生成新的State即可
- Vuex数据流的顺序是:View调用store.commit提交对应的请求到Store中对应的mutation函数->store改变(vue检测到数据变化自动渲染)
箭头函数和普通函数区别
- 箭头函数是匿名函数,不能作为构造函数,不能使用new
- 箭头函数不绑定arguments,取而代之用rest参数...解决
- 箭头函数不绑定this,会捕获其所在的上下文的this值,作为自己的this值
Promise all 和 race 区别
- Promise.all() 处理多个异步Promise,全部成功才会进入then()
- Promise.race() 处理多个异步Promise,有一个成功来就会进入then()
setState 第二个参数用法
- 用于处理state更新成功之后的操作
react 更新 props的生命周期
- 更新阶段:新的props、setState()、forceUpdate() => render() => 更新DOM和refs => componentDidUpdate()
react router Link 和 a 有什么区别
- Link组件不会刷新页面,只会对变化的DOM进行渲染,a 会刷新页面 有一个视觉上的页面闪烁,会全部重新渲染 这很大程度的提高了性能
冒泡排序
- 它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
function bubbleSort(arr) {
var i = arr.length, j;
var tempExchangVal;
while (i > 0) {
for (j = 0; j < i - 1; j++) {
if (arr[j] > arr[j + 1]) {
tempExchangVal = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tempExchangVal;
}
}
i--;
}
return arr;
}
var arr = [3, 2, 4, 9, 1, 5, 7, 6, 8];
var arrSorted = bubbleSort(arr);
console.log(arrSorted);
alert(arrSorted);
深度优先和广度优先
- 参考
- 深度优先遍历就是一种不撞南墙不会头的算法,他会把一条路走完之后再回溯到有分叉的节点继续遍历
- 在广度优先搜索时,会从起点开始“一层一层”扩展的方法来遍历,扩展时每发现一个点就将这个点加入到队列,直到整张图都被遍历过位置。
css垂直居中的方法
- 参考
- 常用
- flex
- transform
- line-height
>> 02.21 15:04 --------------------------------------------
vue中computed和watch的区别
- computed 计算属性,对绑定到实例上的数据进行处理
- 基于它们的响应式依赖进行 缓存,只在相关响应式依赖发生改变时它们才会重新求值
- 无法处理异步操作
- 默认只要getter,也可以设置setter,接受设置的值为参数,当要设置计算属性时会调用setter
- watch 监听属性,当需要在数据变化时执行异步或开销较大的操作时使用
- 无缓存,只要监听的属性变化就会触发
- 可进行异步处理
- 接受两个参数,第一个是最新值,第二个是以前的值
- 还支持 deep 和 immediate 两个选项,deep 可发现对象内部值的变化;immediate 会立即执行一次
// 观察的属性名
person:{
handler(value){
alert("我的name是:"+value.name)
alert("我的age是:"+value.age)
},
deep:true
}
vue生命周期
- beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed
- ajax 请求一般在created中
vue更新机制原理
- 通过Object.defineProperty把data中的各数据属性改为访问器属性,来劫持每个属性的setter、getter;setter劫持到数据变化后,作为发布者 发布通知,订阅者们接到通知后更新数据。
vue双向绑定原理
- 采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。
<!--一个简单的用js实现双向绑定的例子-->
<html>
<body>
<div id="app">
<input type="text" id="txt"/>
<p id="show"></p>
</div>
</body>
<script type="text/javascript">
var obj = {}
Object.defineProperty(obj, 'txt', {
get: function(){
return obj
},
set: function(newVal){
document.getElementById('txt').value = newVal
document.getElementById('show').innerHTML = newVal
}
})
document.addEventListener('keyup', function(e){
obj.txt = e.target.value
})
</script>
</html>
vue父子组件传值有哪些方式
- 父向子传值:props
- 父向子传值:$parent(获取了父的实例)
- 子向父传值:$emit
- 子向父传值:$refs(获取了子的实例)
- 祖先向每个后代传值: provide/inject
provide: function () {
return {
getMap: this.getMap
}
}
inject: ['getMap']
- vuex
vuex的属性有哪些,如何改变state
- state、getters、mutaions、actions
- 可以在mutaions定义方法去更改state 或者 在actions中定义异步方法去执行mutations中的更改state的方法
this的指向有哪些
- 参考
- 谁最终调用函数,this指向谁,this指向的,永远只可能是对象
- 通过函数名()直接调用:this指向window
- 通过对象.函数名()调用的:this指向这个对象
- 函数作为数组的一个元素,通过数组下标调用的:this指向这个数组
- 函数作为window内置函数的回调函数调用:this指向window( setInterval setTimeout 等)
- 函数作为构造函数,用new关键字调用时:this指向新new出的对象
- 严格模式中的默认的this不再是window,而是undefined
ES6会常用到哪些特性
- 模版字符串、扩展运算符、数组中新增的各种方法、箭头函数、let、Promise、Module、Class
继承方式
- 原型链继承,一个类型A的原型对象是另一个类型B的实例,那么A就继承了B中原型对象的方法
- ES6的语法糖 Class extends
- 拷贝继承?
什么是闭包
- 函数内部可以调用外部的属性 这就形成了一个闭包,有内存泄漏隐患
- 闭包参考
- 闭包造成内存泄漏问题的解决办法
RN热更新
react-native-updatepushy账号
是否有接触过自动化部署
webpack了解多少
>> 02.19 18:06 --------------------------------------------
原生发一个ajax请求
- 创建异步对象
var xhr = new XMLHttpRequest(); - 设置请求行 open(请求方式,请求url)
xhr.open("get","validate.php?username="+name) - 设置请求(GET方式忽略此步骤)头:setRequestHeader()
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); - 设置请求体 send()
xhr.send(null) 或 xhr.send("username="+name); - 让异步对象接收服务器的响应数据
xhr.onreadystatechange = function(){
if(xhr.status == 200 && xhr.readyState == 4){
console.log(xhr.responseText);
}
}
- readyState
- 0: 请求未初始化
- 1: 服务器连接已建立
- 2: 请求已接收
- 3: 请求处理中
- 4: 请求已完成,且响应已就绪
浏览器敲回车到渲染整个页面的过程
- 读取缓存:搜索自身的 DNS 缓存。(如果 DNS 缓存中找到IP 地址就跳过了接下来查找 IP 地址步骤,直接访问该 IP 地址。)
- DNS 解析:将域名解析成 IP 地址
- TCP 连接:TCP 三次握手,简易描述三次握手
- 客户端:服务端你在么?
- 服务端:客户端我在,你要连接我么?
- 客户端:是的服务端,我要连接。
- 连接打通,可以开始请求了
- 发送 HTTP 请求
- 服务器处理请求并返回 HTTP 报文
- 浏览器解析渲染页面
- 断开连接:TCP 四次挥手
http和https的区别
- HTTPS协议可以理解为HTTP协议的升级,就是在HTTP的基础上增加了 数据加密。在数据进行传输之前,对数据进行加密,然后再发送到服务器。这样,就算数据被第三者所截获,但是由于数据是加密的,所以你的个人信息让然是安全的。这就是HTTP和HTTPS的最大区别。
闭包的应用场景
- 参考
- 原生的setTimeout传递的第一个函数不能带参数,通过闭包可以实现传参效果
- 函数防抖
- 封装私有变量
react 的事件和原生事件区别
- 参考
- React合成事件一套机制:React并不是将click事件直接绑定在dom上面,而是采用事件冒泡的形式冒泡到document上面,然后React将事件封装给正式的函数处理运行和处理。
>> 02.19 17:06 --------------------------------------------
箭头函数和普通函数的区别
- 箭头函数是匿名函数,不能作为构造函数,不能使用new
- 箭头函数不绑定arguments,取而代之用rest参数...解决
- 箭头函数不绑定this,会捕获其所在的上下文的this值,作为自己的this值
let和var的区别,什么时变量提升
- let、const不存在变量提升、不允许重复声明、块级作用域
- 变量提升:变量可以在声明之前使用,值为undefined
for in 和 for of 的区别 怎么避免原型链属性被遍历?
- for in 取 key; for of 取 value
- for of 无法遍历对象
- 一个数据结构只要部署了 Symbol.iterator 属性, 就被视为具有 iterator接口, 就可以使用 for of循环
Promise的用法
- new Promise((resolve, reject) => ...).then().catch()
setState时发生了什么
- 参考
- 可以接受一个对象或者一个函数(接受参数为前一个state和props),第二个参数是一个回调函数用于处理状态更新后的操作
- setState()方法通过一个队列机制实现state更新,当执行setState()的时候,会将需要更新的state合并之后放入状态队列,而不会立即更新this.state(可以和浏览器的事件队列类比)。如果我们不使用setState而是使用this.state.key来修改,将不会触发组件的re-render。
react hook的设计原由
- 参考
- 在组件之间复用状态逻辑很难
- 相互关联且需要对照修改的代码被进行了拆分,而完全不相关的代码却在同一个方法中组合在一起。如此很容易产生 bug,并且导致逻辑不一致。
react如何阻止状态更新
- 利用shouldComponentUpdate
react中key的作用 有相同key时怎么处理
- 有了key属性后,就可以与组件建立了一种对应关系,每个key 对应一个组件,相同的key react认为是同一个组件,这样后续相同的key对应组件都不会被创建
- 如果你选择不指定显式的 key 值,那么 React 将默认使用索引用作为列表项目的 key 值
react父子组件之间传递数据的方式
- props
- context
- redux
ts中函数默认值和可选参数
function buildName(firstName = "XXX", lastName?: string) {}
描述一下设计点赞组件的思路
>> 02.19 15:37 --------------------------------------------
let与var区别
- let、const不存在变量提升、不允许重复声明、块级作用域
浏览器存储
- sessionStorage:仅在当前浏览器窗口关闭之前有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,本地存储,因此用作持久数据;cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
React生命周期

项目迁移怎么考虑
- 参考
- 理清项目结构、页面结构、使用技术栈,规范代码。
组件式开发的见解
React Hook 版本
- @16.8
函数组件和Class组件的区别
- 函数组件没有状态、生命周期、this
pushy热更新
react-native-update
除了redux还了解过其他状态管理库吗?
- React 自带的 Context
- 参考
地图定点数据有很多时怎么处理?
- 分批渲染?
- 子线程?
antDesign 和 Bootstrap 的区别
- antDesign 组件库
- Bootstrap 样式库
>> 02.05 17:00 --------------------------------------------
this.$nextTick
- 参考
- 将回调延迟到下次 DOM 更新循环之后执行。状态改变后页面不会立即改变,而是等到下一次更新才会改变。
- 在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中
- 在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。
- 内部实现,先判断是否原生支持promise,如果支持,则利用promise来触发执行回调函数;否则,如果支持MutationObserver,则实例化一个观察者对象,观察文本节点发生变化时,触发执行所有回调函数;如果都不支持,则利用setTimeout设置延时为0。
<keep-alive>
- 参考
- 当组件在 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行
- 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在组件的父组件链中
- include - 字符串或正则表达式。只有名称匹配的组件会被缓存
- exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存
Promise.all()
- 只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数
- 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
- 如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法。
Vue 生命周期
- beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed
- ajax 请求一般在created中
sass Mixin 混合指令
- 定义可重复使用的样式,避免了使用无语意的 class
- @mixin 定义混合;@include 引用混合
原型链和闭包
- 原型链参考
- 一个类型的原型又是另一个类型的实例

- 闭包参考
- 闭包造成内存泄漏问题的解决办法
let、const、var 区别
- 参考
- let、const不存在变量提升、不允许重复声明、块级作用域
>> 02.06 14:00 --------------------------------------------
对象和数组的拼接
- 对象的拼接
- Object.assign(target, source) 将对象source合并到对象target中,target会被改变
- {...a, ...b}
- 数组的拼接
- Array.concat() 不会改变原数组
- [...a, ...b]