美文网首页
JS面试题

JS面试题

作者: 我家有个王胖胖 | 来源:发表于2022-03-07 21:18 被阅读0次

一.一个完整的URL 解析过程
DNS解析过程
1 用户输入 URL 地址。
2 如果输入的是域名,对 URL 地址进行 DNS 域名解获得IP地址。
3 建立 TCP 连接(三次握手)。
4 浏览器向 web 服务器发送一个 HTTP 请求报文。
5 服务器返回 HTTP 响应报文给客户端。
6 关闭 TCP 连接(四次挥手)。
7 浏览器解析文档资源并渲染页面。
解析过程:浏览器解析的资源(html,svg,Xhtml等),解析完成后都会生成一个完整的DOM Tree ,css资源则会解析成CSS Rule Tree,生成之后进行浏览器渲染,保证脚本执行前已完成DOM渲染会放在body标签结束之后。

二.EventLoop机制:Event Loop即事件循环,是指浏览器或Node的一种解决javaScript单线程运行时不会阻塞的一种机制,也就是我们经常使用异步的原理。
为什么JS是单线程?
JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?产生了冲突。
单线程执行机制:
1)所有同步任务都在主线程上执行,形成一个[执行栈]execution context stack
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。
avaScript 把异步任务又做了进一步的划分,异步任务又分为两类,分别是:
① 宏任务(macrotask)

  • 异步 Ajax 请求、
  • setTimeout、setInterval、
  • 文件操作(I/O)
  • 其它宏任务

② 微任务(microtask)

  • Promise.then、.catch 和 .finally
  • process.nextTick
  • Object.observe
  • MutationObserver
  • 其它微任务

宏任务和微任务的执行顺序:

宏任务与微任务.png
  • 每一个宏任务执行完之后,都会检查是否存在待执行的微任务,
  • 如果有,则执行完所有微任务之后,再继续执行下一个宏任务。

注意:promise本身是同步的,promise的回调then是异步的。
三.MVC与MVVM的区别
3.1mvc


mvc
  1. View 传送指令到 Controller
  2. Controller 完成业务逻辑后,要求 Model 改变状态
  3. Model 将新的数据发送到 View,用户得到反馈

mvc中的所有通信都是单向的

3.2mvp
MVP 模式将 Controller 改名为 Presenter,同时改变了通信方向。

mvp

1. 各部分之间的通信,都是双向的。

2. View 与 Model 不发生联系,都通过 Presenter 传递。

3. View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。
3.3mvvm
MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。

mvvm

唯一的区别是,它采用双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之亦然。AngularEmber 都采用这种模式。

四:Vue数据双向绑定原理
①Vue2.X的双向绑定响应式原理
什么是响应式,也即是说,数据发生改变的时候,视图会重新渲染,匹配更新为最新的值。
Object.defineProperty 为对象中的每一个属性,设置 get 和 set 方法,每个声明的属性,都会有一个 专属的依赖收集器 subs,当页面使用到 某个属性时,触发 ObjectdefineProperty - get函数,页面的 watcher 就会被放到属性的依赖收集器 subs 中,在数据变化时,通知更新;
当数据改变的时候,会触发Object.defineProperty - set函数,数据会遍历自己的依赖收集器 subs,逐个通知 watcher,视图开始更新;

②Vue3.x双向绑定响应式数据原理
Vue3.x改用Proxy替代Object.defineProperty。
因为Proxy可以直接监听对象和数组的变化,并且有多达13种拦截方法。并且作为新标准将受到浏览器厂商重点持续的性能优化。
Proxy只会代理对象的第一层,Vue3是怎样处理这个问题的呢?
判断当前Reflect.get的返回值是否为Object,如果是则再通过reactive方法做代理, 这样就实现了深度观测。
监测数组的时候可能触发多次get/set,那么如何防止触发多次呢?我们可以判断key是否为当前被代理对象target自身属性,也可以判断旧值与新值是否相等,只有满足以上两个条件之一时,才有可能执行trigger。

③Vue3 里为什么要用 Proxy API替代 defineProperty API?
defineProperty API 的局限性最大原因是它只能针对单例属性做监听。
Vue2.x中的响应式实现正是基于defineProperty中的descriptor,对 data 中的属性做了遍历 + 递归,为每个属性设置了 getter、setter。这也就是为什么 Vue 只能对 data 中预定义过的属性做出响应的原因。
Proxy API的监听是针对一个对象的,那么对这个对象的所有操作会进入监听操作, 这就完全可以代理所有属性,将会带来很大的性能提升和更优的代码。
Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
响应式是惰性的。
在 Vue.js 2.x 中,对于一个深层属性嵌套的对象,要劫持它内部深层次的变化,就需要递归遍历这个对象,执行 Object.defineProperty 把每一层对象数据都变成响应式的,这无疑会有很大的性能消耗。
在 Vue.js 3.0 中,使用 Proxy API 并不能监听到对象内部深层次的属性变化,因此它的处理方式是在 getter 中去递归响应式,这样的好处是真正访问到的内部属性才会变成响应式,简单的可以说是按需实现响应式,减少性能消耗。
五.什么是虚拟DOM
virtual DOM 虚拟DOM,用普通js对象来描述DOM结构,因为不是真实DOM,所以称之为虚拟DOM。
目的是为了减少回流和重绘,提升性能。
虚拟DOM基本步骤

1.页面初始加载解析DOM树,将DOM解析为JS对象
[最终还需要将其映射成真实DOM,渲染到页面]
2.DOM结构要发生变化,生成一个新的JS对象
3.DIFF比较,比较同级对象
4.将不同之处写入到patch对象中
5.渲染到页面

那么为什么用虚拟dom呢?
Web界面由DOM树(树的意思是数据结构)来构建,当其中一部分发生变化时,其实就是对应某个DOM节点发生了变化,
虚拟DOM就是为了解决浏览器性能问题而被设计出来的。若一次操作中有10次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地一个JS对象中,最终将这个JS对象一次性attch到DOM树上,再进行后续操作,避免大量无谓的计算量。所以,用JS对象模拟DOM节点的好处是,页面的更新可以先全部反映在JS对象(虚拟DOM)上,操作内存中的JS对象的速度显然要更快,等更新完成后,再将最终的JS对象映射成真实的DOM,交由浏览器去绘制。

大白话:就是为了提高代码效率,渲染效果,就如往常的js jquery这些使用dom操作时都是一段复杂的过程,整个过程要遍历属性,标签啦,就是在你的代码上一遍遍寻找大半天还不知道有没有收获,很慢。而且做多件事情的时候只能一件件去做,浪费很多时间,而我们的虚拟dom呢,就是,把你想要做的事情都用小本子记起来(记在本地js对象上)在虚拟dom上更新完成后,再拿到真是的dom上去渲染,然后交给浏览器绘制页面呀。从头到末尾,人家知道每一步要做什么,而且可以同时做,还不会等到你的页面渲染完成后才出发,人家可是早早出发了,

真实DOM和虚拟DOM的区别
那么说回到真实DOM,虚拟DOM和真实DOM又有什么区别呢?
我想,应该会有一下几点:

1.虚拟DOM不会进行排版与重绘操作
2.真实DOM频繁排版与重绘的效率是相当低的
3.虚拟DOM进行频繁修改,然后一次性比较并修改真实DOM中需要改的部分,最后并在真实DOM中进行排版与重绘,减少过多DOM节点排版与重绘损耗
4.虚拟DOM有效降低大面积(真实DOM节点)的重绘与排版,因为最终与真实DOM比较差异,可以只渲染局部
DIFF算法
vue diff算法

六.Diff算法步骤
用js对象结构(虚拟DOM)表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中
当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异
把所记录的差异应用到所构建的真正的DOM树上,视图就更新了
Diff 算法: 仅在同级的vnode间做diff,递归地进行同级vnode的diff,不仅仅是同层级对比,在diff算法中也会进行同key值对比和同组件对比
Diff 过程整体策略:深度优先,同层比较

key的作用
在使用v-forj添加唯一的key的作用标识,Diff算法就可以正确的识别此节点,找到正确的位置区更新新的节点,高效的更新虚拟DOM。
八:Vue的生命周期:

  • beforecreated :表示刚创建了一个空的Vue实例,此时对象身上只有生命周期钩子函数和事件,其他的东西还未创建,data,method等都还未初始化
  • created:data和methods等已被初始化,之后开始编译模板
  • beforeMount:完成了模板($el)的编译,还未挂载到页面上去
  • mounted:将已经编译好的模板(el),挂载到指定的容器中去(el或mount)
  • beforeUpdate:此时data中的数据是最新的,但是view还没有被更新
  • updated:date和view都是最新的
  • beforeDestroy: 实例销毁之前,在当前阶段实例完全可以被使用(data,methods,指令等),我们可以在这时进行善后收尾工作,比如清除计时器
  • destroy:组件已经被彻底销毁,实例不可用
  • activited keep-alive 专属 , 组件被激活时调用
  • deactivated keep-alive 专属 , 组件被销毁时调用
    九:Vue组件通信
    1.父组件向子组件传递数据可以通过 props;
    2.子组件向父组件是通过 emit、on事件;
    3.还可以通过 root、parent、refs属性相互访问组件实例; 不建议使用root(根组件)和parent(上一级父组件)(不稳定) ref说明: ①ref 加在普通的元素上,用this.refs.(ref值) 获取到的是dom元素
    ②ref 加在子组件上,用this.refs.(ref值) 获取到的是组件实例,可以使用组件的所有方法。在使用方法的时候直接this.refs.(ref值).方法() 就可以使用了。
    4.跨级通信: eventbus ;Vuex;provide / inject;
    十:Vue项目优化
    项目优化

相关文章

  • js基础面试题

    面试题:延迟加载JS有哪些方式? 面试题:JS数据类型有哪些? 面试题:JS数据类型考题 考题一: 考题二: 面试...

  • 前端相关大杂烩

    前端基础面试题(JS部分) 前端基础面试题(JS部分)学习 React.js 比你想象的要简单 原文地址:Lear...

  • 前端JavaScript面试技巧

    1-1 课程概述 要做什么?——讲解前端 JS 基础面试题 哪些部分?——JS 基础,JS-WEB-API,JS ...

  • 2021 web高频面试题新人可看

    当日目标 1 常见面试题分布情况? 2 高频面试题 1 常见面试题分布情况 公司面试题一般分为js,vue,小程序...

  • js 基础面试题

    js 基础面试题 1 js中使用typeof能得到哪些类型? undefined、string、number、bo...

  • 99%的人都会答错的js面试题(你会吗?)(转)

    99%的人都会答错的js面试题(你会吗?)

  • js数组题目

    js面试题 js数组 一、按要求分割数组 将"js,数组,分类"字符串数组以/分割 for循环累加 join()把...

  • 前端JavaScript面试技巧

    先看几道面试题: 1、JS中使用typeof能得到哪些类型。//JS变量类型2、何时使用“==”、“===”。//...

  • js运行机制

    js运行机制 在日常面试求职中,不免会做几道面试题,这面试题中往往会遇到js执行输出顺序,而这运行机制是我们每个前...

  • web前端入门到实战:32道常见的js面试题

    JS面试题: 【点击这里领取面试题资料】[https://jq.qq.com/?_wv=1027&k=fBr6dx...

网友评论

      本文标题:JS面试题

      本文链接:https://www.haomeiwen.com/subject/jmigrrtx.html