前端面试题答案

217 阅读3分钟

咳咳,慢慢写,水平有限,如果哪里有问题麻烦指出,有什么比较有意思的面试题也欢迎大家留言

Vue双向绑定原理

这问题问的挺烂了,有的是想问底层,具体的就是vue2有两种情况下数据不会更新,为啥。还有一种是想问v-model怎么实现的,这个是想看看有没有封装过组件

简述下底层原理,双向绑定意思是dom变化更新data中的数据,data变化更新dom的显示

// 上一个极度精简版Vue3的代码
<input id="input"></input>
<div id="output"></div>
<script>
   const output = document.getElementById('output')
   const input = document.getElementById('input')
   const data = {
   	text: '123',
   }
   const dataProxy = new Proxy(data, {
   	get(target, prop) {
   		return Reflect.get(...arguments)
   	},
   	set(target, prop, value) {
   		console.log('触发proxy监听',target, prop, value)
           //正儿八经的话这应该是个事件,订阅/发布模式去更新dom
   		output.innerText = value
   	}
   })
   input.addEventListener('input',(evt)=>{
   	console.log('触发input事件')
       // 这步赋值会触发Proxy的set
   	dataProxy.text = evt.target.value
   })
</script>

给data套层Proxy的主要目的是为了添加set,其实就是监听数据变化,数去变化后再去更新dom,应该还会问下为什么vue3会换成Proxy,也就是为什么vue2新添加的属性和直接改变数组vue不更新

// 新添加属性
const obj = {
   test: 1,
};
// 只能劫持一个属性,相当于vue2是在初始化的时候把对象属性循环个编,然后每个属性套
//一个defineProperty,新添加的属性没有defineProperty,也就没法更新
Object.defineProperty(obj, 'test', {
   set: function() {},
   get: function() {},
});

// 直接更新数组,其实直接更新数组是可以监听到的,只不过尤大考虑性能问题,没做,
// 但是重写了数组api
function defineReactive(data, key, value) {
    Object.defineProperty(data, key, {
   	 get: function defineGet() {
   		 console.log(`get key: ${key} value: ${value}`)
   		 return value
   	 },
   	 set: function defineSet(newVal) {
   		 console.log(`set key: ${key} value: ${newVal}`)
   		 value = newVal
   	 }
    })
}

function observe(data) {
   Object.keys(data).forEach(function(key) {
   	defineReactive(data, key, data[key])
   })
}

let arr = [1, 2, 3]
observe(arr)
arr[2]=4 //这个会触发set,但是如果写arr[100] = 4无法触发,原因是初始时不存在所以劫持不到

Vue虚拟dom

先说下为什么需要虚拟dom,用js去一次次更新dom的性能成本会比较高,更新10次就要查10次dom节点,所以用js模拟一层dom,数据变化后先更新模拟出来的dom,模拟的dom可以去一次性的批量更新真实dom,应该还会问些关于虚拟dom的优化方法,以及可能会出现的bug,我只知道一个比较出名的bug,也就是为什么for循环不建议用index做索引

输入URL后到页面渲染,期间都发生了什么

这个可以夹杂各种优化问题,我会用黑体标出,先简述下主要过程

  • 输入URL后,交给浏览器的网络线程,网络进程可能会对输入的URL进行下加工。
  • 网络进程收到之后,先查缓存,有缓存的话就直接返回结果,没有的话,就发起正式的请求。
  • 请求先通过DNS找到要请求的服务器地址,DNS查询比较耗时,但是有浏览器和系统设置的DNS缓存,和dns Prefetch预解析,即如果网页中有URL,在渲染阶段就预先缓存DNS
  • 建立TCP/IP链接(IP负责定位是哪台机器,TCP负责建立稳定的持续链接),这边应该会问下三次握手四次挥手什么的,还有长链接,短链接,正常来说发送一次请求就会断掉,开启长链接后可以发送多个HTTP请求
  • TCP建立成功后,就开始HTTP请求
  • 服务器接收到请求,返回结果,顺带了解下各种响应状态码,
  • 浏览器渲染界面