前端面试题总结(持续更新中)

699 阅读43分钟

HTML 、HTTP 、web综合问题

前端需要注意哪些SEO

  • 合理的 title 、 description 、 keywords :搜索对着三项的权重逐个减小, title值强调重点即可, 重要关键词出现不要超过2次, 而且要靠前,不同⻚⾯ title 要有所不同; description 把⻚⾯内容高度概括, ⻓度合适,不可过分堆砌关键词,不同⻚⾯description 有所不同; keywords 列举出重要关键词即可;
  • 语义化的 HTML 代码,符合W3C规范:语义化代码让搜索引擎容易理解网⻚;
  • 重要内容 HTML 代码放在最前:搜索引擎抓取 HTML 顺序是从上到下, 有的搜索引擎对抓取⻓度有限制,保证重要内容⼀定会被抓取;
  • 重要内容不要用 js 输出:爬虫不会执⾏js获取内容;
  • 少用 iframe :搜索引擎不会抓取 iframe 中的内容;
  • ⾮装饰性图片必须加 alt;
  • 提高网站速度: 网站速度是搜索引擎排序的⼀个重要指标。

<img> 的 title 和 alt 有什么区别

  • 通常当鼠标滑动到元素上的时候显示;
  • alt 是<img>的特有属性, 是图片内容的等价描述,用于图片⽆法加载时显示 、读屏器 阅读图片。可提图片高可访问性, 除了纯装饰图片外都必须设置有意义的值, 搜索引擎会 重点分析

HTTP的几种请求方法用途

  • GET⽅法——发送⼀个请求来取得服务器上的某⼀资源
  • POST⽅法——向URL指定的资源提交数据或附加新的数据
  • PUT⽅法——跟POST⽅法很像,也是向服务器提交数据。但是,它们之间有不同。PUT 指定了资源在服务器上的位置, 而POST没有
  • HEAD⽅法——只请求页面的首部
  • DELETE⽅法——删除服务器上的某资源
  • OPTIONS⽅法——它用于获取当前 URL 所⽀持的⽅法 。如果请求成功,会有⼀个 Allow 的头包含类似 “GET,POST” 这样的信息
  • TRACE ⽅法——TRACE ⽅法被用于激发⼀个远程的,应用层的请求消息回路
  • CONNECT ⽅法——把请求连接转换到透明的 TCP/IP 通道

从浏览器地址栏输入url到显示页面的步骤

  • 浏览器根据请求的 URL 交给 DNS 域名解析,找到真实 IP , 向服务器发起请求;
  • 服务器交给后台处理完成后返回数据, 浏览器接收⽂件 ( HTML、JS、CSS 、图象等);
  • 浏览器对加载到的资源 ( HTML、JS、CSS 等) 进行语法解析, 建立相应的内部数据结构( 如 HTML 的 DOM );
  • 载⼊解析到的资源⽂件, 渲染页面, 完成。

语义化的理解

  • 用正确的标签做正确的事情
  • HTML 语义化就是让页面的内容结构化,便于对浏览器 、搜索引擎解析
  • 在没有样式 CSS 情况下也以⼀种⽂档格式显示, 并且是容易阅读的
  • 搜索引擎的爬虫依赖于标记来确定上下⽂和各个关键字的权重,利于 SEO
  • 使阅读源代码的⼈对网站更容易将网站分块,便于阅读维护理解

如何进行网站性能优化

content方面
  • 减少 HTTP 请求:合并文件 、 CSS 精灵 、 inline Image
  • 减少 DNS 查询: DNS 缓存 、将资源分布到恰当数量的主机名
  • 减少 DOM 元素数量
Server方面
  • 使用 CDN
  • 配置 ETag
  • 对组件使用 Gzip 压缩
Cookie方面
  • 减⼩ cookie 大⼩
css方面
  • 将样式表放到页面顶部
  • 不使用 CSS 表达式
  • 使用 < link> 不使用 @import
Javascript 方面
  • 将脚本放到页面底部
  • 将 javascript 和 css 从外部引⼊
  • 压缩 javascript 和 css
  • 删除不需要的脚本
  • 减少 DOM 访问
图片方面
  • 优化图片:根据实际颜色需要选择色深 、压缩
  • 优化 css 精灵
  • 不要在 HTML 中拉伸图片

HTTP状态码及其含义

1XX:信息状态码
  • 100 Continue 继续,⼀ 般在发送 post 请求时, 已发送了 http header 之后服务端将返回此信息,表示确认, 之后发送具体参数信息
2XX :成功状态码
  • 200 OK 正常返回信息
  • 201 Created 请求成功并且服务器创建了新的资源
  • 202 Accepted 服务器已接受请求,但尚未处理
3XX :重定向
  • 301 Moved Permanently 请求的网页已永久移动到新位置
  • 302 Found 临时性重定向
  • 303 See Other 临时性重定向,且总是使用 GET 请求新的 URI
  • 304 Not Modified 自从上次请求后,请求的网页未修改过
4XX :客户端错误
  • 400 Bad Request 服务器⽆法理解请求的格式,客户端不应当尝试再次使用相同的内容发起请求。
  • 401 Unauthorized 请求未授权
  • 403 Forbidden 禁止访问
  • 404 Not Found 找不到如何与 URI 相匹配的资源
5XX: 服务器错误
  • 500 Internal Server Error 最常⻅的服务器端错误
  • 503 Service Unavailable 服务器端暂时⽆法处理请求 ( 可能是过载或维护)

介绍⼀下你对浏览器内核的理解

主要分成两部分:渲染引擎(layout engineerRendering Engine)和 JS 引擎

  • 渲染引擎:负责取得网页的内容 ( HTML 、 XML 、图像等等) 、整理讯息 (例如加⼊CSS 等), 以及计算网页的显示⽅式,然后会输出至显示器或打印机 。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同 。所有网页浏览器 、电子邮件客户端以及其它需要编辑 、显示网络内容的应用程序都需要内核;
  • JS 引擎:解析和执⾏ javascript 来实现网页的动态效果; 最开始渲染引擎JS 引擎并没有区分的很明确,后来JS引擎越来越独立, 内核就倾向于只指渲染引擎

html5有哪些新特性、移除了那些元素

  1. HTML5 现在已经不是 SGML 的子集, 主要是关于图像,位置,存储, 多任务等功能的增加:
  • 绘画 canvas
  • 用于媒介回放的 videoaudio 元素
  • 本地离线存储localstorage长期存储数据,刘篮球关闭后数据不丢失
  • sessionStorage的数据在浏览器关闭后自动删除
  • 语义化更好的内容元素:比如article、footer、header、nav、section
  • 表单控件:calendar、date、time、email、url、search
  • 新的技术:webworker、websocket、Geolocation
  1. 移除的元素:
  • 纯表现的元素:basefont、big、center、font、s、strike、tt、 u
  • 对可用性产生负面影响的元素:frame、frameset、noframes
  1. 支持HTML5新标签:
  • IE8/IE7/IE6支持通过document.createElement方法产生的标签
  • 可以利用这一特性让这些浏览器支持HTML5标签
  • 浏览器支持新标签后,还需要添加标签默认的样式
  1. 当然也可以直接使用成熟的框架 、比如 html5shim

HTML5 的离线储存怎么使用, 工作原理能不能解释⼀下

  • 在用户没有与因特网连接时,可以正常访问站点与应用,在用户与因特网连接时,更新用户机器上的缓存文件
  • 原理:HTML5的离线存储是基于一个新建的.appcache文件的缓存机制(不是存储技术),通过这个文件上的解析清单离线存储资源,这些资源就会像cookie一样被存储了下来,之后当网络在处于离线状态下时,浏览器会通过被离线存储的数据进行页面展示
  • 如何使用
    • 页面头部像下面一样加入一个manifest的属性
    • cache.manifest文件的编写离线存储的资源
    • 在离线状态下操作window.applicationCache进行需求实现
CACHE MANIFEST
#v0.11
CACHE:
js/app.js
css/style.css
NETWORK:
resourse/logo.png
FALLBACK:
/offline.html

浏览器是怎么对 HTML5 的离线储存资源进行管理和加载的

  • 在线的情况下, 浏览器发现 html 头部有 manifest 属性, 它会请求 manifest 文件, 如果是第⼀次访问 app ,那么浏览器就会根据manifest文件的内容下载相应的资源并且进行离线存储 。如果已经访问过 app 并且资源已经离线存储了,那么浏览器就会使用离线的资源加载页面,然后浏览器会对比新的 manifest 文件与旧的 manifest 文件, 如果文件没有发生改变,就不做任何操作, 如果文件改变了,那么就会重新下载文件中的资源并进行离线存储;
  • 离线的情况下, 浏览器就直接使用离线存储的资源。

cookies , sessionStorage 和 localStorage 的区别

  • cookie是网站为了标识用户身份而存储在用户本地终端(Client Side)上的数据(通常通过加密)
  • cookie数据始终在同源的http请求中携带(即使不需要),记会在浏览器和服务器之间来回传递
  • sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存
  • 存储大小:
    • cookie数据大小不能超过4k
    • sessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,可以打到5M或者更大
  • 有效时间:
    • localStorage存储持久数据,浏览器关闭后数据不丢失除非主动删除数据
    • sessionStorage数据在当前浏览器窗口关闭后自动删除
    • cookie设置的cookie过期时间之前一直有效,即使窗口或者浏览器关闭

iframe的缺点

  • iframe会阻塞主页面的onload事件
  • 搜索引擎的检索程序无法解读这种页面,不利于SEO
  • iframe和主页面共享连接池,而浏览器对相同域的连接有限制,所以会影响页面的并行加载
  • 使用iframe之前需要考虑这两个缺点,如果需要使用iframe,最好是通过javascript动态给iframe添加src属性值,这样可以绕开以上两个问题

WEB标准以及W3C标准是什么

标签闭合、标签小写、不乱嵌套、使用外链css和js、结构行为表现分离

XHTML和HTML的区别

  • 功能上:XHTML可以兼容各大浏览器、手机以及PDA,并且浏览器也能快速正确地编译网页
  • 书写习惯上:XHTML元素必须正确地嵌套、闭合、区分大小写、文档必须拥有根元素

link和@import的区别

  • 页面被加载时,link会同时被加载;
  • @import页面被加载时,link会被同时加载,@import引用的css会等到页面被加载完再加载;
  • @import只在IE5以上才能识别,而link是XHTML标签,无兼容问题;
  • link方式的样式权重高于@import的权重。

Doctype作用?严格模式与混杂模式如何区分?

  • <!DOCTYPE>声明位于文档的最前面,处于html标签之前,告知浏览器的解析器,用什么文档类型规范来解析这个文档;
  • 严格模式的排版和JS运作模式是以浏览器支持的最高标准运行;
  • 混杂模式中,页面以宽松的向后兼容的方式显示,模拟老式浏览器的行为以防止站点无法工作;
  • DOCTYPE不存在或者格式不正确会导致文档以混杂模式呈现;

HTML5 为什么只需要写 <!DOCTYPE HTML>

  • HTML5 不基于 SGML , 因此不需要对 DTD 进⾏引用,但是需要 doctype 来规范浏览器的⾏为
  • 而 HTML4.01 基于 SGML ,所以需要对DTD 进⾏引用, 才能告知浏览器文档所使用的文档类型

行内元素有哪些?块级元素有哪些? 空(void)元素有那些?行内元素和块级元素有什么区别?

  • 行内元素:a b span img input select strong
  • 块级元素:div ul ol li dl dt dd h1 h2 h3 h4 h5 h6... p
  • 空元素:br hr img input link meta
  • 行内元素不可以设置宽高,不独占一行
  • 块级元素可以设置宽高,独占一行

HTML全局属性(global attribute)有哪些

  • class :为元素设置类标识
  • data- :为元素添加自定义属性
  • draggable :设置元素是否可拖拽
  • id :元素id,文档内唯一
  • lang :元素内容的语言
  • style :行内css样式
  • title :元素相关的建议信息

canvas和svg的区别

  • svg绘制出来的每一个图形的元素都是独立的DOM节点,能够方便的绑定时间或用来修改;canvas输出的事一整副画布;
  • svg输出的图形是矢量图形,后期可以修改参数来自由放大缩小,不会失真和锯齿;canvas输出标量画布,就像一张图片一样,放大会失真或者锯齿;

渐进增强和优雅降级之间的不同

  • 渐进增强:针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。
  • 优雅降级:一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。
  • 区别:优雅降级是从复杂的现状开始,并试图减少用户体验的供给,而渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要。降级(功能衰退)意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处理安全地带。

为什么利用多个域名来存储网站资源会更有效

  • CDN缓存更方便
  • 突破浏览器并发限制
  • 节约cookie带宽
  • 节约主域名的连接数量,优化页面响应速度
  • 防止不必要的安全问题

src和href的区别

  • src用于替换元素,href用于在当前文档和引用资源之间确立关系
  • src是source的缩写,指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置;在请求src资源时会将其指向的资源下载并应用到文档内,例如js脚本、img图片和iframe等元素。
<script src="js.js"></script>
// 当浏览器解析到该元素时,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,图片和框架等元素也如此,类似于将所指向资源嵌入当前标签内,这也是为什么将js脚本放在底部而不是头部。
  • href是Hypertext Reference的缩写,指向网络资源所在位置,建立和当前元素(锚点)或者当前文档(链接)之前的链接,如果在文档中添加<link href="css.css" rel="stylesheet" /> ,那么浏览器就会识别该文档为css文件,就会并行下载资源并且不会停止对当前文档的处理,这也是为什么建议使用link方式来加载css,而不是使用@import方式。

CSS问题

display:nonevisibility:hidden的区别

  • display:none会让元素完全从渲染树中消失,渲染的时候不占据任何空间;visibility:hidden不会让元素从渲染树中消失,渲染元素继续占据空间,只是内容不可见。
  • display:none是非继承性,子孙节点由于元素从渲染树中消失造成,通过修改子孙节点属性无法显示;visibility:hidden是继承属性,子孙节点消失由于继承了hidden,通过设置visibility:hidden可以让子孙节点显示。
  • 修改常规流中元素的display通常会造成文档重排,修改visibility属性只会造成元素的重绘。
  • 读屏器不会读取display:none的元素内容,会读取visibility:hidden的元素内容。

link和@import的区别

  • link是HTML方式,@import是CSS方式
  • link最大限度支持并行下载,@import过多嵌套导致串行下载,出现文档样式短暂失效
  • link可以通过rel="alternate stylesheet"制定候选样式
  • 浏览器对link支持早于@import,可以使用@import对老浏览器隐藏样式
  • @import必须在样式规则之前,可以在css文件中引用其他文件

FOUC

  • FOUC:Flash of unstayled content——用户定义样式表加载之前浏览器使用默认样式显示文档,用户样式加载渲染之后再从新显示文档,造成页面闪烁。
  • 解决办法:把样式表放到文档的<head>

如何创建块式化上下文

创建规则:

  • 根元素
  • 浮动元素
  • 绝对定位元素(position取值魏absolute或者fixed)
  • display取值为inline-block、table-cell、table-caption、flex、inline-flex的元素
  • overflow不取值为visible的元素

BFC的作用

  • 可以包含浮动元素
  • 不被浮动元素覆盖
  • 阻止父子元素的margin折叠

清楚浮动的几种方式

  • 父级div定义height

  • 结尾处加空div标签clear:both

  • 父级div定义伪类:after和zoom

  • 父级 div 定义 overflow:hidden

  • 父级 div 也浮动, 需要定义宽度

  • 结尾处加 br 标签 clear:both

css3有哪些新特性

  • 新增各种 css 选择器

  • 圆角 border-radius

  • 多列布局

  • 阴影和反射

  • 文字特效 text-shadow

  • 线性渐变

  • 旋转 transform

CSS3新增伪类

  • p:first-of-type 选择属于其父元素的首个<p> 元素的每个 <p> 元素。

  • p:last-of-type 选择属于其父元素的最后<p>元素的每个<p> 元素。

  • p:only-of-type 选择属于其父元素唯⼀的 <p>元素的每个 <p> 元素。

  • p:only-child 选择属于其父元素的唯⼀⼦元素的每个 <p> 元素。

  • p:nth-child(2) 选择属于其父元素的第⼆个⼦元素的每个 <p> 元素。

  • :after 在元素之前添加内容,也可以用来做清除浮动。

  • :before 在元素之后添加内容。

  • :enabled 已启用的表单元素。

  • :disabled 已禁用的表单元素。

  • :checked 单选框或复选框被选中。

display属性值

  • block转换成块状元素
  • inline转换成行内元素
  • none设置元素不可见
  • inline-block像行内元素一样显示,但是内容像块类型元素一样显示
  • list-item像块型元素一样显示,并添加样式列表标记
  • table元素会作为块级表格来显示
  • inherit规定应该从父元素继承display属性的值

标准的CSS的盒子模型和低版本IE的盒子模型有什么不同

  • 标准的CSS的盒模型: 内容(content)、填充( padding )、边界( margin )、 边框( border );
  • 区别:IE 的content 部分把 border 和 padding 计算了进去

CSS优先级算法如何计算

优先级为: !important > id > class > tag , !important 比 内联优先级高

position的值, relative和absolute定位原点

  • absolute:生成绝对定位的元素,相对于 static 定位以外的第⼀个父元素进行定位
  • fixed:生成绝对定位的元素,相对于浏览器窗⼝进行定位
  • relative:生成相对定位的元素,相对于其正常位置进行定位
  • static:默认值,没有定位,元素出现在正常的流中
  • inherit: 规定从父元素继承 position 属性的值

display:inline-block 什么时候不会显示间隙

  • 移除空格
  • 使用 margin 负值
  • 使用 font-size:0;
  • letter-spacing
  • word-spacing

CSS3动画 ( 简单动画的实现, 如旋转等)

  • 依靠 CSS3 中提出的三个属性: transition 、 transform 、 animation
  • transition:定义了元素在变化过程中是怎么样的, 包含 transition-property 、transition-duration 、 transition-timing-function 、 transition-delay
  • transform:定义元素的变化结果, 包含 rotate 、 scale 、 skew 、 translate
  • animation:动画定义了动作的每⼀帧 ( @keyframes ) 有什么效果, 包括 animation-name, animation-duration、 animation-timing-function、 animation-delay、 animation-iteration-count、 animation-direction

base64的原理及优缺点

  • 优点可以加密,减少了 HTTTP 请求
  • 缺点是需要消耗 CPU 进行编解码
  • base64 的使用:用于减少 HTTP 请求、适用于小图片、base64 的体积约为原图的 4/3

几种常见的css布局

伪类和伪元素的区别

  • 伪类表状态
  • 伪元素是真的有元素
  • 前者单冒号,后者双冒号

css实现一个简单的幻灯片

什么是外边距重叠?重叠的结果是什么?

外边距重叠就是margin-collapse;

  • 在CSS当中,相邻的两个盒子 ( 可能是兄弟关系也可能是祖先关系) 的外边距可以结合成⼀个单独的外边距 。这种合并外边距的方式被称为折叠, 并且因而所结合成的外边距称为折叠外边距。

折叠结果遵循下列计算规则:

  • 两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值
  • 两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值
  • 两个外边距⼀正⼀负时,折叠结果是两者的相加的和

rgba()和opacity的透明效果有什么不同

  • rgba() 和 opacity 都能实现透明效果,但最大的不同是 opacity 作用于元素, 以及元素内的所有内容的透明度
  • rgba() 只作用于元素的颜色或其背景色 。 ( 设置 rgba 透明的元素的子元素不会继承透明效果!)

css中可以让文字在垂直和水平方向上重叠的两个属性是什么

  • 垂直方向: line-height
  • 水平方向: letter-spacing

水平居中的方法

  • 元素为行内元素,设置父元素 text-align:center
  • 如果元素宽度固定, 可以设置左右 margin 为 auto ;
  • 如果元素为绝对定位,设置父元素 position 为 relative ,元素设left:0;right:0;margin:auto;
  • 使用 flex-box 布局,指定 justify-content 属性为center
  • display 设置为 tabel-ceil

垂直居中的方法

  • 将显示方式设置为表格, display:table-cell ,同时设置 vertial-align:middle
  • 使用 flex 布局,设置为 align-item:center
  • 绝对定位中设置 bottom:0,top:0 ,并设置 margin:auto
  • 绝对定位中固定高度时设置 top:50%,margin-top 值为高度⼀半的负值
  • 文本垂直居中设置 line-height 为 height 值

px和em的区别

  • px 和 em 都是长度单位,区别是:px的值是固定的,指定是多少就是多少,计算比较容易。 em的值不是固定的, 并且 em 会继承父级元素的字体大⼩ 。
  • 浏览器的默认字体高都是 16px 。所以未经调整的浏览器都符合: 1em=16px 。那么12px=0.75em,10px=0.625em

重绘和回流 ( 重排) 是什么, 如何避免

  • DOM的变化影响到了元素的⼏何属性 ( 宽高) ,浏览器重新计算元素的⼏何属性, 其他元素的⼏何属性和位置也会受到影响, 浏览器需要重新构造渲染树, 这个过程称为重排, 浏览器将受到影响的部分重新绘制到屏幕上的过程称为重绘
  • 引起重排的原因有:
    • 1)添加或者删除可见的DOM元素;
    • 2)元素位置 、尺⼨ 、内容改变;
    • 3)浏览器页面初始化;
    • 4)浏览器窗⼝尺⼨改变, 重排⼀定重绘, 重绘不⼀定重排
  • 减少重绘和重排的方法:
    • 1)不在布局信息改变时做 DOM 查询;
    • 2)使用 cssText 或者 className ⼀次性改变属性;
    • 3)使用 fragment;
    • 4)对于多次重排的元素, 如动画,使用绝对定位脱离文档流,让他的改变不影响到其他元素;

如何实现小于12px的字体效果

transform:scale()这个属性只可以缩放可以定义宽高的元素, 而⾏内元素是没有宽高的, 我们可以加上⼀个 display:inline-block;然后去缩放:transform: scale(0.7);

Javascript问题

javaScript(简称“JS”) 是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。虽然它是作为开发Web页面的脚本语言而出名,但是它也被用到了很多非浏览器环境中,JavaScript 基于原型编程、多范式的动态脚本语言,并且支持面向对象、命令式、声明式、函数式编程范式。

JavaScript的标准是ECMAScript 。截至 2012 年,所有浏览器都完整的支持ECMAScript 5.1,旧版本的浏览器至少支持ECMAScript 3 标准。2015年6月17日,ECMA国际组织发布了ECMAScript的第六版,该版本正式名称为 ECMAScript 2015,但通常被称为ECMAScript 6 或者ES2015。

Javascript包括哪些数据类型

在JavaScript中,数据类型分为:基本类型、复杂类型。区别是,两种类型的存储位置不同。

基本类型分为6种:Number、String、Boolean、Undefined、Null、Symbol。

复杂类型统称为Object,分为3种:Object、Array、Function。

除此之外,还有引用类型,包括Date、RegExp、Map、Set等......

  1. Undefined

Undefined类型只有一个值,即特殊值undefined。在使用var或者let声明变量,但未对其加以初始化时,这个变量值就是undefined。

  1. Null

Null类型是第二个只有一个值的数据类型。其特殊值就是Null。从逻辑角度上看,null是一个空的对象指针。而这也正是使用typeof操作符检测null值,会返回“object”的原因。

console.log(null == undefined); // true
  1. Boolean

布尔类型,该类型有两个值:true、false。需要注意的是,Boolean类型的字面值true和false是区分大小写的。也就是说,True和False(以及其它的混合大小形式)都不是Boolean值,只是标识符。

  1. Number

该类型的表示方法有两种形式,第一种是整数,第二种为浮点数。整数:可以通过十进制,八进制,十六进制的字面值来表示。浮点数:就是该数值中必须包含一个小数点,且小数点后必须有一位数字。

  1. String

String类型用于表示由零或多个16位的Unicode字符组成的字符序列,即字符串。至于用单引号,还是双引号,在js中还是没有差别的。记得成对出现。

  1. Symbol

符号 (Symbols) 是 ECMAScript 第 6 版新定义的。符号类型是唯一的并且是不可修改的。Symbol 函数前不能使用 new 命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。Symbol 函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述

  1. Object

Object数据类型,称为对象,是一组数据和功能(函数)的集合。可以用new操作符后跟要创建的对象类型的名称来创建。也可以用字面量表示法创建。在其中添加不同名(包含空字符串在内的任意字符串)的属性。

  1. Array

JavaScript 数组用方括号书写,数组的项目由逗号分隔。

  1. Function

ECMAScript中的函数是对象,与其他引用类型一样具有属性和方法。因此,函数名实际是一个指向函数对象的指针。

数据类型的转换

查看详情

==和===的区别

查看详情

JavaScript之堆与栈

堆和栈都是用来存储变量数据的,在JavaScript中变量分为两种,一种是基本类型(String,Number、Boolean、null、undefined、symbol(ES6)),一种是引用类型(Object、Array、Function)。

  • 基本类型:基本类型在内存中分别占有固定大小的空间,他们的值保存在栈中,我们通过按值来访问的。
  • 引用类型:引用类型指的是那些保存在堆内存中的对象,值的大小不固定。栈内存中存放地址,地址指向堆内存中的对象,是按引用访问的。
  • 栈内存中存放的只是引用类型的访问地址,在堆内存中为引用类型的值分配空间。由于这种值的大小不固定,因此不能把它们保存到栈内存中。但内存地址大小的固定的,因此可以将内存地址保存在栈内存中。
  • 当查询引用类型的变量时, 先从栈中读取内存地址, 然后再通过地址找到堆中的值。对于这种,我们把它叫做按引用访问。

堆和栈的意义:

堆和栈的出现通常与垃圾回收机制有关。为了使程序运行时占用的内存最小,及时进行变量销毁。

当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块内存栈里,随着方法执行结束,这个方法的内存栈也将自然销毁了。因此,所有在方法中定义的变量都是放在栈内存中的;

当我们在程序中创建一个对象时,这个对象地址将被保存到栈中,值将被保存到堆内存。堆内存中的对象不会随方法的结束而销毁。当方法结束后,如果这个对象被另一个引用变量所引用,则这个对象依然不会被销毁,只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。

JavaScript的数据结构

数据结构是计算机存储、组织数据的方式。

数据结构意味着接口或封装:一个数据结构可被视为两个函数之间的接口,或者是由数据类型联合组成的存储内容的访问方法封装。

我们每天的编码中都会用到数据结构,数组是最简单的内存数据结构。 下面是常见的数据结构:

  1. 数组(Array)
  2. 栈 (Stack)
  3. 队列 (Queue)
  4. 链表 (Linked List)
  5. 字典
  6. 散列表 (Hash table)
  7. 树 (Tree)
  8. 图(Graph)
  9. 堆(Heap)

闭包

闭包就是能够读取其他函数内部变量的函数。

闭包是指有权访问另⼀个函数作用域中变量的函数,创建闭包的最常⻅的方式就是在⼀个函数内创建另⼀个函数, 通过另⼀个函数访问这个函数的局部变量,利用闭包可以突破作用链域。

闭包的特性:

  • 函数内再嵌套函数
  • 内部函数可以引用外层的参数和变量
  • 参数和变量不会被垃圾回收机制回收

说说你对闭包的理解:

  • 使用闭包主要是为了设计私有的方法和变量 。闭包的优点是可以避免全局变量的污染, 缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露 。在js中, 函数即闭包, 只有函数才会产生作用域的概念;
  • 闭包 的最大用处有两个,⼀个是可以读取函数内部的变量, 另⼀个就是让这些变量始终保持在内存中;闭包的另⼀个用处, 是封装对象的私有属性和私有方法;
  • 好处:能够实现封装和缓存等;坏处:就是消耗内存 、不正当使用会造成内存溢出的问题

使用闭包的注意点:

  • 由于闭包会使得函数中的变量都被保存在内存中, 内存消耗很大,所以不能滥用闭包, 否 则会造成网页的性能问题,在IE中可能导致内存泄露;
  • 解决方法是,在退出函数之前,将不使用的局部变量全部删除。

说说你对作用域链的理解

作用域链的作用是保证执⾏环境里有权访问的变量和函数是有序的,作用域链的变量只能向上访问, 变量访问到 window 对象即被终止,作用域链向下访问变量是不被允许的;

简单的说,作用域就是变量与函数的可访问范围, 即作用域控制着变量与函数的可⻅性和生命周期。

JavaScript原型,原型链 ? 有什么特点?

  • 每个对象都会在其内部初始化⼀个属性,就是 prototype (原型), 当我们访问⼀个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去 prototype 里找这个属性, 这个prototype ⼜会有自⼰的 prototype , 于是就这样⼀直找下去,也就是我们平时所说的原型链的概念。
  • 关系:instance.constructor.prototype = instance.__proto__
  • 特点:
    • JavaScript 对象是通过引用来传递的, 我们创建的每个新对象实体中并没有⼀份属于自⼰的原型副本 。当我们修改原型时,与之相关的对象也会继承这⼀改变;
    • 当我们需要⼀个属性的时,Javascript 引擎会先看当前对象中是否有这个属性, 如果没有的就会查找他的 Prototype对象是否有这个属性, 如此递推下去,⼀直检索到 Object 内建对象。

Javascript如何实现继承?

  • 构造继承
  • 原型继承
  • 实例继承
  • 拷贝继承
  • 原型 prototype 机制或 apply 和 call 方法去实现较简单, 建议使用构造函数与原型混合方式
function Parent(){
  this.name = 'wang';
}
function Child(){
  this.age = 28;
}
Child.prototype = new Parent();//继承了Parent,通过原型
var demo = new Child();
alert(demo.age);
alert(demo.name);//得到被继承的属性

谈谈this对象的理解

  • this 总是指向函数的直接调用者 ( 而非间接调用者)
  • 如果有 new 关键字, this 指向 new 出来的那个对象
  • 在事件中, this 指向触发这个事件的对象, 特殊的是,IE 中的 attachEvent 中的this 总是指向全局对象 Window

函数中this的指向

  • this的指向在函数定义的时候是确定不了的, 只有函数执⾏的时候才能确定this到底指向谁, 实际上this的最终指向的是那个调用它的对象;

《 javascript语⾔精髓》 中大概概括了4种调用方式:方法调用模式、函数调用模式、构造器调用模式、apply/call调用模式。

事件模型

W3C 中定义事件的发生经历三个阶段:捕获阶段 (capturing) 、 目标阶段 (targetin) 、冒泡阶段 (bubbling)。

  • 冒泡型事件: 当你使用事件冒泡时, 子级元素先触发, 父级元素后触发
  • 捕获型事件: 当你使用事件捕获时, 父级元素先触发, 子级元素后触发
  • DOM 事件流: 同时支持两种事件模型:捕获型事件和冒泡型事件
  • 阻止冒泡:在 W3c 中,使用 stopPropagation() 方法;在IE下设置 cancelBubble =true
  • 阻止捕获:阻止事件的默认行为,例如 click - <a> 后的跳转 。在 W3c 中,使用preventDefault() 方法,在 IE 下设置 window.event.returnValue = false

new操作符具体干了什么

  • 创建⼀个空对象, 并且 this 变量引用该对象, 同时还继承了该函数的原型
  • 属性和方法被加⼊到 this 引用的对象中
  • 新创建的对象由 this 所引用, 并且最后隐式的返回 this

Ajax原理

Ajax 的原理简单来说是在用户和服务器之间加了—个中间层( AJAX 引擎), 通过 XmlHttpRequest 对象来向服务器发异步请求,从服务器获得数据,然后用 javascript 来操作 DOM 而更新页面 ,使用户操作与服务器响应异步化 ,这其中最关键的⼀步就是从服 务器获得请求数据。

Ajax的过程只涉及 JavaScript 、 XMLHttpRequest 和 DOM , XMLHttpRequest 是 ajax的核⼼机制。

/** 1. 创建连接 **/
var xhr = null;
xhr = new XMLHttpRequest();
/** 2. 连接服务器 **/
xhr.open( 'get', url, true);
/** 3. 发送请求 **/
xhr.send(null);
/** 4. 接受请求 **/
xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
        if(xhr.status == 200){
          success(xhr.responseText);
        } else {
           fail && fail(xhr.status);
        }
    }
}

ajax 有那些优缺点?

优点:

  • 通过异步模式,提升了用户体验.
  • 优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用
  • Ajax 在客户端运行,承担了⼀部分本来由服务器承担的⼯作,减少了大用户量下的服务器负载。
  • Ajax 可以实现动态不刷新 (局部刷新)

缺点:

  • 安全问题 AJAX 暴露了与服务器交互的细节
  • 对搜索引擎的支持比较弱
  • 不容易调试

如何解决跨域问题

首先了解下浏览器的同源策略 同源策略 /SOP ( Same origin policy) 是⼀种约定, 由Netscape公司1995年引⼊浏览器, 它是浏览器最核⼼也最基本的安全功能, 如果缺少了同源策略, 浏览器很容易受到 XSS 、 CSFR 等攻击 。所谓同源是指"协议+域名+端口"三者相同, 即便两个不同的域名指向同⼀个ip地址,也非同源。

  1. 通过jsonp跨域
  2. document.domain + iframe跨域
  3. nginx代理跨域
  4. nodejs中间件代理跨域
  5. 后端在头部信息里面设置安全域名

那些操作会造成内存泄漏

  • 内存泄漏指任何对象在您不再拥有或需要它之后仍然存在
  • setTimeout 的第⼀个参数使用字符串而非函数的话,会引发内存泄漏
  • 闭包使用不当

XML和JSON的区别

  • 数据体积方面:JSON 相对 于XML 来讲,数据的体积⼩,传递的速度更快些。
  • 数据交互方面:JSON 与 JavaScript 的交互更加方便,更容易解析处理,更好的数据交互。
  • 数据描述方面:JSON 对数据的描述性比 XML 较差。
  • 传输速度方面:JSON 的速度要远远快于 XML。

对webpack的看法

WebPack 是⼀个模块打包⼯具,你可以使用 WebPack 管理你的模块依赖, 并编绎输出模块们所需的静态文件 。它能够很好地管理 、打包 Web 开发中所用到的 HTML 、Javascript 、 CSS 以及各种静态文件 ( 图片 、字体等), 让开发过程更加高效,对于不同类型的资源, webpack 有对应的模块加载器 , webpack 模块打包器会分析模块间的 依赖关系, 最后生成了优化且合并后的静态资源。

对AMD和Commonjs的理解

  • CommonJS 是服务器端模块的规范, Node.js 采用了这个规范 。 CommonJS 规范加载模块是同步的,也就是说, 只有加载完成,才能执⾏后面的操作。AMD 规范则是非同步加载模块, 允许指定回调函数;
  • AMD 推荐的⻛格通过返回⼀个对象做为模块对象, CommonJS 的⻛格通过对module.exports 或 exports 的属性赋值来达到暴露模块对象的目的。
  • CommonJS 的规范中,每个 JavaScript ⽂件就是⼀个独立的模块上下⽂ ( module context ), 在这个上下⽂中默认创建的属性都是私有的 。也就是说,在⼀个⽂件定义的变量 ( 还包括函数和类), 都是私有的,对其他⽂件是不可⻅的。
  • CommonJS 是同步加载模块,在浏览器中会出现堵塞情况,所以不适用AMD 异步, 需要定义回调 define ⽅式,es6 ⼀个模块就是⼀个独立的⽂件,该⽂件内部的所有变量,外部⽆法获取 。如果你希望外部能够读取模块内部的某个变量,就必须使用 export 关键字输出该变量 。
  • es6 还可以导出类 、⽅法, 自动适用严格模式。

为什么要有同源限制

同源策略指的是:协议, 域名,端⼝相同, 同源策略是⼀种安全协议。

举例说明: 比如⼀个黑客程序,他利用 Iframe 把真正的银⾏登录页面嵌到他的页面上,当你使用真实的用户名,密码登录时,他的页面就可以通过 Javascript 读取到你的表单中 input 中的内容, 这样用户名,密码就轻松到手了。

offsetWidth/offsetHeight/clientWidth/clientHeight与scrollWidth/scrollHeight的区别

  • offsetWidth/offsetHeight 返回值包含content + padding + border,效果与e.getBoundingClientRect()相同
  • clientWidth/clientHeight 返回值只包含content + padding, 不包括border值和滚动条的大小
  • scrollWidth/scrollHeight 返回值包含content + padding + 溢出内容的尺寸

javascript有哪些方法定义对象

  • 对象字面量: var obj = {};
  • 构造函数: var obj = new Object();
  • Object.create(): var obj = Object.create(Object.prototype);

对promise的了解

依照 Promise/A+ 的定义, Promise 有四种状态:

  1. pending: 初始状态, 非 fulfilled 或 rejected。
  2. fulfilled: 成功的操作。
  3. rejected: 失败的操作。
  4. settled: Promise 已被 fulfilled 或 rejected ,且不是 pending。 (fulfilled 与 rejected ⼀起合称 settled)

构造⼀个 Promise , 最基本的用法:

var promise = new Promise(function(resolve, reject) {
if (...) { 
// succeed
    resolve(result);
} else {
// fails
    reject(Error(errMessage));
    }
});

Promise 实例拥有 then 方法 ( 具有 then 方法的对象, 通常被称为 thenable ) 。 它的使用方法如下:

promise.then(onFulfilled, onRejected)

接收两个函数作为参数,⼀个在fulfilled 的时候被调用,⼀个在 rejected 的时候被调用,接收参数就是 future ,onFulfilled 对应 resolve , onRejected 对应reject。

vue 、react 、angular

  • Vue.js ⼀个用于创建 web 交互界面的库, 是⼀个精简的 MVVM 。它通过双向数据绑定把 View 层和 Model 层连接了起来 。实际的 DOM 封装和输出格式都被抽象为了Directives 和 Filters;
  • AngularJS 是⼀个比较完善的前端 MVVM 框架, 包含模板,数据双向绑定,路由,模块化, 服务,依赖注⼊等所有功能,模板功能强大丰富, 自带了丰富的 Angular 指令。
  • React 仅仅是 VIEW 层是 facebook 公司推出的⼀个用于构建 UI 的⼀个库, 能够实现服务器端的渲染,用了 virtual dom (虚拟dom),所以性能很好。

Node的应用场景

特点:

  1. 它是⼀个 Javascript 运⾏环境
  2. 依赖于 Chrome V8 引擎进⾏代码解释
  3. 事件驱动
  4. 非阻塞 I/O
  5. 单进程, 单线程

优点:高并发 ( 最重要的优点)

缺点:只⽀持单核 CPU ,不能充分利用 CPU;可靠性低,⼀ 旦代码某个环节崩溃,整个系统都崩溃

js有哪些内置对象

  • Object 是 JavaScript 中所有对象的父对象
  • 数据封装类对象: Object 、 Array 、 Boolean 、 Number 和 String
  • 其他对象: Function 、 Arguments 、 Math 、 Date 、 RegExp 、 Error

几条写JavaScript的基本规范

  • 不要在同⼀行声明多个变量
  • 请使用 ===/!== 来比较 true/false 或者数值
  • 使用对象字面量替代 new Array 这种形式
  • 不要使用全局函数
  • Switch 语句必须带有 default 分支
  • If 语句必须使用大括号
  • or-in 循环中的变量 应该使用 var 关键字明确限定作用域,从而避免作用域污

javascript 代码中的"use strict"是什么意思

use strict 是⼀种 ECMAscript 5 添加的 (严格) 运⾏模式,这种模式使得 Javascript在更严格的条件下运⾏ ,使 JS 编码更加规范化的模式,消除 Javascript 语法的⼀些不合理 、不严谨之处,减少⼀些怪异⾏为。

严格模式的限制:

  • 变量必须声明后再使用
  • 函数的参数不能有同名属性, 否则报错
  • 不能使用 with 语句
  • 禁止 this 指向全局对象

JSON 的了解

JSON(JavaScript Object Notation) 是⼀种轻量级的数据交换格式,是基于 JavaScript 的⼀个⼦集 。数据格式简单, 易于读写, 占用带宽⼩。

  • JSON 字符串转换为JSON对象:
var obj = str.parseJSON();
var obj = JSON.parse(str);
  • JSON 对象转换为JSON字符串:
var last = obj.toJSONString();
var last = JSON.stringify(obj);

js延迟加载的方式有哪些

defer 和 async 、动态创建 DOM 方式 ( 用得最多) 、按需异步载⼊ js。

同步和异步的区别

  • 同步:浏览器访问服务器请求,用户看得到页面刷新, 重新发请求,等请求完, 页面刷新,新内容出现,用户看到新内容,进⾏下⼀步操作
  • 异步:浏览器访问服务器请求,用户正常操作, 浏览器后端进⾏请求,等请求完, 页面不刷新,新内容也会出现,用户看到新内容

对ES6的理解

  • 新增模板字符串 ( 为 JavaScript 提供了简单的字符串插值功能)
  • 箭头函数
  • for-of ( 用来遍历数据—例如数组中的值 )
  • arguments 对象可被不定参数和默认参数完美代替
  • ES6 将p romise 对象纳⼊规范,提供了原生的 Promise 对象
  • 增加了 let 和 const 命令,用来声明变量
  • 增加了块级作用域

面向对象编程、面向过程编程

  • 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤⼀步⼀步实现,使用的时候⼀个⼀个依次调用就可以了
  • 面向对象是把构成问题事务分解成各个对象, 建立对象的目的不是为了完成⼀个步骤, 而是为了描叙某个事物在整个解决问题的步骤中的⾏为,面向对象是以功能来划分问题, 而不是步骤。

对web标准、可用性、可访问性的理解

  • 可用性 ( Usability): 产品是否容易上⼿ ,用户能否完成任务,效率如何, 以及这过程中 用户的主观感受可好; 从用户的⻆度来看产品的质量 ,可用性好意味着产品质量高, 是企业的核⼼竞争⼒

  • 可访问性 (Accessibility): Web内容对于残障用户的可阅读和可理解性

  • 可维护性 ( Maintainability):⼀般包含两个层次,⼀ 是当系统出现问题时,快速定位并解 决问题的成本,成本低则可维护性好 。⼆是代码是否容易被⼈理解, 是否容易修改和增强功能。

如何通过JS判断⼀个数组

  1. instanceof方法 instanceof运算符是用来测试一个对象是否在其原型链原型构造函数的属性。
var arr = [];
arr instanceof Array; // true
  1. constructor方法 constructor属性返回对创建此对象的数组函数的引用,就是返回对象相应的构造函数;
var arr = [];
arr.constructor === Array;
  1. isArray()
var a = new Array(123);
var b = new Date();
console.log(Array.isArray(a)); //true
console.log(Array.isArray(b)); // false

let与var的区别

  • let 命令不存在变量提升, 如果在 let 前使用,会导致报错
  • 如果块区中存在 let 和 const 命令,就会形成封闭作用域
  • 不允许重复声明, 因此,不能在函数内部重新声明参数

map与forEach的区别

  • forEach 方法, 是最基本的方法,就是遍历与循环, 默认有3个传参:分别是遍历的数组内容 item 、数组索引 index 、和当前遍历数组 Array
  • map 方法, 基本用法与 forEach ⼀致,但是不同的, 它会返回⼀个新的数组,所以在callback需要有 return 值, 如果没有,会返回 undefined

函数式编程的理解

简单说, "函数式编程"是⼀种"编程范式" ( programming paradigm), 也就是如何编写程序的方法论;它具有以下特性: 闭包和高阶函数 、惰性计算 、递归 、函数是"第⼀等公民"、只用"表达式。

箭头函数与普通函数的区别

  • 函数体内的 this 对象,就是定义时所在的对象, 而不是使用时所在的对象
  • 不可以当作构造函数,也就是说,不可以使用 new 命令, 否则会抛出⼀个错误
  • 不可以使用 arguments 对象,该对象在函数体内不存在 ;如果要用, 可以用 Rest 参数代替
  • 不可以使用 yield 命令, 因此箭头函数不能用作 Generator 函数

异步编程的实现方式

  1. 回调函数
  • 优点:简单 、容易理解
  • 缺点:不利于维护,代码耦合高
  1. 事件监听(采用时间驱动模式, 取决于某个事件是否发生)
  • 优点:容易理解, 可以绑定多个事件,每个事件可以指定多个回调函数
  • 缺点:事件驱动型, 流程不够清晰
  1. 发布/订阅(观察者模式)
  • 类似于事件监听,但是可以通过‘消息中心ʼ, 了解现在有多少发布者, 多少订阅者
  1. Promise对象
  • 优点:可以利用then方法, 进行链式写法;可以书写错误时的回调函数;
  • 缺点:编写和理解,相对比较难
  1. Generator函数
  • 优点: 函数体内外的数据交换 、错误处理机制
  • 缺点:流程管理不方便
  1. async函数
  • 优点: 内置执行器 、更好的语义 、更广的适用性 、返回的是Promise、结构清晰。
  • 缺点:错误处理机制

addEventListener()和attachEvent()的区别

  • addEventListener() 是符合W3C规范的标准方法,attachEvent() 是IE低版本的非标准方法

  • addEventListener() 支持事件冒泡和事件捕获,而 attachEvent() 只支持事件冒泡

  • addEventListener() 的第⼀个参数中,事件类型不需要添加 on;attachEvent() 需要添加 'on'

  • 如果为同⼀个元素绑定多个事件,addEventListener() 会按照事件绑定的顺序依次执行,attachEvent() 会按照事件绑定的顺序倒序执行

数组去重方法总结

  • 利用ES6 Set去重 (ES6中最常用)
function uniqueArr(arr) {
  return Array.from(new Set(arr))
}
// 简化写法
function uniqueArr(arr) {
  return [...new Set(arr)]
}
var arr = [1,1,1,1,3,3,3,5,6,6,false,false, null, undefined, undefined,100];
console.log(uniqueArr(arr)); // [1, 3, 5, 6, false, null, undefined, 100]
  • for嵌套for,然后splice去重 (ES5中最常用)
function uniqueArr (arr) {
  for (var i = 0; i < arr.length; i++) {
    for (var j = i + 1; j < arr.length; j++) {
      if (arr[i] == arr[j]) {
        arr.splice (j, 1);
        j--;
      }
    }
  }
  return arr;
}
var arr = [1,1,1,1,3,3,3,5,6,6,false,false, null, undefined, undefined,100];
console.log (uniqueArr (arr)); // [1, 3, 5, 6, false, null, undefined, 100]
  • indexOf去重
function uniqueArr (arr) {
  var brr = [];
  for (i = 0; i < arr.length; i++) {
    // 判断语句
    // indexOf()返回-1时,说明没有重复,如果有返回索引值
    if (brr.indexOf (arr[i]) == -1) {
      // 不重复在新数组中追加新元素
      brr.push (arr[i]);
    }
  }
  return brr;
}
var arr = [1,1,1,1,3,3,3,5,6,6,false,false, null, undefined, undefined,100];
console.log (uniqueArr(arr)); // [1, 3, 5, 6, false, null, undefined, 100]
  • sort()
function uniqueArr(arr) {
    arr = arr.sort();
    var brr = [];
    for (var i = 0; i < arr.length; i++) {
      if (arr[i] !== arr[i - 1]) {
          brr.push(arr[i])
      }
    }
    return brr;
}
var arr = [1,1,1,1,3,3,3,5,6,6,false,false, null, undefined, undefined,100];
console.log (uniqueArr(arr)); // [1, 3, 5, 6, false, null, undefined, 100]
  • includes
function uniqueArr(arr) {
  var array = [];
  for (var i = 0; i < arr.length; i++) {
    if (!array.includes(arr[i])) {
      array.push(arr[i])
    }
  }
  return array;
}
var arr = [1,1,1,1,3,3,3,5,6,6,false,false, null, undefined, undefined,100];
console.log (uniqueArr(arr)); // [1, 3, 5, 6, false, null, undefined, 100]
  • hasOwnProperty
  • filter
  • 递归
  • Map
  • reduce+inclueds

Vue

对vue生命周期的理解

vue生命周期总共分为8个阶段:创建前/后、载入前/后、更新前/后、销毁前/后。

生命周期描述
beforeCreate组件实例被创建前
created组件实例创建后
beforeMount组件挂载之前
mounted组件挂载到实例上去后
beforeUpdate组件数据发生变化,更新之前
updated组件数据更新之后
beforeDestroy组件实例销毁之前
destroyed组件实例销毁之后
activatedkeep-alive缓存的组件激活时    
deactivatedkeep-alive缓存的组件停用时调用
errorCaptured捕获一个来自子孙组件的错误时被调用
  1. beforeCreate→created

    初始化vue实例,进行数据观测。

  2. created

    完成数据检测,属性与方法的预算,可以在created调用methods中的方法,访问和修改data数据触发响应式渲染,可以通过computed和watch完成数据计算;这时候vm.$el并没有被创建。

  3. created→beforeMount

    判断是否存在el选项,不存在则停止编译,直到调用vm.$mount(el)才会继续编译。

  4. beforeMount

    这时候可获取到vm.el,vm.el已经完成dom初始化,并未挂载到el选项上。

  5. mounted

    vm.el已完成dom的挂载与渲染。

  6. beforeUpdate

    更新的数据必须是被渲染在模板上的,此时的view层还未更新,在这个阶段修改数据,不会触发更新方法。

  7. updated

    完成view的更新,在这个阶段修改数据,会再次触发更新方法。

  8. beforeDestroy

    实例被销毁前调用,此时实例属性与方法可以访问。

  9. destroyed

    完全销毁一个实例,解绑它的全部指令和事件监听器,并不能消除dom。

使用场景

生命周期描述
beforeCreate执行时组件实例还未创建,通常用于插件开发中执行一些初始化任务。
created组件初始化完毕,各种数据可以使用,常用于异步获取数据
mounted初始化结束,dom创建,用于获取数据和dom元素
beforeDestroy销毁前,可用于一些定时器或者订阅的取消

vue2和vue3生命周期的对比

vue2vue3
beforeCreatesetup
createdsetup
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeDestroyonBeforeUnmount
destroyedonUnmounted
activatedonActivated
deactivatedonDeactivated
errorCapturedonErrorCaptured

created和mounted的区别

  1. created在组件实例创建完成的时候调用,这时候页面节点dom节点并未生成;

  2. mounted在页面dom节点渲染完成后立刻执行的,时间上,created的触发比mounted早。

  3. 放在mounted中的请求有可能导致页面闪动,建议对页面内容的改动放在created中。

  4. 相同点:都能拿到实例对象的属性和方法。

Vue组件之间的通信方式有哪些

  1.  props传递通信
  2. $emit触发自定义事件通信
  3. 使用ref
  4. EventBus
  5. parent/parent / children
  6. attrs、listeners
  7. Provide、Inject
  8. Vuex

1. props传递通信

适用场景:父组件传递数据给子组件;

使用方法:子组件设置props属性,定义接受父组件传递过来的参数,父组件在使用子组件标签中通过字面量来传递值。

// 子组件 child.vue
<template>
   <div id="child">
       <p>{{msg}}</p>
       <button @click="getMsg">按钮</button>
   </div>
 </template>
<script>
export default {
    name: "child",
    // 数组形式接收
    props: ["msg", "getMsg"],
};
</script>
// 接收参数的对象形式写法
props: {
  // 对象形式传递
  info: {
    type: Object,
    require: true, // 必传
    default: {
      name: '',
    }
   },
   // 字符串形式传递
   name: String
 }
// 父组件中需要先import引入,再在页面中使用
<template>
  <div id="father">
    <child :msg="msg" :getMsg="createMsg"></child>
  </div>
</template>

<script>
import child from "./child.vue";
export default {
   name: "father",
   components: {
       child
    },
    data() {
      msg: "你好";
    },
    methods: {
      createMsg() {
        console.log("你好,我是一个方法");
      }
    }
};
</script>

2. $emit触发自定义事件通信

适用场景:子组件传递数据给父组件;
使用方法:子组件通过$emit触发自定义时间,emit的第二个参数为传递的数值,父组件绑定监听器获取到子组件传递过来的参数。

// 子组件
this.$emit('getInfoName','张三');

// 父组件
<child @getInfoName="getName"></child>

getName(value) {
  console.log(value);
}

3. ref

使用方法:父组件在使用子组件的时候来设置ref,以此来获取数据。

// 父组件
<child ref="info"></child>

// 获取子组件实例
console.log(this.$refs.info);

4. EventBus

适用场景:兄弟组件传值;

使用方法:创建一个中央事件总线EventBus,兄弟组件通过emit触发自定义事件,emit的第二个参数为传递的数值,另外一个兄弟组件通过emit触发自定义事件,emit的第二个参数为传递的数值,另外一个兄弟组件通过on监听自定义事件。

// eventBus.js
import Vue from 'vue'
export const EventBus = new Vue()
// 引入childOne和childTwo兄弟组件
<template>
    <div>
      <child-one></child-one>
      <child-two></child-two>
    </div>
</template>

<script>
import childOne from './childOne.vue'
import childTwo from './childTwo.vue'
export default {
  components: { childOne, childTwo}
}
</script>
// childOne.vue
<template>
  <div>
    <button @click="getName">获取名字</button>    
  </div>
</template>

<script>
import { EventBus } from './eventBus.js' // 引入事件中心
export default {
  data(){
    return{
      name: ''张三
    }
  },
  methods:{
    getName(){
      EventBus.$emit('getName', {
        name: this.name
      })
    }
  }
}
</script>
// childTwo.vue
<template>
  <div>{{name}}</div>
</template>
<script>
import { EventBus } from './eventBus.js'
export default {
  data() {
    return {
      name: ''
    }
  },
  mounted() {
    EventBus.$on('getName', param => {
      this.name = param.name;
    })
  }
}
</script>

相当于将name的值存贮在了事件总线中,在其他组件中可以直接访问。事件总线就相当于一个桥梁,通过它来通信。

5. parent/parent / children

使用 parent可以让组件访问父组件的实例,使用parent可以让组件访问父组件的实例,使用 children 可以让组件访问子组件的实例。

// child.vue
<template>
  <div>
    <div>{{msg}}</div>
    <div>父组件的值为:  {{parentVal}}</div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      msg: 'Vue'
    }
  },
  computed:{
    parentVal(){
      return this.$parent.msg;
    }
  }
}
</script>
// parent.vue
<template>
  <div class="app">
     <div>{{msg}}</div>
     <child></child>
     <button @click="change">点击改变子组件值</button>
  </div>
</template>
<script>
import child from './child.vue'
export default {
  components: { child },
  data() {
    return {
      msg: 'Hello'
    }
  },
  methods: {
    change() {
      // 获取到子组件
      this.$children[0].msg= 'VueVue'
    }
  }
}
</script>

6. attrs、listeners

使用场景:祖先传递数据给子孙;

// 父组件
<template>
  <child :name="name" :age="age" @updateInfo="updateInfo" />
</template>
<script>
import Child from './child.vue'
export default {
     name: 'father',
     components: { Child },
     data () {
        return {
           name: '绘梨衣',
           age: 27
         }
        },
      methods: {
         updateInfo() {
             console.log('update info');
          },
      }
}
</script>
// 子组件
// 通过 $listeners 将父作用域中的事件,
// 传入 grandSon 组件,使其可以获取到 father 中的事件
<template>
   <grand-son :weight="weight" @addInfo="addInfo" v-bind="$attrs" v-on="$listeners"  />
</template>
<script>
import GrandSon from './grandSon.vue'
export default {
    name: 'child',
    components: { GrandSon },
    props: ['name'],
    data() {
        return {
           weight: '55kg'
        };
     }
    created() {
      // 结果age
    // 因为父组件共传来name, age,由于name被 props接收了,所以只有age属性
       console.log(this.$attrs);
       console.log(this.$listeners); 
       // updateInfo: f, delInfo: f
     },
     methods: {
         addInfo () {
            console.log('add info')
         }
     }
 }
</script>
// 孙子组件
<template>
    <div>
        {{ $attrs }} — {{ $listeners }}
    <div>
</template>
<script>
    export default {
        props: ['weight'],
        created() {
            console.log(this.$attrs); // age
            console.log(this.$listeners) 
          // updateInfo: f, delInfo: f, addInfo: f
            this.$emit('updateInfo') 
          // 可以触发 father 组件中的updateInfo函数
        }
    }
</script>

7. Provide、Inject

使用场景:vue中依赖注入,用于父子组件之间 的通信;也可以用于祖孙组件的通信;

使用方法:provide和inject是vue提供的两个钩子,和data、methods是同级的,provide的书写形式和data是一样的。provide 钩子用来发送数据或方法,inject钩子用来接收数据或方法。

// 父组件
provide() { 
    return {     
       name: this.name
    };
}
// 子组件
inject: ['name']

// 这种写法可以访问父组件中的所有属性
provide() {
 return {
    app: this
  };
}
data() {
 return {
    name: '张三'
  };
}

inject: ['app']
console.log(this.app.name)

8. Vuex

适用场景:复杂关系的组件进行数据传递;

Vuex是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

Vuex 解决了多个视图依赖于同一状态和来自不同视图的行为需要变更同一状态的问题,将开发者的精力聚焦于数据的更新而不是数据在组件之间的传递上。

Vuex的各个模块:

  • state:用于数据的存储,是store中的唯一数据源;

  • getters:和vue中的计算属性一样,基于state数据的二次包装,常用于数据的筛选和多个数据的相关性计算;

  • mutations:类似函数,改变state数据的唯一途径,不能用于处理异步事件;

  • actions:类似于mutation,用于提交mutation来改变状态,而不直接变更状态,可以包含任意异步操作;

// vue2
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  //数据,相当于data
  state: {},
  getters: {},
  //里面定义方法,操作state方发
  mutations: {},
  // 操作异步操作mutation
  actions: {},
  modules: {},
})

// main.js
import Vue from 'vue';
import App from './App.vue';
import store from '@/vuex/store';

new Vue({
    store,
    render: h => h(App)
}).$mount('#app');
// vue3
import { createStore } from "vuex";

export default createStore({
  state: {},
  getters: {},
  mutations: {},
  actions: {},
  modules: {},
});

// main.ts
import { createApp } from "vue";
import App from "./App.vue";
import store from "./store";

const app = createApp(App);

app.use(store);
app.mount("#app");

总结

  1. 父子之间的通信

    1)父子关系的组件数据传递选择props和$emit进行传递,子组件通过props属性来接受父组件的数据,父组件在子组件上注册监听事件,子组件通过emit触发事件向父组件发送数据。

    2)通过ref属性给子组件设置一个名称,父组件通过$refs组件名称来获取子组件,子组件通过$parent获取父组件。

  2. 跨代组件之间的通信

    1)provide/inject,在父组件中通过provide提供变量,在子组件中通过inject将变量注入到组件中。

  3. 兄弟组件之前的通信

    1)eventBus

    2)$parent+$refs

  4. 任意组件之间的通信

    1)eventBus

常见编程题

获取当天日期

var d = new Date();
// 获取年, getFullYear()返回4位的数字
var year = d.getFullYear();
// 获取月, 月份比较特殊, 0是1月, 11是12月
var month = d.getMonth() + 1;
// 变成两位
month = month < 10 ? '0' + month : month;
// 获取日
var day = d.getDate();
day = day < 10 ? '0' + day : day;
console.log(year + '- ' + month + '- ' + day);

未完待续

可以关注一下公众号,谢谢!

qrcode_for_gh_1bc71e84dc15_258.jpg