面试可能会遇到的问题(三)

基于前端面试整理了一些自己复习到的知识,留作总结。
参考链接已附,侵删。


13、算法

①排序

排序

  1. 快速排序:https://segmentfault.com/a/1190000009426421
    ·先从数列中取出一个数作为“基准”。
    ·分区过程:将比这个“基准”大的数全放到“基准”的右边,小于或等于“基准”的数全放到“基准”的左边。
    ·再对左右区间重复第二步,直到各区间只有一个数。
  2. 选择排序:https://segmentfault.com/a/1190000009366805
    ·在未排序序列中找到最小(大)元素,存放到排序序列的起始位置
    ·从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
    ·重复第二步,直到所有元素均排序完毕。
  3. 希尔排序:https://segmentfault.com/a/1190000009461832
    ·选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1;
    ·按增量序列个数 k,对序列进行 k 趟排序;
    ·每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
  4. 冒泡排序:https://www.cnblogs.com/beli/p/6297741.html
    ·比较相邻的两个元素,如果前一个比后一个大,则交换位置。
    ·第一轮的时候最后一个元素应该是最大的一个。
    ·按照步骤一的方法进行相邻两个元素的比较,这个时候由于最后一个元素已经是最大的了,所以最后一个元素不用比较。
②堆栈、队列、链表

https://juejin.im/entry/58759e79128fe1006b48cdfd

  1. 栈:栈的特点先进后出(First in last out)。对于栈来说,需要实现添加、删除元素、获取栈顶元素、已经是否为空,栈的长度、清除元素等几个基本操作。
    利用数组的push()和pop()实现添加和删除元素。
  2. 队列:队列是遵循FIFO(First In First Out,先进先出,也称为先来先服务)原则的一组有序的项。实现的基本操作与栈相同。
    利用数组的push()和shift()实现添加和删除元素。
  3. 链表:链表存储有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成。相对于传统的数组,链表的一个好处在于,添加或移除元素的时候不需要移动其他元素。双向链表即能指向下一个节点,也能指向上一个节点。
③递归

递归的函数每次调用都会压入调用栈,如果传入的参数值特别大,那么这个调用栈将会非常之大,最终可能超出调用栈的缓存大小而崩溃导致程序执行失败。由此出现尾递归。

尾递归是一种递归的写法,可以避免不断的将函数压栈最终导致堆栈溢出。上一次执行完成就可以pop出去,下一次执行再push进来。

④波兰式和逆波兰式

原理:
http://www.cnblogs.com/chenying99/p/3675876.html
https://blog.csdn.net/linraise/article/details/20459751
实现:https://github.com/Tairraos/rpn.js/blob/master/rpn.js
(后续补充看)
波兰式:中缀表达式转为前缀表达式
逆波兰式:中缀表达式转为后缀表达式

14、渲染机制

①什么是DOCTYPE及作用

DTD(document type definition,文档类型定义):是一系列语法规则。用它来告诉浏览器文档类型,从而决定浏览器如何解析及切换何种模式。

DOCTYPE是用来声明什么文档类型和DTD规范的,告诉浏览器所使用的文档类型。

常见的DOCTYPE:

  1. HTML 5
<!DOCTYPE html>
  1. HTML 4.01 Strict 该DTD包含所有HTNL元素和属性,但不包括展示和弃用的元素
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
  1. HTML 4.01 Transitional 该DTD包含所有HTNL元素和属性,包括展示和弃用的元素
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
②浏览器的渲染过程

浏览器渲染
·将HTML经过HTML Parser解析DOM Tree;
·将CSS经过CSS Parser解析成CSSOM Tree;
·两个树相结合形成一个Render Tree,呈现出渲染树结构;
·渲染树结构不包含html的具体内容,也不包含元素的具体位置等,通过Layout来精确计算dom的宽高颜色等具体样式;
·浏览器开始Painting;
·最后将最终效果呈现在页面上;
Render Tree
Layout

③浏览器重排Reflow
  1. Reflow定义:通过浏览器对各种样式的计算将元素放到它该出现的位置,这个过程叫reflow。
  2. 触发Reflow(每个dom都有reflow方法?基本reflow就会repaint)
    ·增加、删除、修改DOM结点时,会导致Reflow或Repaint
    ·移动DOM的位置,或是搞个动画的时候
    ·修改CSS样式的时候
    ·Resize窗口的时候(移动端没有这个问题),或是滚动的时候 ->有可能
    ·修改网页的默认字体时(影响很严重,可能会闪屏,影响性能)
④浏览器重绘Repaint
  1. Repaint定义:当各种盒子的样式最终确定下来后,浏览器按照元素各自的特性去绘制,最终页面内容出现,这个过程叫repaint。
  2. 触发Repaint
    ·DOM改动
    ·CSS改动
  3. 最大程度的减少Repaint
    多个节点添加到页面上时,通过document.createDocumentFragment创建片段,写好后同意添加。

15、js运行机制

①如何理解js的单线程

js是单线程的,同一时间只能做一件事。

②什么是任务队列

js任务队列有同步任务和异步任务。优先同步任务、同步处理之后响应异步任务。
异步任务的执行时间与放入异步队列的时间是不同的:
执行到异步任务是不会立刻放到异步队列中的,如setTimeout,会先放到浏览器Timer模块中,等时间到了才放入异步队列中等待执行。尽管setTimeout设置为0,最新浏览器也是按照4ms来算的。

③什么是Event Loop

事件循环
运行栈用来放置同步任务,执行到异步任务,先挂起等待事件,放入一个事件模块中。等到事件发生时再push到异步任务队列中。同步任务执行完成后,读取异步任务对列中的任务,将其放入运行栈中作为同步任务执行。同步任务执行完成后,再去监听异步任务队列中的任务,如此循环,循环的过程就是事件循环。

④开启异步任务
  1. setTimeout、setInterval。
  2. DOM事件(浏览器监听GUI线程,触发事件)点击浏览器无响应,也是因为同步任务没有执行完,不去读取异步队列,造成浏览器假死的现象。
  3. ES6中的Promise、异步回调。

16、提升页面性能的方法

  1. 资源压缩合并,减少HTTP请求
  2. 非核心代码异步加载
    ·动态脚本加载:document.createElement(‘script’),用js加载script标签
    ·defer:在HTML解析完之后才会执行,如果是多个,按照加载的顺序依次执行
    ··async:在加载完之后立即执行,如果是多个,执行顺序和加载顺序无关
  3. 利用浏览器缓存
    缓存的分类:
    1)强缓存:浏览器强制使用本地缓存副本
    Expires(过期时间): Thu,21 Jan 2017 23:39:02 GMT(表示服务器的绝对时间)
    (客户端与浏览器的时间可能不一致)
    Cache-Control: max-age=3600(客户端相对时间为止)
    (都下发,以Cache-Control为准)
    2)协商缓存:浏览器向服务器询问是否可以使用本地缓存副本。强缓存失效了就启用协商缓存。
    Last-Modified(服务器的响应头) If-Modified-Since(浏览器的请求头) : Wed, 26 Jan 2017 00:35:11 GMT
    (有可能修改时间变化了,但文件没有变化的情况,还是可能拿缓存的。所以出现了Etag)
    Etag(服务器的响应头) If-None-Match(浏览器的请求头)(hash值)
    (以Etag为准?)
  4. 使用CDN(内容发布网络,与供应商相关联)
  5. 预解析DNS
// 强制打开预解析(页面是https协议开头,很多浏览器是关闭a标签的预解析的)
<meta http-equive="x-dns-prefetch-control" content="on">
<link rel="dns-prefetch" href="//host_name_to_prefetch.com">
  1. 减少对DOM的查询,插入等操作,减少浏览器重排与重绘

17、错误监控

前端错误的分类

即使运行错误:代码错误
资源加载错误

错误的捕获方式
  1. 即时运行错误:代码错误
    try…catch
    window.onerror(只能捕获即时运行错误)
  2. 资源加载错误
    object.onerror(不冒泡)
    performance.getEntries:高级浏览器,用以获取所有已加载资源的加载时长
    Error事件捕获(window上通过事件捕获,在捕获阶段拿事件,冒泡不行)
    跨域js运行错误也可以捕获到,获取的错误信息都是:Script error.
    如果想获取更多信息1)在script标签头上增加crossorigin属性;2)设置js资源响应头Access-Control-Allow-Origin: *
上报错误的基本原理

·采用Ajax通信的方式上报(都不这么用)
·利用Image对象上报 (new Image()).src="…?r=fff"

18、MVVM框架

https://baijiahao.baidu.com/s?id=1596277899370862119&wfr=spider&for=pc

了解MVVM框架吗

用过Vue.js框架。对Vue.js比较熟悉,在公司中的项目有用。

谈谈你对MVVM的认识

MVVM
MVVM是Model-View-ViewModel的简写。【模型】指的是后端传递的数据。【视图】指的是所看到的页面。【视图模型】MVVM的核心,是连接View和Model的桥梁。它有两个方向:一是将【模型】转为【视图】,即将后端传递的数据转化成所看到的页面,实现的方式是数据绑定;二是将【视图】转化成【模型】,即将所看到的页面转化成后端的数据。实现方式是DOM事件监听。这两个方向就统称为数据双向绑定。在MVVM的框架下视图和模型是不能直接通信的。它们通过ViewModel来通信。

MVC是Model-View- Controller的简写。C即Controller指的是页面业务逻辑。MVC是单向通信。也就是View跟Model,必须通过Controller来承上启下。ViewModel存在目的在于抽离Controller中展示的业务逻辑,而不是替代Controller,其它视图操作业务等还是应该放在Controller中实现。

在vue中:Model:指的是js中的数据,如对象,数组等等。View:指的是页面视图。viewModel:指的是vue实例化对象,实例化时会进行数据的双向绑定。

Vue是一个渐进式的javascript框架, 渐进式是什么意思

对VUE的使用可大可小,它都会有相应的方式来整合到你的项目中。

双向绑定的原理是什么

一是将【模型】转为【视图】,即将后端传递的数据转化成所看到的页面,实现的方式是数据绑定;二是将【视图】转化成【模型】,即将所看到的页面转化成后端的数据。实现方式是DOM事件监听。这两个方向就统称为数据双向绑定。在Vue中会自动帮我们完成。
双向绑定原理

object.defineProperty与reflect.defineProperty的区别

一个是ES5中的用法,返回修改后的对象;
一个是ES6中的用法,返回一个bool值,出错时不会抛出异常;
有一个趋势是,object对象上的方法都会迁移到reflect上。

使用了什么设计模式

使用了观察者模式。观察者模式指的是有一个函数observe自动监听数据对象的变化,一旦对象有变化,通知所有的观察者列表,触发观察者自动执行。
观察者模式

Vue生命周期是什么

https://cn.vuejs.org/v2/guide/instance.html#实例生命周期钩子
https://segmentfault.com/a/1190000011381906
每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

Vue的源码分析

Vue源码分析
初始化Vue实例时,执行observe,对Vue中的每一个data改为Object.defineProPerty()的getter和setter的形式(包括data下的对象,用递归),在getter中维护一个Dep列表,列表中用以添加该data的观察者,在setter中监听数据的变化,遍历Dep数组去执行每一个watcher的update回调方法来渲染view视图层;关于watcher是在后面的Compile中手动添加。然后new一个Compile解析器,初始化视图。先生成虚拟DOM,并且对DOM中绑定的指令和事件进行解析,生成相应的观察者,定义好该观察者的update回调函数,将与data相关的观察者通过getter放入该data的Dep列表。当数据发生变化时,触发observe监听,Dep队列中的watcher就会触发update更新视图。对于v-model,要绑定input监听事件,用于在视图发生变化时自动触发data更新。在中间相应的阶段插入生命周期钩子函数。初始化实例完成。

本地文件:/Users/snow/Downloads/coding-129/source/mvvm
https://github.com/DMQ/mvvm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值