前端八股文
文章目录一. JavaScript1.1 基本数据类型 (7种)1.2 this 的指向 (new, 隐式绑定, 显式绑定)1.3 call, apply(数组), bind1.4eventloop, 宏任务和微任务1.5 闭包 (概念, 用途, 手写)1.7 继承 (extends, 原型链继承, 构造函数继承, 组合继承, 寄生组合继承)1.8深拷贝和浅拷贝1.9 PromiseAjax请求过
一. JavaScript
1.1 数据类型 (9种)
基本数据类型(栈):Number,String,Boolean,null,undefined,symbol(创建唯一值),bigint(后两个为ES6新增)
引用数据类型(堆):object,function
1、typeof typeof 是一个操作符,返回该类型的字符串(全小写字母)形式表示,包括以下 7种:number、string、boolean、undefined、symbol、object、function 等。(对于 null,返回 object 类型。)
- 对于基本类型,除 null 以外,均可以返回正确的结果。
- 对于引用类型,除 function ,一律返回 object 类型。
2、instanceof 检测的是原型,instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型。
3、toString是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]]Object.prototype.toString.call('')
4、constructor是原型prototype的一个属性,当函数被定义时候,js引擎会为函数添加原型prototype,并且这个prototype中constructor属性指向函数引用, 因此重写prototype会丢失原来的constructor。
var、let、const
let 和 const 的优点?
let 和 const 有了块级作用域,变量声明不会提升相比于 var
var、let、const的区别
- var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。
- let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。
- const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。
1.2 普通函数、匿名函数、箭头函数
- 普通函数中的this:谁调用了函数或者方法,this指向谁
- 匿名函数中的this:指向是window,而不是调用该匿名函数的对象;
- 箭头函数中的this
- 箭头函数中的this是在函数定义的时候就确定下来的
- 箭头函数中的this指向父级作用域的执行上下文;
- 箭头函数无法使用apply、call和bind方法改变this指向
箭头函数与普通函数区别
- 箭头函数是匿名函数不能作为构造函数不能使用new
- 箭头函数不绑定arguments,需要用运算符解决…解决
- 箭头函数不绑定this,会捕获其所在的this值,作为自己的this值
- 箭头函数通过call()或apply()调用一个函数,只传入了一个参数,对this并没有影响.
- 箭头函数没有原型属性
new操作符具体干了什么呢
- 创建一个新的对象obj
- 将对象与构建函数通过原型链连接起来
- 将构建函数中的this绑定到新建的对象obj上
- 根据构建函数返回类型作判断,如果是原始值则被忽略,如果是返回对象,需要正常处理
1.3 call, apply(数组), bind
作用:
- 都可以改变函数内部的this指向。
区别点: - call 和 apply 会调用函数,并且改变函数内部this指向。
- call 和 apply 传递的参数不一样,call 传递参数arg1,arg2…形式 apply 必须数组形式[arg]
- bind 不会调用函数,可以改变函数内部this指向。
1.4 eventloop, 宏任务和微任务
不停检查 Call Stack 中是否有任务(也叫栈帧)需要执行,如果没有,就检查 Event Queue,从中弹出一个任务,放入 Call Stack 中,如此往复循环。
1、所有同步任务都在主线程上执行,形成一个执行栈
2、主线程之外,还存在一个"消息队列"。只要异步操作执行完成,就到消息队列中排队
3、一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取消息队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行
4、主线程不断重复上面的第三步
- 宏任务(setTimeout, setInterval,setImmediate) Macrotask 宏任务是指Event Loop在每个阶段执行的任务
- 微任务 (Promises, Object.observe)Microtask 微任务是指Event Loop在每个阶段之间执行的任务
- new promise 与同步一起,先微后宏
1.5 闭包 (概念, 用途, 手写)
一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围), 这样的组合就是闭包(closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。
闭包的特点:
- 让外部访问函数内部变量成为可能;
- 可以避免使用全局变量,防止全局变量污染;
- 可以让局部变量常驻在内存中;
- 会造成内存泄漏(有一块内存空间被长期占用,而不被释放)
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
1.7 继承 (extends, 原型链继承, 构造函数继承, 组合继承, 寄生组合继承)
1.8深拷贝和浅拷贝
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象共享同一块内存。
深拷贝会创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
实现浅拷贝方法:
(1)Object.assign方法
(2)for in方法
实现深拷贝方法:
(1)采用递归去拷贝所有层级属性
(2)使用JSON.stringify和JSON.parse实现深拷贝:JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象;
(3)热门的函数库lodash,也有提供_.cloneDeep用来做深拷贝;
1.9 Promise
Promise对象, 可以将异步操作以同步的流程表达出来。使用 Promise 主要有以下好处:
- 可以很好地解决回调地狱的问题(避免了层层嵌套的回调函数)。
- 语法非常简洁。Promise 对象提供了简洁的API,使得控制异步操作更加容易
new Promise(function(resolve, reject)
then,catch,finally捕获错误
Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中promise 有一个失败(rejected),此实例回调失败(reject),失败的原因是第一个失败 promise的结果。
Promse.race Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。
Ajax请求过程
(1)创建 XMLHttpRequest 对象,也就是创建一个异步调用对象;
(2)创建一个新的 HTTP 请求,并指定该 HTTP 请求的方法、 URL 以及验证信息;
(3)设置响应 HTTP 请求状态变化的函数;
(4)发送 HTTP 请求;
(5)获取异步调用返回的数据;
(6)使用 JavaScript 和 DOM 实现局部刷新。
AMD、CMD、CommonJs、ES6的对比
他们都是用于在模块化定义中使用的,前三个是ES5中提供的模块化编程的方案,
AMD: 是RequireJS在推广过程中对模块定义的规范化产出(依赖前置、异步定义)
通过define()函数定义,第一个参数是一个数组,里面定义一些需要依赖的包,第二个参数是一个回调函数,通过变量来引用模块里面的方法,最后通过return来输出。
CMD:是SeaJS在推广过程中对模块定义的规范化产出,(同步模块,没有前置依赖)
通过define()定义,没有依赖前置,通过require加载jQuery插件,CMD是依赖就近,在什么地方使用到插件就在什么地方require该插件,即用即返,这是一个同步的概念
CommonJs:是通过module.exports定义的,通过node.js后端使用的。
import/export:是ES6中定义新增的,对模块进行导出导入的
require,import和import()函数的区别
import命令会被 JavaScript 引擎静态分析,先于模块内的其他模块执行(叫做”连接“更合适)。
import()函数,完成动态加载。异步加载
require是运行时加载模块,只有运行时才知道,同步加载
ES6转化为ES5
https://blog.csdn.net/weixin_44135121/article/details/104161852
Parser 解析
第一步主要是将 ES6 语法解析为 AST 抽象语法树。简单地说就是将代码打散成颗粒组装的对象。这一步主要是通过 babylon 插件来完成。
Transformer 转换
第二步是将打散的 AST 语法通过配置好的 plugins(babel-traverse 对 AST 进行遍历转译)和 presets (es2015 / es2016 / es2017 / env / stage-0 / stage-4 其中 es20xx 表示转换成该年份批准的标准,env 是最新标准,stage-0 和 stage-4 是实验版)转换成新的 AST 语法。这一步主要是由 babel-transform 插件完成。plugins 和 presets 通常在 .babelrc 文件中配置。
Generator 生成
第三步是将新的 AST 语法树对象再生成浏览器都可以识别的 ES5 语法。这一步主要是由 babel-generator 插件完成
二. 浏览器
2.1浏览器输入URL发生了什么
http请求的推演过程:
- 对网址进行DNS域名解析,得到对应的IP地址(输入地址,在远程 DNS 服务器上启动一个 DNS 查询。这能使浏览器获得请求对应的 IP 地址。)
- 根据这个IP,找到对应的服务器,发起TCP的三次握手(该握手包括一个同步报文,一个同步-应答报文和一个应答报文,这三个报文在 浏览器和服务器之间传递。该握手首先由客户端尝试建立起通信,而后服务器应答并接受客户端的请求,最后由客户端发出该请求已经被接受的报文。)
- 建立TCP连接后发起HTTP请求
- 服务器响应HTTP请求,浏览器得到html代码
(HTTP响应:状态行(协议版本、状态码、状态码描述),响应头,空格,消息体) - 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等)
(先得到html代码,才能去找这些资源) - 浏览器对页面进行渲染呈现给用户
- 服务器关闭关闭TCP连接
注:
1.DNS怎么找到域名的?
递归查询。 浏览器自身的DNS缓存->系统自身的DNS缓存->hosts文件->域名服务器
DNS优化两个方面:DNS缓存、DNS负载均衡
2.为什么HTTP协议要基于TCP来实现?
TCP是一个端到端的可靠的面相连接的协议,HTTP基于传输层TCP协议不用担心数据传输的各种问题(当发生错误时,会重传)
3.服务器关闭关闭TCP连接
一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码:
Connection:keep-alive
TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。
三次握手 四次挥手
TCP的三次握手过程如下:
C-> SYN -> S SYN标记的包,请求建立连接.
S->SYN/ACK->C SYN包的确认包,对第一个SYN包的确认
C->ACK->S 通知A连接已建立
三次握手的原因: “为了防止已经失效的连接请求报文段突然又传到服务端,因而产生错误”1. 确保建立可靠连接2. 避免资源浪费
例如,客户端先发送了一个SYN,但是由于网络阻塞,该SYN数据包在某个节点长期滞留。然后客户端又重传SYN数据包并正确建立TCP连接,然后传输完数据后关闭该连接。该连接释放后失效的SYN数据包才到达服务器端。在二次握手的前提下,服务器端会认为这是客户端发起的又一次请求,然后发送SYN
,并且在服务器端创建socket套接字,一直等待客户端发送数据。但是由于客户端并没有发起新的请求,所以会丢弃服务端的SYN
。此时服务器会一直等待客户端发送数据从而造成资源浪费。
TCP的四次挥手过程如下:
C->FIN->S 客户端进程发出连接释放报文,并且停止发送数据。
S->ACK->C 服务器收到连接释放报文,发出确认报文
S->FIN->C 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文
C->ACK->S客户端收到服务器的连接释放报文后,必须发出确认
四次挥手的原因:由于连接的关闭控制权在应用层,所以被动关闭的一方在接收到FIN包时,TCP协议栈会直接发送一个ACK确认包,优先关闭一端的通信。然后通知应用层,由应用层决定什么时候发送FIN包。应用层可以使用系统调用函数read==0来判断对端是否关闭连接。
2.2浏览器如何渲染页面的?
- HTML 被 HTML 解析器解析成 DOM 树;
- CSS 被 CSS 解析器解析成 CSSOM 树;
- 结合 DOM 树和 CSSOM 树,生成一棵渲染树(Render Tree),这一过程称为 Attachment;
- 生成布局(flow),浏览器在屏幕上“画”出渲染树中的所有节点;
- 将布局绘制(paint)在屏幕上,显示出整个页面。
2.3回流和重绘
- 重排(Reflow):当渲染树的一部分必须更新并且节点的尺寸发生了变化,浏览器重新构造渲染树。
- 重绘(Repaint):是在一个元素的外观被改变所触发的浏览器行为,浏览器会重绘制。
- 区别:重绘不一定需要重排(比如颜色的改变),重排必然导致重绘(比如改变网页位置)
- 浏览器优化:浏览器会维护1个队列,把所有会引起重排,重绘的操作放入这个队列,等队列中的操作到一定数量或者到了一定时间间隔,浏览器就会flush队列,进行一批处理,这样多次重排,重绘变成一次重排重绘
- 减少 reflow/repaint:
(1)不要一条一条地修改 DOM 的样式。可以先定义好 css 的 class,然后修改 DOM 的
className。
(2)不要把 DOM 结点的属性值放在一个循环里当成循环里的变量。
(3)为动画的 HTML 元件使用 fixed 或 absoult 的 position,那么修改他们的 CSS 是不会reflow 的。
(4)千万不要使用 table 布局。因为可能很小的一个小改动会造成整个 table 的重新布局。(table及其内部元素除外,它可能需要多次计算才能确定好其在渲染树中节点的属性,通常要花3倍于同等元素的时间。这也是为什么我们要避免使用table做布局的一个原因。)
(5)不要在布局信息改变的时候做查询(会导致渲染队列强制刷新)
2.4 http 缓存, 协商缓存
http 缓存控制
- http缓存能够帮助服务器提高并发性能,很多资源不需要重复请求直接从浏览器中拿缓存
- http 缓存分类 :强缓存 协商缓存
- 强缓存: expires 和 cache-control控制
服务器通知浏览器一个缓存时间,在缓存时间内,下次请求,直接用缓存,不在时
间内,执行比较缓存策略。
协商缓存: last-Modify 和E-tag控制
让客户端与服务器之间能实现缓存文件是否更新的验证、提升缓存的复用率,将
缓存信息中的Etag和Last-Modified通过请求发送给服务器,由服务器校验,返回304直接使用缓存,200请求成功。
补充:
1. 为什么有expires 有需要cache-control
因为expires 有个服务器和浏览器时间不同步的问题
expires是绝对事件 cache-control是相对时间
Cache-Control的优先级比Expires的优先级高
2. last-modify和Etag
last-modify 最后一次被修改的时间,它是有个精度问题 到秒
e-tag 没有精度问题 只要文件改变 e-tag值就改变
Etag 的优先级高于 Last-Modified
2.5 cookies, sessionStorage, localStorage
共同点:都是保存在浏览器端、且同源的
web storage:sessionStorage, localStorage
区别:
- 与服务器通信:cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递,而sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。
- 存储大小限制也不同,每个domain最多只能有20条cookie,cookie数据不能超过4K。sessionStorage和localStorage可以达到5M或更大。
- 数据有效期不同,
sessionStorage:仅在当前浏览器窗口关闭之前有效;
localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭 - 作用域不同,
sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;
localstorage在所有同源窗口中都是共享的;
cookie也是在所有同源窗口中都是共享的. - web Storage支持事件通知机制,可以将数据更新的通知发送给监听者
- web Storage的api接口使用更方便
写一个会过期的localStorage:
惰性删除:某个键值过期后不会被马上删除,等到下次被使用,检查到过期删除。
定时删除:每隔一段时间执行一次删除操作,并通过限制删除操作执行的次数和频率,来减少删除操作对CPU的长期占用。另一方面定时删除减少localStorage空间的浪费。
2.7 fetch vs axios
-
fetch是一个底层的 api 浏览器原生支持的 axios是一个封装好的框架
-
axios 1)支持浏览器和nodejs发请求 前后端发请求,
2)支持promise语法
3)支持自动解析json
4)支持中断请求
5) 支持拦截请求
6) 支持请求进度监测
7) 支持客户端防止csrf一句话总结: 封装比较好
-
fetch
优点: 1. 浏览器级别原生支持的api
2. 原生支持promise api
3. 语法简洁 符合 es 标准规范
4. 是由whatwg 组织提出的 现在已经是w3c规范缺点:
1. 不支持文件上传进度监测
2. 使用不完美 需要封装
3. 不支持请求中止
4. 默认不带cookie
一句话总结: 缺点是需要封装 优点 底层原生支持
2.8浏览器多页签通讯实现
- 可以借助 浏览器localstorage方式实现 cookie + setInterval 实现 websocket全双工实现 sharedworker实现
- 1) localstorage 如何实现
localstorage.setItem 方法传数据
监听window上 storage事件 就可以获得数据
2) cookie + setInterval
document.cookie 发数据
setInterval不停地去cookie上去数据
3) websocket实现
websocket是全双工通讯方式 多页签可以将服务器作为桥梁来实现通讯
4)h5 新技术 共享worker sharedworker 也可以实现
2.9前端安全相关-XSS和CSRF
- xss 跨站脚本攻击 csrf 是跨站请求伪造
- xss
浏览器向服务器请求的时候被注入脚本攻击
分成三种类型 反射型(非持久型), 存储型(持久型), 基于DOM
防范手段:
1. 输入过滤
2. 输出过滤
3. 加httponly 请求头 锁死cookie - csrf
黑客通过网站B 诱使用户去访问已经登录了的网站A 进行一些违背用户意愿的请求造成用户损失
防范手段:
1. 服务器验证 http请求的 refer 头信息
2. 请求的时候 传token
3. 加验证码
2.10跨域问题
1.跨域问题是浏览器同源策略限制,当前域名的js只能读取同域下的窗口属性。
(协议名,子域名,主域名,端口号)
-
跨域解决方案
-
jsonp:利用script 标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。JSONP优点是简单兼容性好,缺点是仅支持get方法具有局限性, 不安全可能会遭受XSS攻击。
-
cors:跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来进行跨域。浏览器会自动进行 CORS 通信,服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。
- postMessage:「window.postMessage()」是HTML5中的API,允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。
- websocket:是HTML5的协议,实现了浏览器与服务器的全双工通信,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。
- Node中间件代理 :实现原理:同源策略是浏览器需要遵循的标准,而如果是服务器向服务器请求就无需遵循同源策略。
- nginx反向代理 :
搭建一个中转nginx服务器,用于转发请求。只需要修改nginx的配置即可解决跨域问题 - window.name + iframe
- location.hash + iframe
- document.domain + iframe
日常工作中,用得比较多的跨域方案是cors和nginx反向代理
2.11HTTP响应
HTTP响应由三部分组成:状态行,响应头,空格,消息体
状态行包括:协议版本、状态码、状态码描述
状态码: 状态码用于表示服务器对请求的处理结果
1xx:指示信息——表示请求已经接受,继续处理
2xx:成功——表示请求已经被成功接收、理解、接受。
3xx:重定向——要完成请求必须进行更进一步的操作
4xx:客户端错误——请求有语法错误或请求无法实现
5xx:服务器端错误——服务器未能实现合法的请求。
列举几种常见的:
200(没有问题)
301是永久重定向
302(要你去找别人) 临时重定向
304(要你去拿缓存) 未修改
307(要你去拿缓存)
403(有这个资源,但是没有访问权限)
404(服务器没有这个资源)
500(服务器这边有问题)
响应头: 响应头用于描述服务器的基本信息,以及客户端如何处理数据
空格: CRLF(即 \r\n)分割
消息体: 服务器返回给客户端的数据
2.12 http(http1.x 和http2.x)和https
HTTP:是一种网络协议,用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。
HTTPS:是HTTP的安全版,即HTTP下加入SSL层。,如今 SSL 已废弃,HTTPS 引入了数据加密和身份验证机制。通过安全可靠的 TLS 协议进行加密。
HTTPS作用:
- 内容加密 建立一个信息安全通道,来保证数据传输的安全;
- 身份认证 确认网站的真实性
- 数据完整性 防止内容被第三方冒充或者篡改
HTTPS和HTTP的区别主要如下:
1、https协议需要到ca申请证书,需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
http1.x 和http2.x主要有以下4个区别:
- HTTP2使用的是二进制传送(帧和流),HTTP1.X是文本(字符串)传送。
- HTTP2支持多路复用
- HTTP2头部压缩
- HTTP2支持服务器推送
非对称加密和对称加密
- 对称加密:在对称加密算法中,加密使用的密钥和解密使用的密钥是相同的。也就是说,加密和解密都是使用的同一个密钥。
- 非对称加密:指加密和解密使用不同密钥的加密算法。非对称加密算法需要两个密钥:公钥(publickey)私钥(privatekey)。
加密在HTTPS协议中的应用
- 浏览器向服务器发出请求,询问对方支持的对称加密算法和非对称加密算法;服务器回应自己支持的算法。
- 浏览器选择双方都支持的加密算法,并请求服务器出示自己的证书;服务器回应自己的证书。
- 浏览器随机产生一个用于本次会话的对称加密的钥匙,并使用服务器证书中附带的公钥对该钥匙进行加密后传递给服务器;服务器为本次会话保持该对称加密的钥匙。第三方不知道服务器的私钥,即使截获了数据也无法解密。非对称加密让任何浏览器都可以与服务器进行加密会话。
- 浏览器使用对称加密的钥匙对请求消息加密后传送给服务器,服务器使用该对称加密的钥匙进行解密;服务器使用对称加密的钥匙对响应消息加密后传送给浏览器,浏览器使用该对称加密的钥匙进行解密。第三方不知道对称加密的钥匙,即使截获了数据也无法解密。对称加密提高了加密速度 。
完整的非对称加密过程
假如现在 你向支付宝 转账(术语数据信息),为了保证信息传送的保密性、真实性、完整性和不可否认性,需要对传送的信息进行数字加密和签名,其传送过程为:
- 首先你要确认是否是支付宝的数字证书,如果确认为支付宝身份后,则对方真实可信。可以向对方传送信息
- 你准备好要传送的数字信息(明文)计算要转的多少钱,对方支付宝账号等;
- 你对数字信息进行哈希运算,得到一个信息摘要(客户端主要职责);
- 你用自己的私钥对信息摘要进行加密得到 你 的数字签名,并将其附在数字信息上;
- 你随机产生一个加密密钥,并用此密码对要发送的信息进行加密(密文);
- 你用支付宝的公钥对刚才随机产生的加密密钥进行加密,将加密后的 DES 密钥连同密文一起传送给支付宝
- 支付宝收到 你 传送来的密文和加密过的 DES 密钥,先用自己的私钥对加密的 DES 密钥进行解密,得到 你随机产生的加密密钥;
- 支付宝 然后用随机密钥对收到的密文进行解密,得到明文的数字信息,然后将随机密钥抛弃;
- 支付宝 用你 的公钥对 你的的数字签名进行解密,得到信息摘要;
- 支付宝用相同的哈希算法对收到的明文再进行一次哈希运算,得到一个新的信息摘要;
- 支付宝将收到的信息摘要和新产生的信息摘要进行比较,如果一致,说明收到的信息没有被修改
过; - 确定收到信息,然后进行向对方进行付款交易,一次非对称密过程结束。
三. CSS
盒子模型, 怪异盒子
盒模型: 内容(content)、填充(padding)、边界(margin)、 边框(border)
标准 W3C 盒子模型:width=content
IE 盒子模型:width=content+ border +padding;
BFC
BFC,块级格式化上下文,形成独立的渲染区域,盒子里面的子元素的样式不会影响到外面的元素。
BFC触发方式
- 根元素,即HTML标签
- 浮动元素:float值为 left 、 right
- overflow值不为 visible,为 auto 、 scroll 、 hidden
- display值为 inline-block 、 table-cell 、 table-caption 、 table 、 inline-table 、 flex 、 inline-flex 、 grid 、 inline-grid
- 定位元素:position值为 absolute 、 fixed
作用
- 阻止元素被浮动元素覆盖 :一个正常文档流的block元素可能被一个float元素覆盖,挤占正常文档流,因此可以设置一个元 素的float、 display、position值等方式触发BFC,以阻止被浮动盒子覆盖。
- (清除浮动)可以包含浮动元素 通过改变包含浮动子元素的父盒子的属性值,触发BFC,以此来包含子元素的浮动盒子。
- 阻止因为浏览器因为四舍五入造成的多列布局换行的情况 有时候因为多列布局采用小数点位的width导致因为浏览器因为四舍五入造成的换行的情况,可 以在最后一列触发BFC的形式来阻止换行的发生。比如下面栗子的特殊情况
- (外边距塌陷)阻止相邻元素的margin合并 属于同一个BFC的两个相邻块级子元素的上下margin会发生重叠,(设置writing-mode:tb-rl时, 水平margin会发生重叠)。所以当两个相邻块级子元素分属于不同的BFC时可以阻止margin重
float, 清除浮动
浮动元素引起的问题
- 多个浮动的元素无法撑开父元素的宽度,父元素的高度可能会变成0。
- 若浮动元素后面跟非浮动元素,非浮动元素会紧随其后浮动起来。
- 若浮动元素前面还有同级元素没有浮动则会影响页面结构。 浮动元素脱离文档流,不占据空间。浮动元素碰到包含它的边框或者浮动元素的边框停留。
clear当应用于非浮动块时,它将非浮动块的边框边界移动到所有相关浮动元素外边界的下方。这个非浮动块的垂直外边距会折叠。
1.使用空标签清除浮动。clear属性
<div style="clear:both;"></div>
2. 使用after伪对象清除浮动。clear属性
该方法只适用于非IE浏览器。该方法中必须为需要清除浮动元素的伪对象中设置 height:0,否则该元素会比实际高出若干像素;
3. 使用overflow。(计算BFC高度时,浮动子元素也参与计算)
可以给父元素设置overflow:auto或者hidden
4. 浮动外部元素 形成BFC
解决盒子塌陷
- 盒子大小写死,给每个盒子设定固定的width和height
- 给外部的父盒子也添加浮动,脱离标准文档流
- 给父盒子添加overflow属性。
- 父盒子里最下方引入清除浮动块。
- 用after伪元素清除浮动
- 给父盒子添加border
- 给父盒子设置padding-top
垂直居中的方法
- 绝对定位+css3 transform:translate(-50%,-50%)
- css3 的flex布局 align-self:center;
- table布局 table-cell 和 vertical-align 对容器里的文字进行垂直居中
样式优先级
内联样式 > id选择器样式 > 类选择器样式 > 元素选择器样式
CSS中 link 和@import 的区别是?
(1) link属于HTML标签,而@import是CSS提供的;
(2) 页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载;
(3) import只在IE5以上才能识别,而link是HTML标签,无兼容问题;
position 的值的定位区别:
1.absolute 生成绝对定位的元素,相对于 static 定位以外的第一个祖先元素进行定位。
2.fixed 生成固定定位的元素,相对于浏览器窗口进行定位(老IE不支持)。
3.relative 生成相对定位的元素,相对于其在普通流中的位置进行定位。
4.static 默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right z-index 声明)。
5.inherit 规定从父元素继承 position 属性的值。
position的absolute与fixed共同点与不同点
共同点
1.改变行内元素的呈现方式,display被置为block
2.让元素脱离普通流,不占据空间
3.默认会覆盖到非定位的元素上
不同点
- absolute的“根元素”是可以设置的,而fixed的“根元素”固定位浏览器窗口
- 当滚动网页时,fixed元素与浏览器窗口之间的距离是不变的
四.HTML
块元素, 行内元素
语义化标签: header, section 等
异步加载JS文件: defer 和 async
Ajax->XMLHttpRequest
Axios->fetch
五.VUE
mvc和mvvm的区别
参考答案:
MVC: MVC是应用最广泛的软件架构之一,一般 MVC 分为: Model(模型) , View(视图) , Controller(控制 器) 。 这主要是基于分层的目的,让彼此的职责分开. View 一般用过 Controller 来和 Model 进行联系。 Controller 是 Model 和 View 的协调者, View 和 Model 不直接联系。基本都是单向联系。
MVVM: MVVM 是把 MVC 中的 Controller 改变成了ViewModel 。 View 的变化会自动更新到ViewModel , ViewModel 的变化也会自动同步到 View上 显示,通过数据来显示视图层。
MVVM和MVC的区别:
- MVC中Controller演变成MVVM中的ViewModel
- MVVM通过数据来显示视图层而不是节点操作
- MVVM主要解决了MVC中大量的dom操作使页面渲染性能降低,加载速度变慢,影响用户体验
diff 原理
dom-diff 算法会比较前后虚拟 DOM ,从而得到 patches (补丁),然后与老 Virtual DOM 进行对比,将其应用在需要更新的地方,将 O(n^3) 复杂度的问题转换成 O(n^1=n) 复杂度的问题,得到新的
Virtual DOM 。降低时间复杂度的方法:
- 两个不同类型的元素会产生不同的树
- 对于同一层级的一组子节点,它们可以通过唯一 key 进行区分
组件通信
- props和$emit
父->子 prop传递的,子->父组件 $emit触发事件来做到的 - v-model
父组件通过v-model传递值给子组件时,会自动传递一个value的prop属性,在子组件中通过this.$emit(‘input’,val)自动修改v-model绑定的值 - p a r e n t ( 子 − > 父 ) 和 c h i l d r e n / parent(子->父) 和 children/ parent(子−>父)和children/ref(父->子)
-
a
t
t
r
s
和
attrs和
attrs和listeners A->B->C
A->C B通过attrs拿到A值(除props),通过v-bind=“attrs”->C
C->A B通过$listeners监听C触发事件,C发出的数据传给A - provide和inject(多层)
父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量。不论子组件有多深,只要调用了inject那么就可以注入provider中的数据。而不是局限于只能从当前父组件的prop属性来获取数据,只要在父组件的生命周期内,子组件都可以调用。 - boradcast和dispatch
broadcast是向特定的父组件,触发事件,dispatch是向特定的子组件触发事件,本质上这种方式还是on和on和emit的封装 - 中央事件总线 (兄弟)
新建一个Vue事件bus对象,然后通过bus. e m i t 触 发 事 件 , b u s . emit触发事件,bus. emit触发事件,bus.on监听触发的事件。 - vuex处理组件之间的数据交互
父子组件生命周期的顺序
-
加载渲染过程
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted -
子组件更新过程
父beforeUpdate->子beforeUpdate->子updated->父updated -
父组件更新过程
父beforeUpdate->父updated -
销毁过程
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
生命周期, 父子生命周期的顺序
组件生命周期
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- activated keep-alive 组件激活时调用。
- deactivated keep-alive 组件停用时调用。
- beforeDestroy
- destroyed
Vue双向绑定
的数据响应是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty () 来
劫持各个属性的setter、getter,但是它并不算是实现数据的响应式的完美方案,某些情况下需要对其
进行修补或者hack这也是它的缺陷,主要表现在两个方面:
- vue 实例创建后,无法检测到对象属性的新增或删除,只能追踪到数据是否被修改
- 不能监听数组的变化
Vue3.0 实现数据双向绑定的方法
vue3.0 实现数据双向绑定是通过Proxy
Vuex
Vuex是专门为Vuejs应用程序设计的状态管理工具。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化
具体工作:vuex是一种状态管理机制,将全局组件的共享状态抽取出来为一个store,以一个单例模式存在,应用任何一个组件中都可以使用,vuex更改state的唯一途径是通过mutation,mutation需要commit触发, action实际触发是mutation,其中mutation处理同步任务,action处理异步任务。
vue-router 实现懒加载
结合 Vue 的异步组件和 Webpack 的代码分割功能,可以实现路由组件的懒加载
HashRouter 和 HistoryRouter的区别和原理
参考答案:
vue-router是Vue官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。 vue-router 默认 hash 模式,还有一种是history模式。
原理:
- hash路由:hash模式的工作原理是hashchange事件,可以在window监听hash的变化。我们在url后面随便添加一个#xx触发这个事件。vue-router默认的是hash模式—使用URL的hash来模拟一个完整的URL,于是当URL改变的时候,页面不会重新加载,也就是单页应用了,当#后面的hash发生变化,不会导致浏览器向服务器发出请求,浏览器不发出请求就不会刷新页面,并且会触发hasChange这个事件,通过监听hash值的变化来实现更新页面部分内容的操作对于hash模式会创建hashHistory对象,在访问不同的路由的时候,会发生两件事:
HashHistory.push()将新的路由添加到浏览器访问的历史的栈顶,和HasHistory.replace()替换到当前栈顶的路由 - history路由:
主要使用HTML5的pushState()和replaceState()这两个api结合window.popstate事件(监听浏览器前进后退)来实现的,pushState()可以改变url地址且不会发送请求,replaceState()可以读取历史记录栈,还可以对浏览器记录进行修改
操作系统
进程与线程的区别
进程是操作系统分配资源的单位,线程是CPU调度的基本单位,线程之间共享进程资源
- 一个程序至少有一个进程,一个进程至少有一个线程
- 线程的划分尺度小于进程,使得多线程程序的并发性高
- 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率
- 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制
- 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别
TCP(传输控制协议) vs UDP(用户数据报协议)
TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议,在不可靠的网络中提供一个可靠的端对端字节流。.
UDP是一种无连接的传输层协议,提供简单不可靠的非连接传输层服务,面向报文。
区别:
- TCP是面向连接的,可靠性高;UDP是基于非连接的,可靠性低
- 由于TCP是连接的通信,需要有三次握手、重新确认等连接过程,会有延时,实时性差,同时过程复杂,也使其易于攻击;UDP没有建立连接的过程,因而实时性较强,也稍安全
- 在传输相同大小的数据时,TCP首部开销20字节;UDP首部开销8字节,TCP报头比UDP复杂,故实际包含的用户数据较少。TCP在IP协议的基础上添加了序号机制、确认机制、超时重传机制等,保证了传输的可靠性,不会出现丢包或乱序,而UDP有丢包,故TCP开销大,UDP开销较小
- 每条TCP连接只能时点到点的;UDP支持一对一、一对多、多对一、多对多的交互通信
应用场景选择:
对实时性要求高和高速传输的场合下使用UDP;
在可靠性要求低,追求效率的情况下使用UDP;
需要传输大量数据且对可靠性要求高的情况下使用TCP。
OSI七层协议
OSI定义了网络互连的七层框架(物理层、数据链路层、网络层、传输层、会话层、表示层、应用层),即ISO开放互连系统参考模型。
1.应用层
作用:它是与其他计算机进行通信的应用,它是对应应用程序的通信服务的。各种应用软件,包括web应用。
协议:DNS、FTP、HTTP、SMTP、TELNET、IRC、WHOIS
2.表示层
作用:这一层的主要作用是定义数据格式和加密
3.会话层
作用:控制应用程序的会话能力,它定义了一段会话的开始、控制和结束,包括对多个双向消息的控制和管理,以便在只完成一部分消息时可以通知应用
4.传输层
作用:对差错恢复协议和无差错恢复协议的选择,对同一主机上不同数据流的输入进行复用,对数据包进行重新排序。是最关键的一层,是唯一负责整体的数据传输和数据控制的。对上三层提供可靠的传输服务,对网络层提供可靠的目的地信息。在这一层数据的单位被称为数据段。
协议:TCP、UDP等
5.网络层
作用:主要负责寻找地址和路由选择,网络层还可以实现阻塞控制、网际互联等。
协议:IP、IPX、RIP、OSPF等
6.数据链路层
作用:负责物理层面上的互联的、节点间的通信传输;该层的作用包括:物理地址寻址、数据的成帧、流量控制、数据的检错、重发等。在这一层,数据的单位称为帧(frame)
协议:ARP、RARP、SDLC、HDLC、PPP、STP、帧中继等
7.物理层
作用:负责0、1 比特流(0/1序列)与电压的高低、逛的闪灭之间的转换 规定了激活、维持、关闭通信端点之间的机械特性、电气特性、功能特性以及过程特性;该层为上层协议提供了一个传输数据的物理媒体。在这一层,数据的单位称为比特(bit)。
典型规范:EIA/TIA RS-232、EIA/TIA RS-449、V.35、RJ-45、fddi令牌环网等
优化
你如何对网站的文件和资源进行优化?
期待的解决方案包括:
- 文件合并
- 文件最小化/文件压缩
- 使用 CDN 托管
- 缓存的使用(多个域名来提供缓存)
- 其他
请说出三种减少页面加载时间的方法
- 优化图片
- 图像格式的选择(GIF:提供的颜色较少,可用在一些对颜色要求不高的地方)
- 优化CSS(压缩合并css,如 margin-top, margin-left…)
- 网址后加斜杠(如www.campr.com/目录,会判断这个目录是什么文件类型,或者是目录。)
- 标明高度和宽度(如果浏览器没有找到这两个参数,它需要一边下载图片一边计算大小,如果图片很多,浏览器需要不断地调整页面。这不但影响速度,也影响浏览体验。
- 减少http请求(合并文件,合并图片)
页面级优化(7个)
1、减少HTTP请求数
合理设置HTTP缓存:能缓存的越多越好,能缓存的越久越好。
资源合并和压缩:如果可以的话,尽可能的将外部的脚本、样式进行合并(CSS Sprites:合并css图片);另外css、js、image都可以用相应的工具进行压缩
Inline Images:使用data:URL scheme的方式将图片嵌入到页面或者CSS中
2、异步请求callback、异步执行脚本
3、Lazy Load Javascript:只有在需要加载的时候加载
随着js框架流行,越来越多的站点使用起了框架,不过一个框架往往包括很多的资源,这些功能并不是每个页面都需要的。为了节省资源和时间,目前有两种做法:mini版本和Lazy Load
4、避免重复的资源请求:这种情况主要是由于疏忽或者页面由多个模块拼接而成,然后每个模块都请求了同样的资源
测试代码性能的工具
- Profiler 内存分析工具
- JSPerf(http://jsperf.com/nexttick-vs-setzerotimeout-vs-settimeout)
- Dromaeo
js延迟加载的方式有哪些?
(关于js的延迟加载)的好处是有助于提高页面加载速度,js延迟加载就是等页面加载完成之后在加载js文件
- defer(按顺序依次执行)和async(不保证会按顺序执行)
- 动态创建DOM方式(创建script,插入到DOM中,加载完毕后callBack)
- 按需异步载入js
你有哪些性能优化的方法?
- 减少http请求次数:CSS Sprites, JS、CSS 源码压缩、图片大小控制合适;网页 Gzip,CDN 托管,data 缓存 ,图片服务器
- 前端模板 JS + 数据,减少由于HTML标签导致的带宽浪费,前端用变量保存 AJAX 请求结果,每次操作本地变量,不用请求,减少请求次数
- 用 innerHTML 代替 DOM 操作,减少 DOM 操作次数,优化 javascript 性能
- 当需要设置的样式很多时设置 className 而不是直接操作 style
- 少用全局变量、缓存DOM节点查找的结果。减少 IO 读取操作
- 避免使用 CSS Expression(css表达式)又称 Dynamic properties(动态属性)
- 图片预加载,将样式表放在顶部,将脚本放在底部,加上时间戳
更多推荐
所有评论(0)