2021-05-10 前端面试集

178 阅读1小时+

前端基础

来源:极客大学 2021-05-10

| HTTP/HTML/浏览器

(1)http 和 https 的基本概念

http: 超文本传输协议,是互联网上应用最为广泛的一种网络协议,是一个客户端和服 务器端请求和应答的标准(TCP),用于从 WWW 服务器传输超文本到本地浏览器的传 输协议,它可以使浏览器更加高效,使网络传输减少。

https: 是以安全为目标的 HTTP 通道,简单讲是 HTTP 的安全版,即 HTTP 下加入 SSL 层,HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL。 https 协议的主要作用是:建立一个信息安全通道,来确保数组的传输,确保网站的真实 性。

(2)http 和 https 的区别?

http 传输的数据都是未加密的,也就是明文的,网景公司设置了 SSL 协议来对 http 协议 传输的数据进行加密处理,简单来说 https 协议是由 http 和 ssl 协议构建的可进行加密传 输和身份认证的网络协议,比 http 协议的安全性更高。

主要的区别如下:

Https 协议需要 ca 证书,费用较高。

http 是超文本传输协议,信息是明文传输,https 则是具有安全性的 ssl 加密传输协议。

使用不同的链接方式,端口也不同,一般而言,http 协议的端口为 80,https 的端口为 443

http 的连接很简单,是无状态的;

HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传 输、身份认证的网络协议,比 http 协议安全。

(3)https 协议的工作原理

客户端在使用 HTTPS 方式与 Web 服务器通信时有以下几个步骤, 如图所示。

客户使用 https url 访问服务器,则要求 web 服务器建立 ssl 链接。

web 服务器接收到客户端的请求之后,会将网站的证书(证书中包含了公钥),返回或 者说传输给客户端。

客户端和 web 服务器端开始协商 SSL 链接的安全等级,也就是加密等级。

客户端浏览器通过双方协商一致的安全等级,建立会话密钥,然后通过网站的公钥来加 密会话密钥,并传送给网站。

web 服务器通过自己的私钥解密出会话密钥。 web 服务器通过会话密钥加密与客户端之间的通信。

4)https 协议的优点

使用 HTTPS 协议可认证用户和服务器,确保数据发送到正确的客户机和服务器;

HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,要比 http 协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。

HTTPS 是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻 击的成本。 谷歌曾在 2014 年 8 月份调整搜索引擎算法,并称“比起同等 HTTP 网站,采用 HTTPS 加密的网站在搜索结果中的排名将会更高”。

(5)https 协议的缺点

https 握手阶段比较费时,会使页面加载时间延长 50%,增加 10%~20%的耗电。

https 缓存不如 http 高效,会增加数据开销。

SSL 证书也需要钱,功能越强大的证书费用越高。

SSL 证书需要绑定 IP,不能再同一个 ip 上绑定多个域名,ipv4 资源支持不了这种消耗

tcp 三次握手,一句话概括

图片.png

从图片可以得到三次握手可以简化为:C 发起请求连接 S 确认,也发起连接 C 确认我们

再看看每次握手的作用

第一次握手:S 只可以确认 自己可以接受 C 发送的报文段

第二次握手:C 可以确认 S 收到了自己发送的报文段,并且可以确认 自己可以接受 S 发 送的报文段

第三次握手:S 可以确认 C 收到了自己发送的报文段

TCP 和 UDP 的区别

(1)TCP 是面向连接的,udp 是无连接的即发送数据前不需要先建立链接。

(2)TCP 提供可靠的服务。也就是说,通过 TCP 连接传送的数据,无差错,不丢失, 不重复,且按序到达;UDP 尽最大努力交付,即不保证可靠交付。 并且因为 tcp 可靠, 面向连接,不会丢失数据因此适合大数据量的交换。

(3)TCP 是面向字节流,UDP 面向报文,并且网络出现拥塞不会使得发送速率降低(因 此会出现丢包,对实时的应用比如 IP 电话和视频会议等)。

(4)TCP 只能是 1 对 1 的,UDP 支持 1 对 1,1 对多。

(5)TCP 的首部较大为 20 字节,而 UDP 只有 8 字节。

(6)TCP 是面向连接的可靠性传输,而 UDP 是不可靠的。

WebSocket 的实现和应用

(1)什么是 WebSocket?

WebSocket 是 HTML5 中的协议,支持持久连续,http 协议不支持持久性连接。Http1.0 和 HTTP1.1 都不支持持久性的链接,HTTP1.1 中的 keep-alive,将多个 http 请求合并为 1 个

(2)WebSocket 是什么样的协议,具体有什么优点?

HTTP 的生命周期通过 Request 来界定,也就是 Request 一个 Response,那么在 Http1.0 协议中,这次 Http 请求就结束了。在 Http1.1 中进行了改进,是的有一个 connection: Keep-alive,也就是说,在一个 Http 连接中,可以发送多个 Request,接收多个 Response。 但是必须记住,在 Http 中一个 Request 只能对应有一个 Response,而且这个 Response 是被动的,不能主动发起。

WebSocket 是基于 Http 协议的,或者说借用了 Http 协议来完成一部分握手,在握手阶段 与 Http 是相同的。我们来看一个 websocket 握手协议的实现,基本是 2 个属性,upgrade, connection。 基本请求如下: GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 Origin: example.com

多了下面 2 个属性

图片.png

告诉服务器发送的是 websocket

图片.png

一个图片 url 访问后直接下载怎样实现?

请求的返回头里面,用于浏览器解析的重要参数就是 OSS 的 API 文档里面的返回 http 头,决定用户下载行为的参数。 下载的情况下:

  1. x-oss-object-type: Normal
  2. x-oss-request-id: 598D5ED34F29D01FE2925F41
  3. x-oss-storage-class: Standard

说一下 web Quality(无障碍)

能够被残障人士使用的网站才能称得上一个易用的(易访问的)网站。 残障人士指的是那些带有残疾或者身体不健康的用户。 使用 alt 属性: <img src="person.jpg" alt="this is a person"/> 有时候浏览器会无法显示图像。具体的原因有: 用户关闭了图像显示 浏览器是不支持图形显示的迷你浏览器 浏览器是语音浏览器(供盲人和弱视人群使用) 如果您使用了 alt 属性,那么浏览器至少可以显示或读出有关图像的描述。

几个很实用的 BOM 属性对象方法?

什么是 Bom? Bom 是浏览器对象

有哪些常用的 Bom 属性呢?

(1)location 对象 location.href-- 返回或设置当前文档的 URL

location.search -- 返回 URL 中的查询字符串部分。例 如 www.dreamdu.com/dreamdu.php… 返回包括(?)后面的内 容?id=5&name=dreamdu location.hash -- 返回 URL#后面的内容,如果没有#,返回空

location.host -- 返回 URL 中的域名部分,例如 www.dreamdu.com

location.hostname -- 返回 URL 中的主域名部分,例如 dreamdu.com

location.pathname -- 返回 URL 的域名后的部分。例如 www.dreamdu.com/xhtml/ 返 回/xhtml/

location.port -- 返回 URL 中的端口部分。例如 www.dreamdu.com:8080/xhtml/ 返回 8080

location.protocol -- 返回 URL 中的协议部分。例如 www.dreamdu.com:8080/xhtml/ 返 回(//)前面的内容 http:

location.assign -- 设置当前文档的 URL

location.replace() -- 设置当前文档的 URL,并且在 history 对象的地址列表中移除这个 URL

location.replace(url);

location.reload() -- 重载当前页面

(2)history 对象

history.back() -- 后退一页

history.forward() -- 前进一页

(3)Navigator 对象

navigator.userAgent -- 返回用户代理头的字符串表示(就是包括浏览器版本信息等的字 符串)

navigator.cookieEnabled -- 返回浏览器是否支持(启用)cookie

说一下 HTML5 drag api

darg:事件主体是被拖放元素,在正在拖放被拖放元素时触发。

dragenter:事件主体是目标元素,在被拖放元素进入某元素时触发。

dragover:事件主体是目标元素,在被拖放在某元素内移动时触发。

dragleave:事件主体是目标元素,在被拖放元素移出目标元素是触发。

drop:事件主体是目标元素,在目标元素完全接受被拖放元素时触发。

dragend:事件主体是被拖放元素,在整个拖放操作结束时触发

说一下 http2.0

首先补充一下,http 和 https 的区别,相比于 http,https 是基于 ssl 加密的 http 协议 简要概括:

http2.0 是基于 1999 年发布的 http1.0 之后的首次更新。

提升访问速度(可以对于,请求资源所需时间更少,访问速度更快,相比 http1.0)

允许多路复用:多路复用允许同时通过单一的 HTTP/2 连接发送多重请求-响应信息。

改善了:在 http1.1 中,浏览器客户端在同一时间,针对同一域名下的请求有一定数量限 制(连接数量),超过限制会被阻塞。

二进制分帧:HTTP2.0 会将所有的传输信息分割为更小的信息或者帧,并对他们进行二进制编码

首部压缩

服务器端推送

补充 400 和 401、403 状态码

(1)400 状态码:请求无效 产生原因:

前端提交数据的字段名称和字段类型与后台的实体没有保持一致 前端提交到后台的数据应该是 json 字符串类型,但是前端没有将对象 JSON.stringify 转 化成字符串。 解决方法: 对照字段的名称,保持一致性 将 obj 对象通过 JSON.stringify 实现序列化

(2)401 状态码:当前请求需要用户验证

(3)403 状态码:服务器已经得到请求,但是拒绝执行

fetch 发送 2 次请求的原因

fetch 发送 post 请求的时候,总是发送 2 次,第一次状态码是 204,第二次才成功?

原因很简单,因为你用 fetch 的 post 请求的时候,导致 fetch 第一次发送了一个 Options 请求,询问服务器是否支持修改的请求头,如果服务器支持,则在第二次中发送真正的 请求

Cookie、sessionStorage、localStorage 的区别

共同点:都是保存在浏览器端,并且是同源的

Cookie:cookie 数据始终在同源的 http 请求中携带(即使不需要),即 cookie 在浏览器 和服务器间来回传递。而 sessionStorage 和 localStorage 不会自动把数据发给服务器,仅 在本地保存。cookie 数据还有路径(path)的概念,可以限制 cookie 只属于某个路径下, 存储的大小很小只有 4K 左右。 (key:可以在浏览器和服务器端来回传递,存储容量 小,只有大约 4K 左右)

sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持,localStorage: 始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie 只在设置的 cookie 过期时间之前一直有效,即使窗口或浏览器关闭。(key:本身就是一个回话过程,关 闭浏览器后消失,session 为一个回话,当页面不同即使是同一页面打开两次,也被视为 同一次回话)

localStorage:localStorage 在所有同源窗口中都是共享的;cookie 也是在所有同源窗口中 都是共享的。(key:同源窗口都会共享,并且不会失效,不管窗口或者浏览器关闭与 否都会始终生效)

补充说明一下 cookie 的作用:

保存用户登录状态。例如将用户 id 存储于一个 cookie 内,这样当用户下次访问该页面 时就不需要重新登录了,现在很多论坛和社区都提供这样的功能。 cookie 还可以设置 过期时间,当超过时间期限后,cookie 就会自动消失。因此,系统往往可以提示用户保 持登录状态的时间:常见选项有一个月、三个 月、一年等。 跟踪用户行为。例如一个天气预报网站,能够根据用户选择的地区显示当地的天气情况。 如果每次都需要选择所在地是烦琐的,当利用了 cookie 后就会显得很人性化了,系统能 够记住上一次访问的地区,当下次再打开该页面时,它就会自动显示上次用户所在地区 的天气情况。因为一切都是在后 台完成,所以这样的页面就像为某个用户所定制的一样,使用起来非常方便定制页面。如果网站提供了换肤或更换布局的功能,那么可以使 用 cookie 来记录用户的选项,例如:背景色、分辨率等。当用户下次访问时,仍然可以 保存上一次访问的界面风格。

对 HTML 语义化标签的理解

HTML5 语义化标签是指正确的标签包含了正确的内容,结构良好,便于阅读,比如 nav 表示导航条,类似的还有 article、header、footer 等等标签。

iframe 是什么?有什么缺点?

定义:iframe 元素会创建包含另一个文档的内联框架

提示:可以将提示文字放在<iframe></iframe>之间,来提示某些不支持 iframe 的浏览器

缺点:

会阻塞主页面的 onload 事件

搜索引擎无法解读这种页面,不利于 SEO iframe 和主页面共享连接池,而浏览器对相同区域有限制所以会影响性能。

Cookie 如何防范 XSS 攻击

XSS(跨站脚本攻击)是指攻击者在返回的 HTML 中嵌入 javascript 脚本,为了减轻这些 攻击,需要在 HTTP 头部配上, set-cookie: httponly-

这个属性可以防止 XSS,它会禁止 javascript 脚本来访问 cookie。

secure - 这个属性告诉浏览器仅在请求为 https 的时候发送 cookie。 结果应该是这样的:Set-Cookie=.....

click 在 ios 上有 300ms 延迟,原因及如何解决?

(1)粗暴型,禁用缩放 <meta name="viewport" content="width=device-width, user-scalable=no">

(2)利用 FastClick,其原理是: 检测到 touchend 事件后,立刻出发模拟 click 事件,并且把浏览器 300 毫秒之后真正出 发的事件给阻断掉

介绍知道的 http 返回的状态码

100 Continue 继续。客户端应继续其请求

101 Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更 高级的协议,例如,切换到 HTTP 的新版本协议

200 OK 请求成功。一般用于 GET 与 POST 请求

201 Created 已创建。成功请求并创建了新的资源

202 Accepted 已接受。已经接受请求,但未处理完成

203 Non-Authoritative Information 非授权信息。请求成功。但返回的 meta 信息不在原 始的服务器,而是一个副本

204 No Content 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下, 可确保浏览器继续显示当前文档

304 Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回 任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返 回在指定日期之后修改的资源

400 Bad Request 客户端请求的语法错误,服务器无法理解

401 Unauthorized 请求要求用户的身份认证

402 Payment Required 保留,将来使用

403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求

404 Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站 设计人员可设置"您所请求的资源无法找到"的个性页面

405 Method Not Allowed 客户端请求中的方法被禁止

500 Internal Server Error 服务器内部错误,无法完成请求

501 Not Implemented 服务器不支持请求的功能,无法完成请求

502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接 收到了一个无效的响应

http 常用请求头

Accept 可接受的响应内容类型(Content-Types)。

Accept-Encoding 可接受的响应内容的编码方式。

Cache-Control 用来指定当前的请求/回复中的,是否使用缓存机制。

Cookie 由之前服务器通过Set-Cookie(见下文)设置的一个HTTP协议Cookie

Content-MD5 请求体的内容的二进制 MD5 散列值(数字签名),以 Base64 编 码的结果

Content-Type 请求体的 MIME 类型 (用于 POST 和 PUT 请求中)

强,协商缓存

缓存分为两种:强缓存和协商缓存,根据响应的 header 内容来决定

强缓存相关字段有 expires,cache-control。如果 cache-control 与 expires 同时存在的话, cache-control 的优先级高于 expires。 协商缓存相关字段有 Last-Modified/If-Modified-Since,Etag/If-None-Match

因为服务器上的资源不是一直固定不变的,大多数情况下它会更新,这个时候如果我们 还访问本地缓存,那么对用户来说,那就相当于资源没有更新,用户看到的还是旧的资 源;所以我们希望服务器上的资源更新了浏览器就请求新的资源,没有更新就使用本地 的缓存,以最大程度的减少因网络请求而产生的资源浪费。

前端优化

降低请求量:合并资源,减少 HTTP 请求数,minify / gzip 压缩,webP,lazyLoad。 加快请求速度:预解析 DNS,减少域名数,并行加载,CDN 分发。 缓存:HTTP 协议缓存请求,离线缓存 manifest,离线数据缓存 localStorage。 渲染:JS/CSS 优化,加载顺序,服务端渲染,pipeline。

GET 和 POST 的区别

get 参数通过 url 传递,post 放在 request body 中。

get 请求在 url 中传递的参数是有长度限制的,而 post 没有。

get 比 post 更不安全,因为参数直接暴露在 url 中,所以不能用来传递敏感信息。

get 请求只能进行 url 编码,而 post 支持多种编码方式

get 请求会浏览器主动 cache,而 post 支持多种编码方式。

get 请求参数会被完整保留在浏览历史记录里,而 post 中的参数不会被保留。

GET 和 POST 本质上就是 TCP 链接,并无差别。但是由于 HTTP 的规定和浏览器/服务器 的限制,导致他们在应用过程中体现出一些不同。

GET 产生一个 TCP 数据包;

POST 产生两个 TCP 数据包。

HTTP 支持的方法

GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE, CONNECT

如何画一个三角形

三角形原理:边框的均分原理

div { 
width:0px; 
height:0px; 
border-top:10px solid red; 
border-right:10px solid transparent; 
border-bottom:10px solid transparent; 
border-left:10px solid transparent; 
}

HTML5 新增的元素

首先 html5 为了更好的实践 web 语义化,增加了 header,footer,nav,aside,section 等语义 化标签,在表单方面,为了增强表单,为 input 增加了 color,emial,data ,range 等类型, 在存储方面,提供了 sessionStorage,localStorage,和离线存储,通过这些存储方式方便数 据在客户端的存储和获取,在多媒体方面规定了音频和视频元素 audio 和 vedio,另外还 有地理定位,canvas 画布,拖放,多线程编程的 web worker 和 websocket 协议。

在地址栏里输入一个 URL,到这个页面呈现出来,中间会发生什么?

这是一个必考的面试问题

输入 url 后,首先需要找到这个 url 域名的服务器 ip,为了寻找这个 ip,浏览器首先会寻 找缓存,查看缓存中是否有记录,缓存的查找记录为:浏览器缓存-》系统缓存-》路由器缓存,缓存中没有则查找系统的 hosts 文件中是否有记录,如果没有则查询 DNS 服务器,得到服务器的 ip 地址后,浏览器根据这个 ip 以及相应的端口号,构造一个 http 请求,这个请求报文会包括这次请求的信息,主要是请求方法,请求说明和请求附带的数据,并将这个 http 请求封装在一个 tcp 包中,这个 tcp 包会依次经过传输层,网络层, 数据链路层,物理层到达服务器,服务器解析这个请求来作出响应,返回相应的 html 给浏览器,因为** html 是一个树形结构**,浏览器根据这个 html 来构建 DOM 树,在 dom 树的构建过程中如果遇到 JS 脚本和外部 JS 连接,则会停止构建 DOM 树来执行和下载相应的代码,这会造成阻塞,这就是为什么推荐 JS 代码应该放在 html 代码的后面,之后根据外部央视,内部央视,内联样式构建一个 CSS 对象模型树 CSSOM 树,构建完成后和 DOM 树合并为渲染树,这里主要做的是排除非视觉节点,比如 script,meta 标签和 排除 display 为 none 的节点,之后进行布局,布局主要是确定各个元素的位置和尺寸,之后是渲染页面,因为 html 文件中会含有图片,视频,音频等资源,在解析 DOM 的过程中,遇到这些都会进行并行下载,浏览器对每个域的并行下载数量有一定的限制,一般是 4-6 个,当然在这些所有的请求中我们还需要关注的就是缓存,缓存一般通过 Cache-Control、Last-Modify、Expires 等首部字段控制。 Cache-Control 和 Expires 的区别 在于 Cache-Control 使用相对时间,Expires 使用的是基于服务器 端的绝对时间,因为存在时差问题,一般采用 Cache-Control,在请求这些有设置了缓存的数据时,会先查看是否过期,如果没有过期则直接使用本地缓存,过期则请求并在服务器校验文件是否修 改,如果上一次 响应设置了 ETag 值会在这次请求的时候作为 If-None-Match 的值交给 服务器校验,如果一致,继续校验 Last-Modified,没有设置 ETag 则直接验证 Last-Modified,再决定是否返回 304。

cache-control 的值有哪些

cache-control 是一个通用消息头字段被用于 HTTP 请求和响应中,通过指定指令来实现 缓存机制,这个缓存指令是单向的,常见的取值有 private、no-cache、max-age、 must-revalidate 等,默认为 private。

csrf 和 xss 的网络攻击及防范

CSRF:跨站请求伪造,可以理解为攻击者盗用了用户的身份,以用户的名义发送了恶 意请求,比如用户登录了一个网站后,立刻在另一个tab页面访问量攻击者用来制造攻击的网站,这个网站要求访问刚刚登陆的网站,并发送了一个恶意请求,这时候 CSRF 就产生了,比如这个制造攻击的网站使用一张图片,但是这种图片的链接却是可以修改 数据库的,这时候攻击者就可以以用户的名义操作这个数据库,防御方式的话:使用验 证码,检查 https 头部的 refer,使用 token XSS:跨站脚本攻击,是说攻击者通过注入恶意的脚本,在用户浏览网页的时候进行攻 击,比如获取 cookie,或者其他用户身份信息,可以分为存储型和反射型,存储型是攻 击者输入一些数据并且存储到了数据库中,其他浏览者看到的时候进行攻击,反射型的 话不存储在数据库中,往往表现为将攻击代码放在 url 地址的请求参数中,防御的话为 cookie 设置 httpOnly 属性,对用户的输入进行检查,进行特殊字符过滤。

怎么看网站的性能如何

检测页面加载时间一般有两种方式,

一种是被动去测:就是在被检测的页面置入脚本或 探针,当用户访问网页时,探针自动采集数据并传回数据库进行分析,

另一种主动监测的方式,即主动的搭建分布式受控环境,模拟用户发起页面访问请求,主动采集性能数 据并分析,在检测的精准度上,专业的第三方工具效果更佳,比如说性能极客

输入 URL 到页面加载显示完成发生了什么?

DNS 解析

TCP 连接

发送 HTTP 请求

服务器处理请求并返回 HTTP 报文

浏览器解析渲染页面

连接结束

描述一下 XSS 和 CRSF 攻击?防御方法?

XSS, 即为(Cross Site Scripting), 中文名为跨站脚本, 是发生在目标用户的浏览器层面 上的,当渲染 DOM 树的过程成发生了不在预期内执行的 JS 代码时,就发生了 XSS 攻击。 大多数 XSS 攻击的主要方式是嵌入一段远程或者第三方域上的 JS 代码。实际上是在目 标网站的作用域下执行了这段 JS 代码。 CSRF(Cross Site Request Forgery,跨站请求伪造),字面理解意思就是在别的站点伪造 了一个请求。专业术语来说就是在受害者访问一个网站时,其 Cookie 还没有过期的情 况下,攻击者伪造一个链接地址发送受害者并欺骗让其点击,从而形成 CSRF 攻击。 XSS 防御的总体思路是:对输入(和 URL 参数)进行过滤,对输出进行编码。也就是对提 交的所有内容进行过滤,对 url 中的参数进行过滤,过滤掉会导致脚本执行的相关内容; 然后对动态输出到页面的内容进行 html 编码,使脚本无法在浏览器中执行。虽然对输 入过滤可以被绕过,但是也还是会拦截很大一部分的 XSS 攻击。 防御 CSRF 攻击主要有三种策略:验证 HTTP Referer 字段;在请求地址中添加 token 并 验证;在 HTTP 头中自定义属性并验证。

知道 304 吗,什么时候用 304?

304:如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自 上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个 304 状态码。

cookie 有哪些字段可以设置

name 字段为一个 cookie 的名称。 value 字段为一个 cookie 的值。 domain 字段为可以访问此 cookie 的域名。 非顶级域名,如二级域名或者三级域名,设置的 cookie 的 domain 只能为顶级域名或者 二级域名或者三级域名本身,不能设置其他二级域名的 cookie,否则 cookie 无法生成。 顶级域名只能设置 domain 为顶级域名,不能设置为二级域名或者三级域名,否则 cookie 无法生成。 二级域名能读取设置了 domain 为顶级域名或者自身的 cookie,不能读取其他二级域名 domain 的 cookie。所以要想 cookie 在多个二级域名中共享,需要设置 domain 为顶级域 名,这样就可以在所有二级域名里面或者到这个 cookie 的值了。 顶级域名只能获取到 domain 设置为顶级域名的 cookie,其他 domain 设置为二级域名的 无法获取。 path 字段为可以访问此 cookie 的页面路径。 比如 domain 是 abc.com,path 是/test,那么只 有/test 路径下的页面可以读取此 cookie。 expires/Max-Age 字段为此 cookie 超时时间。若设置其值为一个时间,那么当到达此时间 后,此 cookie 失效。不设置的话默认值是 Session,意思是 cookie 会和 session 一起失效。 当浏览器关闭(不是浏览器标签页,而是整个浏览器) 后,此 cookie 失效。 Size 字段 此 cookie 大小。 http字段 cookie的httponly属性。若此属性为true,则只有在http请求头中会带有此cookie 的信息,而不能通过 document.cookie 来访问此 cookie。 secure 字段 设置是否只能通过 https 来传递此条 cookie

HTML5 和 CSS3 用的多吗?你了解它们的新属性吗?有在项目中用过 吗?

html5:

1)标签增删 8 个语义元素 header section footer aside nav main article figure 内容元素 mark 高亮 progress 进度 新的表单控件 calander date time email url search 新的 input 类型 color date datetime datetime-local email 移除过时标签 big font frame frameset

2)canvas 绘图,支持内联 SVG。支持 MathML

3)多媒体 audio video source embed track

4)本地离线存储,把需要离线存储在本地的文件列在一个 manifest 配置文件

5)web 存储。localStorage、SessionStorage

css3:

CSS3边框如border-radius,box-shadow等;

CSS3背景如background-size,background-origin 等;

CSS3 2D,3D 转换如 transform 等;CSS3 动画如 animation 等

| CSS

说一下 css 盒模型

CSS 中的盒子模型包括IE盒子模型标准的 W3C 盒子模型

图片.png

图片.png

区别:从图中我们可以看出,这两种盒子模型最主要的区别就是 width 的包含范围,在 标准的盒子模型中,width 指 content 部分的宽度,在 IE 盒子模型中,width 表示 content+padding+border 这三个部分的宽度,故这使得在计算整个盒子的宽度时存在着差 异:

标准盒子模型的盒子宽度:左右 border+左右 padding+width

IE 盒子模型的盒子宽度:width

在 CSS3 中引入了 box-sizing 属性,box-sizing:content-box;表示标准的盒子模型, box-sizing:border-box 表示的是 IE 盒子模型 最后,前面我们还提到了,box-sizing:padding-box,这个属性值的宽度包含了左右 padding+width 也很好理解性记忆,包含什么,width 就从什么开始算起。

画一条 0.5px 的线

采用 meta viewport 的方式 <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />

采用 border-image 的方式

采用 transform: scale()的方式

link 标签和 import 标签的区别

link 属于 html 标签,而@import 是 css 提供的 页面被加载时,link 会同时被加载,而@import 引用的 css 会等到页面加载结束后加载。

link 是 html 标签,因此没有兼容性,而@import 只有 IE5 以上才能识别。 link 方式样式的权重高于@import 的。

transition 和 animation 的区别

Animation 和 transition 大部分属性是相同的,他们都是随时间改变元素的属性值,他们 的主要区别是 transition 需要触发一个事件才能改变属性,而 animation 不需要触发任何 事件的情况下才会随时间改变属性值,并且 transition 为 2 帧,从 from .... to,而 animation 可以一帧一帧的。

来源:极客大学 2021-05-10

Flex 布局

Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性

布局的传统解决方案,基于盒状模型,依赖 display 属性 + position 属性 + float 属性。它 对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。

Flex 简单的分为容器属性元素属性

容器的属性:

flex-direction:决定主轴的方向(即子 item 的排列方法)

flex-direction: row | row-reverse | column | column-reverse;

flex-wrap:决定换行规则

flex-wrap: nowrap | wrap | wrap-reverse;

flex-flow:属性是 flex-direction 和 flex-wrap 属性的复合属性

flex-flow: || ;

比如:让弹性盒的元素以相反的顺序显示,且在必要的时候进行拆行:

display:flex;

flex-flow:row-reverse wrap;

justify-content:对其方式,水平主轴对齐方式

align-items:对齐方式,竖直轴线方向

项目的属性(元素的属性):

order 属性:定义项目的排列顺序,顺序越小,排列越靠前,默认为 0

flex-grow 属性:定义项目的放大比例,即使存在空间,也不会放大

flex-shrink 属性:定义了项目的缩小比例,当空间不足的情况下会等比例的缩小,如果 定义个 item 的 flow-shrink 为 0,则为不缩小

flex-basis 属性:定义了在分配多余的空间,项目占据的空间。

flex:是 flex-growflex-shrink、flex-basis 的简写,默认值为 0 1 auto。

align-self:允许单个项目与其他项目不一样的对齐方式,可以覆盖

align-items,默认属 性为 auto,表示继承父元素的

align-items 比如说,用 flex 实现圣杯布局

BFC(块级格式化上下文,用于清楚浮动,防止 margin 重叠等)

直译成:块级格式化上下文,是一个独立的渲染区域,并且有一定的布局规则。 BFC 区域不会与 float box 重叠 BFC 是页面上的一个独立容器,子元素不会影响到外面 计算 BFC 的高度时,浮动元素也会参与计算

那些元素会生成 BFC:

根元素

float 不为 none 的元素

position 为 fixed 和 absolute 的元素

display 为 inline-block、table-cell、table-caption,flex,inline-flex 的元素

overflow 不为 visible 的元素

垂直居中的方法

.container{ width: 500px; height: 400px; border: 2px solid #379; position: relative; }

.inner{ width: 480px; height: 380px; background-color: #746; position: absolute; top: 50%; left: 50%; margin-top: -190px; /height 的一半/ margin-left: -240px; /width 的一半/ }

补充:其实这里也可以将 marin-top 和 margin-left 负值替换成,

transform:translateX(-50%)和 transform:translateY(-50%)

table-cell(未脱离文档流的)

设置父元素的 display:table-cell,并且 vertical-align:middle,这样子元素可以实现垂直居中

div{ width: 300px; height: 300px; border: 3px solid #555; display: table-cell; vertical-align: middle; text-align: center; }

img{ vertical-align: middle; }

**(4)利用 flex **

将父元素设置为 display:flex,并且设置

align-items:center;justify-content:center;

display: -webkit-flex; display: flex; -webkit-align-items: center; align-items: center; -webkit-justify-content: center; justify-content:

关于 JS 动画和 css3 动画的差异性

渲染线程分为 main thread 和 compositor thread,如果 css 动画只改变 transform 和 opacity, 这时整个 CSS 动画得以在 compositor trhead 完成(而 JS 动画则会在 main thread 执行,然 后出发 compositor thread 进行下一步操作),特别注意的是如果改变 transform 和 opacity 是不会 layout 或者 paint 的。

区别

功能涵盖面,JS 比 CSS 大

实现/重构难度不一,CSS3 比 JS 更加简单,性能跳优方向固定

对帧速表现不好的低版本浏览器,

css3 可以做到自然降级

css 动画有天然事件支持

css3 有兼容性问题

说一下块元素和行元素

块元素:独占一行,并且有自动填满父元素,可以设置 margin 和 pading 以及高度和宽 度

行元素:不会独占一行,width 和 height 会失效,并且在垂直方向的 padding 和 margin 会失效。

多行元素的文本省略号

display: -webkit-box 

-webkit-box-orient:vertical 

-webkit-line-clamp:3 

overflow:hidden

双边距重叠问题(外边距折叠)

多个相邻(兄弟或者父子关系)普通流的块元素垂直方向 marigin 会重叠 折叠的结果为:

两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。

两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。

两个外边距一正一负时,折叠结果是两者的相加的和。

position 属性 比较

Position 属性把元素放置在一个静态的,相对的,绝对的,固定的位置中,

Static:位置设置为 static 的元素,他始终处于页面流给予的位置,static 元素会忽略任何 top,buttom,left,right 声明

Relative:位置设置为 relative 的元素,可将其移至相对于其正常位置的地方,因此 left: 20 会将元素移至元素正常位置左边 20 个像素的位置

Absolute:此元素可定位于相对包含他的元素的指定坐标,此元素可通过 left,top 等属 性规定

Fixed:位置被设为 fiexd 的元素,可定为与相对浏览器窗口的指定坐标,可以通过 left, top,right 属性来定位

浮动清除

方法一:使用带 clear 属性的空元素

方法二:使用 CSS 的 overflow 属性

方法三:给浮动的元素的容器添加浮动

方法四:使用邻接元素处理:给浮动元素后面的元素添加 clear 属性。

方法五:使用 CSS 的:after 伪元素

结合:after 伪元素(注意这不是伪类,而是伪元素,代表一个元素之后最近的元素)和 IEhack ,可以完美兼容当前主流的各大浏览器,这里的 IEhack 指的是触发 hasLayout。 给浮动元素的容器添加一个 clearfix 的 class,然后给这个 class 添加一个:after 伪元素实 现元素末尾添加一个看不见的块元素(Block element)清理浮动。

CSS 选择器有哪些,优先级呢

id 选择器,class 选择器,标签选择器,伪元素选择器,伪类选择器等

带有!important 标记的样式属性的优先级最高; 样式表的来源不同时,优先级顺序为:内联样式> 内部样式 > 外部样式 > 浏览器用户 自定义样式 > 浏览器默认样式

怎么样让一个元素消失

display:none; visibility:hidden; opacity: 0; 等等

css 动画如何实现 创建动画序列,需要使用 animation 属性或其子属性,该属性允许配置动画时间、时长 以及其他动画细节,但该属性不能配置动画的实际表现,动画的实际表现是 由 @keyframes 规则实现,具体情况参见使用 keyframes 定义动画序列小节部分。 transition 也可实现动画。transition 强调过渡,是元素的一个或多个属性发生变化时产生 的过渡效果,同一个元素通过两个不同的途径获取样式,而第二个途径当某种改变发生 (例如 hover)时才能获取样式,这样就会产生过渡动画

如何实现图片在某个容器中居中的?

父元素固定宽高,利用定位及设置子元素 margin 值为自身的一半。

父元素固定宽高,子元素设置 position: absolute,margin:auto 平均分配 margin

css3 属性 transform。子元素设置 position: absolute; left: 50%; top: 50%;transform: translate(-50%,-50%);即可。

将父元素设置成 display: table, 子元素设置为单元格 display: table-cell。

弹性布局 display: flex。设置 align-items: center; justify-content: center

法一:父元素 display:flex,align-items:center;

法二:元素绝对定位,top:50%,margin-top:-(高度/2)

法三:高度不确定用 transform:translateY(-50%)

法四:父元素 table 布局,子元素设置 vertical-align:center;

calc 属性

Calc 用户动态计算长度值,任何长度值都可以使用 calc()函数计算,需要注意的是,运 算符前后都需要保留一个空格,例如:width: calc(100% - 10px);

设置一个元素的背景颜色,背景颜色会填充哪些区域?

background-color 设置的背景颜色会填充元素的 content、padding、border 区域。

知道属性选择器和伪类选择器的优先级吗

属性选择器和伪类选择器优先级相同

inline-block、inline 和 block 的区别;

Block 是块级元素,其前后都会有换行符,能设置宽度,高度,margin/padding 水平垂直 方向都有效。

Inline:设置 width 和 height 无效,margin 在竖直方向上无效,padding 在水平方向垂直 方向都有效,前后无换行符

Inline-block:能设置宽度高度,margin/padding 水平垂直方向 都有效,前后无换行符

了解重绘和重排吗,知道怎么去减少重绘和重排吗,让文档脱离文档流有 哪些方法

DOM 的变化影响到了预算内宿的几何属性比如宽高,浏览器重新计算元素的几何属性, 其他元素的几何属性也会受到影响,浏览器需要重新构造渲染书,这个过程称之为重排, 浏览器将受到影响的部分重新绘制在屏幕上 的过程称为重绘,引起重排重绘的原因有: 添加或者删除可见的 DOM 元素, 元素尺寸位置的改变 浏览器页面初始化, 浏览器窗口大小发生改变,重排一定导致重绘,重绘不一定导致重排, 减少重绘重排的方法有: 不在布局信息改变时做 DOM 查询, 使用 csstext,className 一次性改变属性 使用 fragment 对于多次重排的元素,比如说动画。使用绝对定位脱离文档流,使其不影响其他元素

display:none 和 visibilty:hidden 的区别

  1. visibility:hidden,该元素隐藏起来了,但不会改变页面布局,但是不会触发该元素已 经绑定的事件

  2. display:none,把元素隐藏起来,并且会改变页面布局,可以理解成在页面中把该元 素删除掉。

css 布局

六种布局方式总结:圣杯布局双飞翼布局Flex 布局绝对定位布局表格布局网格布局

圣杯布局是指布局从上到下分为 header、container、footer,然后 container 部分定为三栏 布局。这种布局方式同样分为 header、container、footer。

圣杯布局的缺陷在于 center 是 在 container 的 padding 中的,因此宽度小的时候会出现混乱。

双飞翼布局给 center 部分包裹了一个 main 通过设置 margin 主动地把页面撑开。

Flex 布局是由 CSS3 提供的一种方便的布局方式。

绝对定位布局是给 container 设置 position: relative 和 overflow: hidden,因为绝对定位的元 素的参照物为第一个 postion 不为 static 的祖先元素。 left 向左浮动,right 向右浮动。 center 使用绝对定位,通过设置 left 和 right 并把两边撑开。 center 设置 top: 0 和 bottom: 0 使其高度撑开。

表格布局的好处是能使三栏的高度统一。

网格布局可能是最强大的布局方式了,使用起来极其方便,但目前而言,兼容性并不好。 网格布局,可以将页面分割成多个区域,或者用来定义内部元素的大小,位置,图层关 系

css 预处理器有什么

less,sass 等

| JavaScript

get 请求传参长度的误区

误区:

我们经常说 get 请求参数的大小存在限制,而 post 请求的参数大小是无限制的。 实际上 HTTP 协议从未规定 GET/POST 的请求长度限制是多少。

对 get 请求参数的限制 是来源与浏览器或 web 服务器,浏览器或 web 服务器限制了 url 的长度。

为了明确这个概念,我们必须再次强调下面几点:

HTTP 协议 未规定 GET 和 POST 的长度限制 GET 的最大长度显示是因为 浏览器和 web 服务器限制了 URI 的长度不同的浏览器和 WEB 服务器,限制的最大长度不一样

要支持 IE,则最大长度为 2083byte,若只支持 Chrome,则最大长度 8182byte

补充 get 和 post 请求在缓存方面的区别

post/get 的请求区别,具体不再赘述。

补充补充一个 get 和 post 在缓存方面的区别:

get 请求类似于查找的过程,用户获取数据,可以不用每次都与数据库连接,所以可以 使用缓存。 post 不同,post 做的一般是修改和删除的工作,所以必须与数据库交互,所以不能使用 缓存。因此 get 请求适合于请求缓存。

说一下闭包

一句话可以概括:闭包就是能够读取其他函数内部变量的函数,或者子函数在外调用, 子函数所在的父函数的作用域不会被释放

如何解决异步回调地狱

promise、generator、async/await

说说前端中的事件流

HTML 中与 javascript 交互是通过事件驱动来实现的,例如鼠标点击事件 onclick、页面 的滚动事件 onscroll 等等,可以向文档或者文档中的元素添加事件侦听器来预订事件。 想要知道这些事件是在什么时候进行调用的,就需要了解一下“事件流”的概念。

什么是事件流:事件流描述的是从页面中接收事件的顺序,DOM2 级事件流包括下面几个阶段。

事件捕获阶段

处于目标阶段

事件冒泡阶段

addEventListener:addEventListener 是 DOM2 级事件新增的指定事件处理程序的操作, 这个方法接收 3 个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最 后这个布尔值参数如果是 true,表示在捕获阶段调用事件处理程序;如果是 false,表示 在冒泡阶段调用事件处理程序。 IE 只支持事件冒泡。

如何让事件先冒泡后捕获

在 DOM 标准事件模型中,是先捕获后冒泡。但是如果要实现先冒泡后捕获的效果,对 于同一个事件,监听捕获和冒泡,分别对应相应的处理函数,监听到捕获事件,先暂缓 执行,直到冒泡事件被捕获后再执行捕获之间。

说一下事件委托

简介:事件委托指的是,不在事件的发生地(直接 dom)上设置监听函数,而是在其父 元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判 断事件发生元素 DOM 的类型,来做出不同的响应。 举例:最经典的就是 ul 和 li 标签的事件监听,比如我们在添加事件时候,采用事件委 托机制,不会在 li 标签上直接添加,而是在 ul 父元素上添加。 好处:比较合适动态元素的绑定,新添加的子元素也会有监听函数,也可以有事件触发 机制

说一下图片的懒加载和预加载

预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染。 懒加载:懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数。 两种技术的本质:两者的行为是相反的,一个是提前加载,一个是迟缓甚至不加载。 懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力。

JS 的 new 操作符做了哪些事情

new 操作符新建了一个空对象,这个对象原型指向构造函数的 prototype,执行构造函数 后返回这个对象。

改变函数内部 this 指针的指向函数(bind,apply,call 的区别)

通过 apply 和 call 改变函数的 this 指向,他们两个函数的第一个参数都是一样的表示要 改变指向的那个对象,第二个参数,apply 是数组,而 call 则是 arg1,arg2...这种形式。通 过 bind 改变 this 作用域会返回一个新的函数,这个函数不会马上执行

JS 的各种位置,比如 clientHeight,scrollHeight,offsetHeight ,以及 scrollTop, offsetTop,clientTop 的区别?

clientHeight:表示的是可视区域的高度,不包含 border 和滚动条

offsetHeight:表示可视区域的高度,包含了 border 和滚动条

scrollHeight:表示了所有区域的高度,包含了因为滚动被隐藏的部分。

clientTop:表示边框 border 的厚度,在未指定的情况下一般为 0

scrollTop:滚动后被隐藏的高度,获取对象相对于由

offsetParent 属性指定的父坐标(css 定位的元素或 body 元素)距离顶端的高度。

JS 拖拽功能的实现

首先是三个事件,分别是 mousedown,mousemove,mouseup 当鼠标点击按下的时候,需要一个 tag 标识此时已经按下,可以执行 mousemove 里面的具体方法。

clientX,clientY 标识的是鼠标的坐标,分别标识横坐标和纵坐标,并且我们用 offsetX 和 offsetY 来表示元素的元素的初始坐标,移动的举例应该是:

鼠标移动时候的坐标-鼠标按下去时候的坐标。

也就是说定位信息为:

鼠标移动时候的坐标-鼠标按下去时候的坐标+元素初始情况下的 offetLeft. 还有一点也是原理性的东西,也就是拖拽的同时是绝对定位,我们改变的是绝对定位条 件下的 left 以及 top 等等值。

补充:也可以通过 html5 的拖放(Drag 和 drop)来实现

异步加载 JS 的方法

defer:只支持 IE 如果您的脚本不会改变文档的内容,可将 defer 属性加入到<script>标 签中,以便加快处理文档的速度。因为浏览器知道它将能够安全地读取文档的剩余部分 而不用执行脚本,它将推迟对脚本的解释,直到文档已经显示给用户为止。

async,HTML5 属性仅适用于外部脚本,并且如果在 IE 中,同时存在 defer 和 async,那 么 defer 的优先级比较高,脚本将在页面完成时执行。 创建 script 标签,插入到 DOM 中

Ajax 解决浏览器缓存问题

在 ajax 发送请求前加上 anyAjaxObj.setRequestHeader("If-Modified-Since","0")。

在 ajax 发送请求前加上 anyAjaxObj.setRequestHeader("Cache-Control","no-cache")。

在 URL 后面加上一个随机数: "fresh=" + Math.random()。

在 URL 后面加上时间搓:"nowtime=" + new Date().getTime()。

如果是使用 jQuery,直接这样就可以了 $.ajaxSetup({cache:false})。这样页面的所有 ajax 都会执行这条语句就是不需要保存缓存记录。

JS 的节流和防抖

JS 中的垃圾回收机制

必要性:由于字符串、对象和数组没有固定大小,所有当他们的大小已知时,才能对他 们进行动态的存储分配。JavaScript 程序每次创建字符串、数组或对象时,解释器都必 须分配内存来存储那个实体。只要像这样动态地分配了内存,最终都要释放这些内存以 便他们能够被再用,否则,JavaScript 的解释器将会消耗完系统中所有可用的内存,造 成系统崩溃。

这段话解释了为什么需要系统需要垃圾回收,JS 不像 C/C++,他有自己的一套垃圾回收 机制(Garbage Collection)。JavaScript 的解释器可以检测到何时程序不再使用一个对象 了,当他确定了一个对象是无用的时候,他就知道不再需要这个对象,可以把它所占用 的内存释放掉了。例如:

var a="hello world";

var b="world";

var a=b;

//这时,会释放掉"hello world",释放内存以便再引用

垃圾回收的方法:标记清除计数引用

标记清除

这是最常见的垃圾回收方式,当变量进入环境时,就标记这个变量为”进入环境“,从逻 辑上讲,永远不能释放进入环境的变量所占的内存,永远不能释放进入环境变量所占用 的内存,只要执行流程进入相应的环境,就可能用到他们。当离开环境时,就标记为离 开环境。

垃圾回收器在运行的时候会给存储在内存中的变量都加上标记(所有都加),然后去掉 环境变量中的变量,以及被环境变量中的变量所引用的变量(条件性去除标记),删除 所有被标记的变量,删除的变量无法在环境变量中被访问所以会被删除,最后垃圾回收 器,完成了内存的清除工作,并回收他们所占用的内存。

引用计数法

另一种不太常见的方法就是引用计数法,引用计数法的意思就是每个值没引用的次数, 当声明了一个变量,并用一个引用类型的值赋值给改变量,则这个值的引用次数为 1,; 相反的,如果包含了对这个值引用的变量又取得了另外一个值,则原先的引用值引用次 数就减 1,当这个值的引用次数为 0 的时候,说明没有办法再访问这个值了,因此就把 所占的内存给回收进来,这样垃圾收集器再次运行的时候,就会释放引用次数为 0 的这 些值。 用引用计数法会存在内存泄露,下面来看原因:

function problem() { var objA = new Object(); var objB = new Object(); objA.someOtherObject = objB; objB.anotherObject = objA; }

在这个例子里面,objA 和 objB 通过各自的属性相互引用,这样的话,两个对象的引用 次数都为 2,在采用引用计数的策略中,由于函数执行之后,这两个对象都离开了作用 域,函数执行完成之后,因为计数不为 0,这样的相互引用如果大量存在就会导致内存 泄露。

特别是在 DOM 对象中,也容易存在这种问题:

var element=document.getElementById(’‘); var myObj=new Object(); myObj.element=element; element.someObject=myObj;

这样就不会有垃圾回收的过程。

eval 是做什么的

它的功能是将对应的字符串解析成 JS 并执行,应该避免使用 JS,因为非常消耗性能(2 次,一次解析成 JS,一次执行)

如何理解前端模块化

一个模块是能实现特定功能的文件,有了模块就可以方便的使用别人的代码,想要什么 功能就能加载什么模块。

CommonJS:开始于服务器端的模块化,同步定义的模块化,每个模块都是一个单独的 作用域,模块输出,modules.exports,模块加载 require()引入模块。

AMD:中文名异步模块定义的意思。

requireJS 实现了 AMD 规范,主要用于解决下述两个问题。

1.多个文件有依赖关系,被依赖的文件需要早于依赖它的文件加载到浏览器

2.加载的时候浏览器会停止页面渲染,加载文件越多,页面失去响应的时间越长。 语法:requireJS 定义了一个函数 define,它是全局变量,用来定义模块。

总结 AMD 规范:require()函数在加载依赖函数的时候是异步加载的,这样浏览器不 会失去响应,它指定的回调函数,只有前面的模块加载成功,才会去执行。 因为网页在加载 JS 的时候会停止渲染,因此我们可以通过异步的方式去加载 JS,而如果 需要依赖某些,也是异步去依赖,依赖后再执行某些方法。

实现一个 once 函数,传入函数参数只执行一次

function ones(func){ 

var tag=true; 

return function(){ 

if(tag==true){ 

func.apply(null,arguments); 

tag=false; }

return undefined 

}}

将原生的 ajax 封装成 promise

var myNewAjax=function(url){ 

return new Promise(function(resolve,reject){ 

var xhr = new XMLHttpRequest(); 

xhr.open('get',url); 

xhr.send(data); 

xhr.onreadystatechange=function(){

if(xhr.status==200&&readyState==4){ 

var json=JSON.parse(xhr.responseText); 

resolve(json) }

else if(xhr.readyState==4&&xhr.status!=200){ 

reject('error'); }}})}

JS 监听对象属性的改变

我们假设这里有一个 user 对象,

(1)在 ES5 中可以通过 Object.defineProperty 来实现已有属性的监听 Object.defineProperty(user,'name',{

set:function(key,value){ }

})

缺点:如果 id 不在 user 对象中,则不能监听 id 的变化

(2)在 ES6 中可以通过 Proxy 来实现

var user = new Proxy({},{

set:function(target,key,value,receiver){

}})

这样即使有属性在 user 中不存在,通过 user.id 来定义也同样可以这样监听这个属性的 变化哦。

setTimeout、setInterval 和 requestAnimationFrame 之间的区别

与 setTimeout 和 setInterval 不同,requestAnimationFrame 不需要设置时间间隔, 大多数电脑显示器的刷新频率是 60Hz,大概相当于每秒钟重绘 60 次。大多数浏览器都 会对重绘操作加以限制,不超过显示器的重绘频率,因为即使超过那个频率用户体验也 不会有提升。因此,最平滑动画的最佳循环间隔是 1000ms/60,约等于 16.6ms。 RAF 采用的是系统时间间隔,不会因为前面的任务,不会影响 RAF,但是如果前面的 任务多的话, 会响应 setTimeout 和 setInterval 真正运行时的时间间隔。 特点:

(1)requestAnimationFrame 会把每一帧中的所有 DOM 操作集中起来,在一次重绘或回 流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率。

(2)在隐藏或不可见的元素中,requestAnimationFrame 将不会进行重绘或回流,这当然 就意味着更少的 CPU、GPU 和内存使用量

(3)requestAnimationFrame 是由浏览器专门为动画提供的 API,在运行时浏览器会自动 优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了 CPU 开销

实现一个两列等高布局,讲讲思路

为了实现两列等高,可以给每列加上 padding-bottom:9999px; margin-bottom:-9999px;同时父元素设置 overflow:hidden;

自己实现一个 bind 函数

原理:通过 apply 或者 call 方法来实现。

(1)初始版本

Function.prototype.bind=function(obj,arg){ 

var arg=Array.prototype.slice.call(arguments,1); 

var context=this; 

return function(newArg){ 

arg=arg.concat(Array.prototype.slice.call(newArg)); 

return context.apply(obj,arg); 

}}

(2) 考虑到原型链 为什么要考虑?因为在 new 一个 bind 过生成的新函数的时候,必须的条件是要继承原 函数的原型

Function.prototype.bind=function(obj,arg){ 

var arg=Array.prototype.slice.call(arguments,1); 

var context=this; 

var bound=function(newArg){ 

arg=arg.concat(Array.prototype.slice.call(newArg)); 

return context.apply(obj,arg); }

var F=function(){} 

//这里需要一个寄生组合继承 

F.prototype=context.prototype; 

bound.prototype=new F(); 

return bound; }

JS 判断类型

判断方法:typeof(),instanceof,Object.prototype.toString.call()等

去除字符串首尾空格

使用正则(^\s*)|(\s*$)即可

性能优化

减少 HTTP 请求

使用内容发布网络(CDN)

添加本地缓存

压缩资源文件

将 CSS 样式表放在顶部,把 javascript 放在底部(浏览器的运行机制决定)

避免使用 CSS 表达式

减少 DNS 查询

使用外部 javascript 和 CSS

避免重定向

图片 lazyLoad

为什么要用JS 的闭包:

匿名自执行函数:我们知道所有的变量,如果不加上 var 关键字,则默认的会添加到全 局对象的属性上去,这样的临时变量加入全局对象有很多坏处,比如:别的函数可能误 用这些变量;造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链 上遍历的)。除了每次使用变量都是用 var 关键字外,我们在实际情况下经常遇到这样一 种情况,即有的函数只需要执行一次,其内部变量无需维护,可以用闭包。 结果缓存:我们开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象, 每次调用都会花费很长时间,那么我们就需要将计算出来的值存储起来,当调用这个函 数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如 果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部 的引用,从而函数内部的值可以得以保留。

能来讲讲 JS 的语言特性吗

运行在客户端浏览器上;

不用预编译,直接解析执行代码;

是弱类型语言,较为灵活;

与操作系统无关,跨平台的语言;

脚本语言、解释性语言

JS 实现跨域

什么是跨域?

跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览 器对 JavaScript 实施的安全限制,那么只要协议、域名、端口有任何一个不同,都被当 作是不同的域。跨域原理,即是通过各种方式,避开浏览器的安全限制

JSONP:通过动态创建 script,再请求一个带参网址实现跨域通信。document.domain + iframe 跨域:两个页面都通过 js 强制设置 document.domain 为基础主域,就实现了同域。 location.hash + iframe 跨域:a 欲与 b 跨域相互通信,通过中间页 c 来实现。 三个页面, 不同域之间利用 iframe 的 location.hash 传值,相同域之间直接 js 访问来通信。 window.name + iframe跨域:通过iframe的src属性由外域转向本地域,跨域数据即由iframe 的 window.name 从外域传递到本地域。 postMessage 跨域:可以跨域操作的 window 属性之一。

CORS:服务端设置 Access-Control-Allow-Origin 即可,前端无须设置,若要带 cookie 请 求,前后端都需要设置。 代理跨域:启一个代理服务器,实现数据的转发

游戏时候老是卡顿 甚至崩溃

原因可能是:

1.内存溢出问题。

2.资源过大问题。

3.资源加载问题。

4.canvas 绘制频率问题

解决办法:

1.针对内存溢出问题,我们应该在钢管离开可视区域后,销毁钢管,让垃圾收集器回收 钢管,因为不断生成的钢管不及时清理容易导致内存溢出游戏崩溃。

2.针对资源过大问题,我们应该选择图片文件大小更小的图片格式,比如使用 webp、png 格式的图片,因为绘制图片需要较大计算量。

3.针对资源加载问题,我们应该在可视区域之前就预加载好资源,如果在可视区域生成 钢管的话,用户的体验就认为钢管是卡顿后才生成的,不流畅。

4.针对 canvas 绘制频率问题,我们应该需要知道大部分显示器刷新频率为 60 次/s,因此 游戏的每一帧绘制间隔时间需要小于 1000/60=16.7ms,才能让用户觉得不卡顿。

什么是按需加载

当用户触发了动作时才加载对应的功能。触发的动作,是要看具体的业务场景而言,包 括但不限于以下几个情况:鼠标点击、输入文字、拉动滚动条,鼠标移动、窗口大小更 改等。加载的文件,可以是 JS、图片、CSS、HTML 等。

说一下什么是 virtual dom

用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树, 插到文档当中 当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树 进行比较,记录两棵树差异 把所记录的差异应用到所构建的真正的 DOM 树上,视图就 更新了。Virtual DOM 本质上就是在 JS 和 DOM 之间做了一个缓存

ant-design 优点和缺点

优点:组件非常全面,样式效果也都比较不错。

缺点:框架自定义程度低,默认 UI 风格修改困难。

JS 中继承实现的几种方式

1、原型链继承,将父类的实例作为子类的原型,他的特点是实例是子类的实例也是父 类的实例,父类新增的原型方法/属性,子类都能够访问,并且原型链继承简单易于实 现,缺点是来自原型对象的所有属性被所有实例共享,无法实现多继承,无法向父类构 造函数传参。

2、构造继承,使用父类的构造函数来增强子类实例,即复制父类的实例属性给子类, 构造继承可以向父类传递参数,可以实现多继承,通过 call 多个父类对象。但是构造继 承只能继承父类的实例属性和方法,不能继承原型属性和方法,无法实现函数服用,每 个子类都有父类实例函数的副本,影响性能

3、实例继承,为父类实例添加新特性,作为子类实例返回,实例继承的特点是不限制 调用方法,不管是 new 子类()还是子类()返回的对象具有相同的效果,缺点是实 例是父类的实例,不是子类的实例,不支持多继承

4、拷贝继承:特点:支持多继承,缺点:效率较低,内存占用高(因为要拷贝父类的 属性)无法获取父类不可枚举的方法(不可枚举方法,不能使用 for in 访问到)

5、组合继承:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父 类实例作为子类原型,实现函数复用

6、寄生组合继承:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构 造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点

简单介绍一下 symbol

Symbol 是 ES6 的新增属性,代表用给定名称作为唯一标识,这种类型的值可以这样创 建,let id=symbol(“id”)

Symbl 确保唯一,即使采用相同的名称,也会产生不同的值,我们创建一个字段,仅为 知道对应 symbol 的人能访问,使用 symbol 很有用,symbol 并不是 100%隐藏,有内置方 法 Object.getOwnPropertySymbols(obj)可以获得所有的 symbol。 也有一个方法 Reflect.ownKeys(obj)返回对象所有的键,包括 symbol。 所以并不是真正隐藏。但大多数库内置方法和语法结构遵循通用约定他们是隐藏的。

什么是事件监听

addEventListener()方法,用于向指定元素添加事件句柄,它可以更简单的控制事件,语法为element.addEventListener(event, function, useCapture);

第一个参数是事件的类型(如 "click" 或 "mousedown").

第二个参数是事件触发后调用的函数。

第三个参数是个布尔值用于描述事件是冒泡还是捕获。该参数是可选的。

事件传递有两种方式,冒泡和捕获

事件传递定义了元素事件触发的顺序,如果你将 P 元素插入到 div 元素中,用户点击 P 元素, 在冒泡中,内部元素先被触发,然后再触发外部元素, 捕获中,外部元素先被触发,在触发内部元素。

介绍一下 promise,及其底层如何实现

Promise 是一个对象,保存着未来将要结束的事件,她有两个特征:

1、对象的状态不受外部影响,Promise 对象代表一个异步操作,有三种状态,pending 进行中,fulfilled 已成功,rejected 已失败,只有异步操作的结果,才可以决定当前是哪 一种状态,任何其他操作都无法改变这个状态,这也就是 promise 名字的由来

2、一旦状态改变,就不会再变,promise 对象状态改变只有两种可能,从 pending 改到 fulfilled 或者从 pending 改到 rejected,只要这两种情况发生,状态就凝固了,不会再改 变,这个时候就称为定型 resolved,

Promise 的基本用法,


let promise1 = new Promise(function(resolve,reject){ 

setTimeout(function(){ 

resolve('ok') },1000) 

})

promise1.then(function success(val){ 

console.log(val) 

})

最简单代码实现 promise

class PromiseM { 

constructor (process) {

this.status = 'pending' 

this.msg = '' 

process(this.resolve.bind(this), 

this.reject.bind(this)) 

return this 
}

resolve (val){ 

this.status = 'fulfilled' 

this.msg = val 
}

reject (err) { 

this.status = 'rejected' 

this.msg = err 
}

then (fufilled, reject) { 

if(this.status === 'fulfilled') { 

fufilled(this.msg) 

}if(this.status === 'rejected') { 

reject(this.msg) 

}}}

//测试代码

var mm=new PromiseM(function(resolve,reject){ 
resolve('123'); 
}); 
mm.then(function(success){ 
console.log(success); 
},function(){ console.log('fail!'); });

箭头函数

箭头函数与普通函数的区别在于: 1、箭头函数没有 this,所以需要通过查找作用域链来确定 this 的值,这就意味着如果箭 头函数被非箭头函数包含,this 绑定的就是最近一层非箭头函数的 this, 2、箭头函数没有自己的 arguments 对象,但是可以访问外围函数的 arguments 对象 3、不能通过 new 关键字调用,同样也没有 new.target 值和原型

setTimeout(fn,100);100 毫秒是如何权衡的

setTimeout()函数只是将事件插入了任务列表,必须等到当前代码执行完,主线程才会去 执行它指定的回调函数,有可能要等很久,所以没有办法保证回调函数一定会在 setTimeout 指定的时间内执行,100 毫秒是插入队列的时间+等待的时间

怎么获得对象上的属性:比如说通过 Object.key()

从 ES5 开始,有三种方法可以列出对象的属性 for(let I in obj)该方法依次访问一个对象及其原型链中所有可枚举的类型 object.keys:返回一个数组,包括所有可枚举的属性名称 object.getOwnPropertyNames:返回一个数组包含不可枚举的属性

如果已经有三个 promise,A、B 和 C,想串行执行,该怎么写?

// promise

A.then(B).then(C).catch(...)

// async/await

(async ()=>{ await a(); await b(); await c(); })()

知道 private 和 public 吗

public:public 表明该数据成员、成员函数是对所有用户开放的,所有用户都可以直接进 行调用

private:private 表示私有,私有的意思就是除了 class 自己之外,任何人都不可以直接使 用

知道哪些 ES6,ES7 的语法

promise,await/async,let、const、块级作用域、箭头函数

怎么实现一个计算一年中有多少周?

首先你得知道是不是闰年,也就是一年是 365 还是 366. 其次你得知道当年 1 月 1 号是周几。假如是周五,一年 365 天把 1 号 2 号 3 号减去,也 就是把第一个不到一周的天数减去等于 362 还得知道最后一天是周几,加入是周五,需要把周一到周五减去,也就是 362-5=357. 正常情况 357 这个数计算出来是 7 的倍数。357/7=51 。即为周数。

口述数组去重

法一:indexOf 循环去重

法二:ES6 Set 去重;Array.from(new Set(array))

法三:Object 键值对去重;把数组的值存成 Object 的 key 值,比如 Object[value1] = true, 在判断另一个值的时候,如果 Object[value2]存在的话,就说明该值是重复的。

arguments

arguments 是类数组对象,有 length 属性,不能调用数组方法 可用 Array.from()转换

Eventloop

任务队列中,在每一次事件循环中,macrotask 只会提取一个执行,而 microtask 会一直 提取,直到 microsoft 队列为空为止。 也就是说如果某个 microtask 任务被推入到执行中,那么当主线程任务执行完成后,会 循环调用该队列任务中的下一个任务来执行,直到该任务队列到最后一个任务为止。而 事件循环每次只会入栈一个 macrotask,主线程执行完成该任务后又会检查 microtasks 队 列并完成里面的所有任务后再执行 macrotask 的任务。macrotasks: setTimeout, setInterval, setImmediate, I/O, UI rendering microtasks: process.nextTick, Promise, MutationObserver

| 服务端编程

JSONP 的缺点

JSON 只支持 get,因为 script 标签只能使用 get 请求;

JSONP 需要后端配合返回指定格式的数据。

跨域(jsonp,ajax)

代理跨域:起一个代理服务器,实现数据的转发

JSONP:ajax 请求受同源策略影响,不允许进行跨域请求,而 script 标签 src 属性中的链 接却可以访问跨域的 js 脚本,利用这个特性,服务端不再返回 JSON 格式的数据,而是 返回一段调用某个函数的 js 代码,在 src 中进行了调用,这样实现了跨域。

写出原生 Ajax

Ajax 能够在不重新加载整个页面的情况下与服务器交换数据并更新部分网页内容,实现 局部刷新,大大降低了资源的浪费,是一门用于快速创建动态网页的技术,ajax 的使用 分为四部分:

1、创建 XMLHttpRequest 对象 var xhr = new XMLHttpRequest();

2、向服务器发送请求,使用 xmlHttpRequest 对象的 open 和 send 方法,

3、监听状态变化,执行相应回调函数

var xhr = new XMLHttpRequest(); 
xhr.open('get', 'aabb.php', true); 
xhr.send(null); 
xhr.onreadystatechange = function() { 
if(xhr.readyState==4) { 
if(xhr.status==200) { 
console.log(xhr.responseText); 
}}}

发出两个有顺序的 ajax,可以用回调函数,也可以使用 Promise.then 或者 async 等。

Fetch 和 Ajax 比有什么优缺点?

promise 方便异步,在不想用 jQuery 的情况下,相比原生的 ajax,也比较好写

移动端适配 1px 的问题

在 window 对象中有一个 devicePixelRatio 属性,他可以反应 css 中的像素与设备 的像素比。然而 1px 在不同的移动设备上都等于这个移动设备的 1px,这是因为 不同的移动设备有不同的像素密度。有关这个属性,它的官方的定义为:设备物 理像素和设备独立像素的比例,也就是 devicePixelRatio = 物理像素 / 独立像素 1px 变粗的原因:viewport 的设置和屏幕物理分辨率是按比例而不是相同的. 移动 端 window 对象有个 devicePixelRatio 属性,它表示设备物理像素和 css 像素的比例, 在 retina 屏的 iphone 手机上, 这个值为 2 或 3,css 里写的 1px 长度映射到物理像素 上就有 2px 或 3px 那么长

toB 和 toC 项目的区别

to B(business)即面向企业,to C( customer)即面向普通用户 简单的事情重复去做,重复的事情用心去做,长期坚持,自然功成,无论是 B 端还是 C 端都同样适用。

最近团队在 toB 产品研究的过程中,得出结论,相对于 toC 产品与服务,toC 产品更注重 产品用户的共性而淡化角色关系,而 toB 产品则更强调面向用户、客户的角色关系,而 淡化共性提取。实际上,这是由服务对象所引起的,C 端产品的服务对象,由终端所限, 是一个面向个体的服务。而 B 端服务使用最终是面向一个系统体系组织,在干系人间配 合使用中发挥产品价值。 一个好的产品 toB 可以让组织的系统变得更好,最终反哺于系统中的各个单位。 需求动力之不同 toC 的产品方法论,用户体验是几乎最为重要的需求来源,腾讯此前, 也以"以用户体验为归依"来驱动企业产品打造。 但 B 端产品则不同,B 端在一个商业的背景之下,B 端的决策思路是,"以企业获益为归 依",系统是否有利于企业的生产力,竞争力等,单纯的用户体验,仅能让员工得到片 刻的享受, 但无法说服企业,企业并不会为一个不能"赚钱"的东西买单。 需求动力的不同,引发的这是购买使用决策体系的变化。 toB 产品应更考虑 获益与系统性价值,部分情况还有可能会牺牲掉局部个体的利益,对 于使用者而言应该是自律或他律的,toC 产品则更考虑的是个体用户的偏好,并长时间 内,基于技术效率的提升,产品的服务中心更多地围绕着更高效地帮助用户的"欲望"释 放进行设计,对于使用者而言是一个释放自我的存在

移动端兼容性

1.IOS 移动端 click 事件 300ms 的延迟相应 FastClick库

3.h5 底部输入框被键盘遮挡问题

10.CSS 动画页面闪白,动画卡顿

解决方法:

1.尽可能地使用合成属性 transform 和 opacity 来设计 CSS3 动画,不使用 position 的 left 和 top 来定位

2.开启硬件加速

9.上下拉动滚动条时卡顿、慢

body {-webkit-overflow-scrolling: touch;overflow-scrolling: touch;} Android3+和 iOS5+支持 CSS3 的新属性为 overflow-scrolling

| 前端工程化

Babel 的原理是什么?

babel 的转译过程也分为三个阶段,这三步具体是:

解析 Parse: 将代码解析生成抽象语法树( 即 AST ),即词法分析与语法分 析的过程

转换 Transform: 对于 AST 进行变换一系列的操作,babel 接受得到 AST 并通过 babel-traverse 对其进行遍历,在此过程中进行添加、更新 及移除等操作

生成 Generate: 将变换后的 AST 再转换为 JS 代码, 使用到的模块是 babel-generator

webpack 和 gulp 区别(模块化与流的区别)

gulp 强调的是前端开发的工作流程,我们可以通过配置一系列的 task,定义 task 处理的 事务(例如文件压缩合并、雪碧图、启动 server、版本控制等),然后定义执行顺序, 来让 gulp 执行这些 task,从而构建项目的整个前端开发流程。 webpack 是一个前端模块化方案,更侧重模块打包,我们可以把开发中的所有资源(图 片、js 文件、css 文件等)都看成模块,通过 loader(加载器)和 plugins(插件)对资源 进行处理,打包成符合生产环境部署的前端资源。

| Vue 框架

说说 Vue 的优缺点

Vue 是一个构建数据驱动的渐进性框架,它的目标是通过 API 实现响应数据绑定和视图 更新。

优点:

1、数据驱动视图,对真实 dom 进行抽象出 virtual dom(本质就是一个 js 对象), 并配合 diff 算法、响应式和观察者、异步队列等手段以最小代价更新 dom,渲染 页面

2、组件化,组件用单文件的形式进行代码的组织编写,使得我们可以在一个文 件里编写 html\css(scoped 属性配置 css 隔离)\js 并且配合 Vue-loader 之后,支 持更强大的预处理器等功能

3、强大且丰富的 API 提供一系列的 api 能满足业务开发中各类需求

4、由于采用虚拟 dom,让 Vue ssr 先天就足

5、生命周期钩子函数,选项式的代码组织方式,写熟了还是蛮顺畅的,但仍然 有优化空间(Vue3 composition-api)

6、生态好,社区活跃

缺点:

1、由于底层基于 Object.defineProperty 实现响应式,而这个 api 本身不支持 IE8 及以下浏览器

2、csr 的先天不足,首屏性能问题(白屏)

3、由于百度等搜索引擎爬虫无法爬取 js 中的内容,故 spa 先天就对 seo 优化心 有余力不足(谷歌的 puppeteer 就挺牛逼的,实现预渲染底层也是用到了这个工 具)

Vue 和 React 有什么不同?使用场景分别是什么?

1、Vue 是完整一套由官方维护的框架,核心库主要有由尤雨溪大神独自维护,而 React 是不要脸的书维护(很多库由社区维护),曾经一段时间很多人质疑 Vue 的后续维护性, 似乎这并不是问题。

2、Vue 上手简单,进阶式框架,白话说你可以学一点,就可以在你项目中去用一点, 你不一定需要一次性学习整个 Vue 才能去使用它,而 React,恐怕如果你这样会面对项 目束手无策。

3、语法上 Vue 并不限制你必须 es6+完全 js 形式编写页面,可以视图和 js 逻辑尽可能分 离,减少很多人看不惯 React-jsx 的恶心嵌套,毕竟都是作为前端开发者,还是更习惯 于 html 干净。

4、很多人说 React 适合大型项目,适合什么什么,Vue 轻量级,适合移动端中小型项目, 其实我想说,说这话的人是心里根本没点逼数,Vue 完全可以应对复杂的大型应用,甚 至于说如果你 React 学的不是很好,写出来的东西或根本不如 Vue 写的,毕竟 Vue 跟着 官方文档撸就行,自有人帮你规范,而 React 比较懒散自由,可以自由发挥

5、Vue 在国内人气明显胜过 React,这很大程度上得益于它的很多语法包括编程思维更 符合国人思想。

什么是虚拟 DOM?

虚拟 dom 是相对于浏览器所渲染出来的真实 dom 的,在 react,vue 等技术出现之前, 我们要改变页面展示的内容只能通过遍历查询 dom 树的方式找到需要修改的 dom 然 后修改样式行为或者结构,来达到更新 ui 的目的。 这种方式相当消耗计算资源,因为每次查询 dom 几乎都需要遍历整颗 dom 树,如果 建立一个与 dom 树对应的虚拟 dom 对象( js 对象),以对象嵌套的方式来表示 dom 树,那么每次 dom 的更改就变成了 js 对象的属性的更改,这样一来就能查找 js 对象 的属性变化要比查询 dom 树的性能开销小。

vue 如何监听键盘事件?

. @keyup. 方法

. addEventListener

mounted() { 

document.addEventListener('keyup', this.handleKey) 

},

beforeDestroy() { document.removeEventListener('keyup', this.handleKey) },

删除数组用 delete 和 Vue.delete 有什么区别?

delete:只是被删除数组成员变为 empty / undefined,其他元素键值不变

Vue.delete:直接删了数组成员,并改变了数组的键值(对象是响应式的,确保 删除能触发更新视图,这个方法主要用于避开 Vue 不能检测到属性被删除的限 制)

Vue 双向绑定原理

Vue 数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)。

v-model 是什么?有什么用呢

一则语法糖,相当于 v-bind:value="xxx" 和 @input,意思是绑定了一个 value 属性的值, 子组件可对 value 属性监听,通过$emit('input', xxx)的方式给父组件通讯。自己实现 v-model 方式的组件也是这样的思路。

axios 是什么?怎样使用它?怎么解决跨域的问题?

axios 的是一种异步请求,用法和 ajax 类似,安装 npm install axios --save 即可使用,请 求中包括 get,post,put, patch ,delete 等五种请求方式,解决跨域可以在请求头中添加 Access-Control-Allow-Origin,也可以在 index.js 文件中更改 proxyTable 配置等解决跨域 问题。

在 vue 项目中如何引入第三方库(比如 jQuery)?有哪些方法可以做到?

1、绝对路径直接引入 在 index.html 中用 script 引入

<script src="./static/jquery-1.12.4.js"></script>

然后在 webpack 中配置

external externals: { 'jquery': 'jQuery' }

在组件中使用时

import import $ from 'jquery'

2 、在 webpack 中配置 alias

resolve: { extensions: ['.js', '.vue', '.json'], alias: { '@': resolve('src'), 'jquery': resolve('static/jquery-1.12.4.js') } } 然后在组件中 import

3、在 webpack 中配置 plugins

plugins: [ new webpack.ProvidePlugin({ $: 'jquery' }) ]

全局使用,但在使用 eslint 情况下会报错,需要在使用了 $ 的代码前添加 /* eslint-disable*/ 来去掉 ESLint 的检查。

说说 Vue React angularjs jquery 的区别

JQuery 与另外几者最大的区别是,JQuery 是事件驱动,其他两者是数据驱动。 JQuery 业务逻辑和 UI 更改该混在一起, UI 里面还参杂这交互逻辑,让本来混乱的逻 辑更加混乱。 Angular,Vue 是双向绑定,而 React 不是 其他还有设计理念上的区别等

Vue3.0 里为什么要用 Proxy API 替代 defineProperty API?

响应式优化。

a. defineProperty API 的局限性最大原因是它只能针对单例属性做监听。 Vue2.x 中的响应式实现正是基于 defineProperty 中的 descriptor,对 data 中的属性做了遍 历 + 递归,为每个属性设置了 getter、setter。 这也就是为什么 Vue 只能对 data 中预定义过的属性做出响应的原因,在 Vue 中使用 下标的方式直接修改属性的值或者添加一个预先不存在的对象属性是无法做到 setter 监 听的,这是 defineProperty 的局限性。

b. Proxy API 的监听是针对一个对象的,那么对这个对象的所有操作会进入监听操作,这 就完全可以代理所有属性,将会带来很大的性能提升和更优的代码。 Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须 先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

c. 响应式是惰性的 在 Vue.js 2.x 中,对于一个深层属性嵌套的对象,要劫持它内部深层次的变化,就需要 递归遍历这个对象,执行 Object.defineProperty 把每一层对象数据都变成响应式的,这 无疑会有很大的性能消耗。

在 Vue.js 3.0 中,使用 Proxy API 并不能监听到对象内部深层次的属性变化,因此它的 处理方式是在 getter 中去递归响应式,这样的好处是真正访问到的内部属性才会变成响 应式,简单的可以说是按需实现响应式,减少性能消耗

基础用法

图片.png

Vue3.0 编译做了哪些优化?

a. 生成 Block tree Vue.js 2.x 的数据更新并触发重新渲染的粒度是组件级的,单个组件内部 需要遍历该组 件的整个 vnode 树。在 2.0 里,渲染效率的快慢与组件大小成正相关:组件越大,渲染 效率越慢。并且,对于一些静态节点,又无数据更新,这些遍历都是性能浪费。 Vue.js 3.0 做到了通过编译阶段对静态模板的分析,编译生成了 Block tree。 Block tree 是一个将模版基于动态节点指令切割的嵌套区块,每个 区块内部的节点结构是固定的, 每个区块只需要追踪自身包含的动态节点。所以,在 3.0 里,渲染效率不再与模板大小 成正相关,而是与模板中动态节点的数量成正相关

b. slot 编译优化 Vue.js 2.x 中,如果有一个组件传入了 slot,那么每次父组件更新的时候,会强制使子组 件 update,造成性能的浪费。 Vue.js 3.0 优化了 slot 的生成,使得非动态 slot 中属性的更新只会触发子组件的更新。 动态 slot 指的是在 slot 上面使用 v-if,v-for,动态 slot 名字等会导致 slot 产生运行时动 态变化但是又无法被子组件 track 的操作

c. diff 算法优化

Vue3.0 新特性 —— Composition API 与 React.js 中 Hooks 的异同点

a. React.js 中的 Hooks 基本使用

React Hooks 允许你 "勾入" 诸如组件状态和副作用处理等 React 功能中。Hooks 只能 用在函数组件中,并允许我们在不需要创建类的情况下将状态、副作用处理和更多东西 带入组件中。 React 核心团队奉上的采纳策略是不反对类组件,所以你可以升级 React 版本、在新组 件中开始尝试 Hooks,并保持既有组件不做任何更改。

useState 和 useEffect 是 React Hooks 中的一些例子,使得函数组件中也能增加状态和 运行副作用。 我们也可以自定义一个 Hooks,它打开了代码复用性和扩展性的新大门

b. Vue Composition API 基本使用

Vue Composition API 围绕一个新的组件选项 setup 而创建。setup() 为 Vue 组件提供了 状态、计算值、watcher 和生命周期钩子。 并没有让原来的 API(Options-based API)消失。允许开发者 结合使用新旧两种 API (向下兼容)

图片.png

c. 原理

React hook 底层是基于链表实现,调用的条件是每次组件被 render 的时候都会顺序执行 所有的 hooks。 Vue hook 只会被注册调用一次,Vue 能避开这些麻烦的问题,原因在于它对数据的响 应是基于 proxy 的,对数据直接代理观察。(这种场景下,只要任何一个更改 data 的地 方,相关的 function 或者 template 都会被重新计算,因此避开了 React 可能遇到的性能 上的问题)。 React 中,数据更改的时候,会导致重新 render,重新 render 又会重新把 hooks 重新注 册一次,所以 React 复杂程度会高一些。

Vue3.0 是如何变得更快的?(底层,源码

a. diff 方法优化

Vue2.x 中的虚拟 dom 是进行全量的对比。 Vue3.0 中新增了静态标记(PatchFlag):在与上次虚拟结点进行对比的时候,值对比 带有 patch flag 的节点,并且可以通过 flag 的信息得知当前节点要对比的具体内容化

b. hoistStatic 静态提升

Vue2.x : 无论元素是否参与更新,每次都会重新创建。 Vue3.0 : 对不参与更新的元素,只会被创建一次,之后会在每次渲染时候被不停的复用。

c. cacheHandlers 事件侦听器缓存

默认情况下 onClick 会被视为动态绑定,所以每次都会去追踪它的变化但是因为是同一 个函数,所以没有追踪变化,直接缓存起来复用即可。

vue 要做权限管理该怎么做?如果控制到按钮级别的权限怎么做

指令权限

vue 在 created 和 mounted 这两个生命周期中请求数据有什么区别呢?

看实际情况,一般在 created(或 beforeRouter) 里面就可以,如果涉及到需要页面加载 完成之后的话就用 mounted。 在 created 的时候,视图中的 html 并没有渲染出来,所以此时如果直接去操作 html 的 dom 节点,一定找不到相关的元素 而在 mounted 中,由于此时 html 已经渲染出来了,所以可以直接操作 dom 节点,(此 时 document.getelementById 即可生效了)

说说你对 proxy 的理解

vue 的数据劫持有两个缺点:

1、无法监听通过索引修改数组的值的变化

2、无法监听 object 也就是对象的值的变化

所以 vue2.x 中才会有$set 属性的存在 proxy 是 es6 中推出的新 api,可以弥补以上两个缺点,所以 vue3.x 版本用 proxy 替换 object.defineproperty

| React 框架

angularJs 和 React 区别

React 对比 Angular 是思想上的转变,它也并不是一个库,是一种开发理念,组件化,分 治的管理,数据与 view 的一体化。它只有一个中心,发出状态,渲染 view,对于虚拟 dom 它并没有提高渲染页面的性能,它提供更多的是利用 jsx 便捷生成 dom 元素,利用组件 概念进行分治管理页面每个部分(例如 header section footer slider)

redux 中间件

中间件提供第三方插件的模式,自定义拦截 action -> reducer 的过程。变为 action -> middlewares -> reducer 。这种机制可以让我们改变数据流,实现如异步 actionaction 过 滤,日志输出,异常报告等功能。 常见的中间件:redux-logger:提供日志输出;redux-thunk:处理异步操作;redux-promise: 处理异步操作;actionCreator 的返回值是 promise

redux 有什么缺点

1.一个组件所需要的数据,必须由父组件传过来,而不能像 flux 中直接从 store 取。

2.当一个组件相关数据更新时,即使父组件不需要用到这个组件,父组件还是会重新 render,可能会有效率影响,或者需要写复杂的 shouldComponentUpdate 进行判断。

React 组件的划分业务组件技术组件?

根据组件的职责通常把组件分为 UI 组件和容器组件。UI 组件负责 UI 的呈现,容器组 件负责管理数据和逻辑。两者通过 React-Redux 提供 connect 方法联系起来。

React 生命周期函数

一、初始化阶段:

getDefaultProps:获取实例的默认属性

getInitialState:获取每个实例的初始化状态

componentWillMount:组件即将被装载、渲染到页面上

render:组件在这里生成虚拟的 DOM 节点

componentDidMount:组件真正在被装载之后

二、运行中状态:

componentWillReceiveProps:组件将要接收到属性的时候调用

shouldComponentUpdate:组件接受到新属性或者新状态的时候(可以返回 false,接收数据 后不更新,阻止 render 调用,后面的函数不会被继续执行了)

componentWillUpdate:组件即将更新不能修改属性和状态

render:组件重新描绘

componentDidUpdate:组件已经更新

三、销毁阶段:

componentWillUnmount:组件即将销毁

React 性能优化是哪个周期函数?

shouldComponentUpdate 这个方法用来判断是否需要调用 render 方法重新描绘 dom。因 为 dom 的描绘非常消耗性能,如果我们能在 shouldComponentUpdate 方法中能够写出更 优化的 dom diff 算法,可以极大的提高性能。

为什么虚拟 dom 会提高性能?

虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要 的 dom 操作,从而提高性能。

具体实现步骤如下:

1.用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树, 插到文档当中;

2.当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记 录两棵树差异;

把 2 所记录的差异应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。

diff 算法?

1.把树形结构按照层级分解,只比较同级元素。

2.给列表结构的每个单元添加唯一的 key 属性,方便比较。

3.React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)

4.合并操作,调用 component 的 setState 方法的时候, React 将其标记为 dirty.到每一个 事件循环结束, React 检查所有标记 dirty 的 component 重新绘制.

6.选择性子树渲染。开发人员可以重写 shouldComponentUpdate 提高 diff 的性能。

React 性能优化方案

1)重写 shouldComponentUpdate 来避免不必要的 dom 操作。

2)使用 production 版本的 React.js。

3)使用 key 来帮助 React 识别列表中所有子组件的最小变化

简述 flux 思想

Flux 的最大特点,就是数据的"单向流动"。

1.用户访问 View

2.View 发出用户的 Action

3.Dispatcher 收到 Action,要求 Store 进行相应的更新

4.Store 更新后,发出一个"change"事件

5.View 收到"change"事件后,更新页面

React 项目用过什么脚手架?Mern? Yeoman?

Mern:MERN 是脚手架的工具,它可以很容易地使用 Mongo, Express, React and NodeJS 生成同构 JS 应用。它最大限度地减少安装时间,并得到您使用的成熟技术来加速开发。

你了解 React 吗?

了解,React 是 facebook 搞出来的一个轻量级的组件库,用于解决前端视图层的一些问 题,就是 MVC 中 V 层的问题,它内部的 Instagram 网站就是用 React 搭建的。

React 解决了什么问题?

解决了三个问题: 1.组件复用问题, 2.性能问题,3.兼容性问题:

React 的协议

React 遵循的协议是“BSD 许可证 + 专利开源协议”,这个协议比较奇葩,如果你的产 品跟 facebook 没有竞争关系,你可以自由的使用 React,但是如果有竞争关系,你的 React 的使用许可将会被取消

了解 shouldComponentUpdate 吗?

React 虚拟 dom 技术要求不断的将 dom 和虚拟 dom 进行 diff 比较,如果 dom 树比价大, 这种比较操作会比较耗时,因此 React 提供了 shouldComponentUpdate 这种补丁函数,如 果对于一些变化,如果我们不希望某个组件刷新,或者刷新后跟原来其实一样,就可以 使用这个函数直接告诉 React,省去 diff 操作,进一步的提高了效率。

React 的工作原理?

React 会创建一个虚拟 DOM(virtual DOM)。当一个组件中的状态改变时,React 首先会 通过 "diffing" 算法来标记虚拟 DOM 中的改变,第二步是调节(reconciliation),会用 diff 的结果来更新 DOM。

使用 React 有何优点?

1.只需查看 render 函数就会很容易知道一个组件是如何被渲染的

2.JSX 的引入,使得组件的代码更加可读,也更容易看懂组件的布局,或者组件之间是 如何互相引用的

3.支持服务端渲染,这可以改进 SEO 和性能

4.易于测试

5.React 只关注 View 层,所以可以和其它任何框架(如 Backbone.js, Angular.js)一起使用

展示组件(Presentational component)和容器组件(Container component)之间有 何不同?

1.展示组件关心组件看起来是什么。展示专门通过 props 接受数据和回调,并且几乎不 会有自身的状态,但当展示组件拥有自身的状态时,通常也只关心 UI 状态而不是数据 的状态。

2.容器组件则更关心组件是如何运作的。容器组件会为展示组件或者其它容器组件提供 数据和行为(behavior),它们会调用 Flux actions,并将其作为回调提供给展示组件。容器 组件经常是有状态的,因为它们是(其它组件的)数据源

类组件(Class component)和函数式组件(Functional component)之间有何不 同?

1.类组件不仅允许你使用更多额外的功能,如组件自身的状态和生命周期钩子,也能使 组件直接访问 store 并维持状态

2.当组件仅是接收 props,并将组件自身渲染到页面时,该组件就是一个 '无状态组件 (stateless component)',可以使用一个纯函数来创建这样的组件。这种组件也被称为哑组 件(dumb components)或展示组件

(组件的)状态(state)和属性(props)之间有何不同?

  1. State 是一种数据结构,用于组件挂载时所需数据的默认值。State 可能会随着时间的 推移而发生突变,但多数时候是作为用户事件行为的结果。

  2. Props(properties 的简写)则是组件的配置。props 由父组件传递给子组件,并且就子组 件而言,props 是不可变的(immutable)。组件不能改变自身的 props,但是可以把其子组件的 props 放在一起(统一管理)。Props 也不仅仅是数据--回调函数也可以通过 props 传递

应该在 React 组件的何处发起 Ajax 请求?

在 React 组件中,应该在 componentDidMount 中发起网络请求。这个方法会在组件第 一次“挂载”(被添加到 DOM)时执行,在组件的生命周期中仅会执行一次。更重要的是, 你不能保证在组件挂载之前 Ajax 请求已经完成,如果是这样,也就意味着你将尝试在 一个未挂载的组件上调用 setState,这将不起作用。在 componentDidMount 中发起网络 请求将保证这有一个组件可以更新了

在 React 中,refs 的作用是什么?

Refs 可以用于获取一个 DOM 节点或者 React 组件的引用。何时使用 refs 的好的示例 有管理焦点/文本选择,触发命令动画,或者和第三方 DOM 库集成。你应该避免使用 String 类型的 Refs 和内联的 ref 回调。Refs 回调是 React 所推荐的。

何为高阶组件(higher order component)?

高阶组件是一个以组件为参数并返回一个新组件的函数。HOC 运行你重用代码、逻辑 和引导抽象。最常见的可能是 Redux 的 connect 函数。除了简单分享工具库和简单的 组合,HOC 最好的方式是共享 React 组件之间的行为。如果你发现你在不同的地方写 了大量代码来做同一件事时,就应该考虑将代码重构为可重用的 HOC。

使用箭头函数(arrow functions)的优点是什么?

  1. 作用域安全:在箭头函数之前,每一个新创建的函数都有定义自身的 this 值(在构造 函数中是新对象;在严格模式下,函数调用中的 this 是未定义的;如果函数被称为“对 象方法”,则为基础对象等),但箭头函数不会,它会使用封闭执行上下文的 this 值。

  2. 简单:箭头函数易于阅读和书写

  3. 清晰:当一切都是一个箭头函数,任何常规函数都可以立即用于定义作用域。开发者 总是可以查找 next-higher 函数语句,以查看 this 的值

为什么建议传递给 setState 的参数是一个 callback 而不是一个对象?

因为 this.props 和 this.state 的更新可能是异步的,不能依赖它们的值去计算下一个 state。

怎么阻止组件的渲染?

在组件的 render 方法中返回 null 并不会影响触发组件的生命周期方法

当渲染一个列表时,何为 key?设置 key 的目的是什么?

Keys 会有助于 React 识别哪些 items 改变了,被添加了或者被移除了。Keys 应该被赋 予数组内的元素以赋予(DOM)元素一个稳定的标识,选择一个 key 的最佳方法是使用一 个字符串,该字符串能惟一地标识一个列表项。很多时候你会使用数据中的 IDs 作为 keys,当你没有稳定的 IDs 用于被渲染的 items 时,可以使用项目索引作为渲染项的 key,但这种方式并不推荐,如果 items 可以重新排序,就会导致 re-render 变慢

(在构造函数中)调用 super(props) 的目的是什么?

在 super() 被调用之前,子类是不能使用 this 的,在 ES2015 中,子类必须在 constructor 中调用 super()。传递 props 给 super() 的原因则是便于(在子类中)能在 constructor 访问 this.props。

何为 JSX ?

JSX 是 JavaScript 语法的一种语法扩展,并拥有 JavaScript 的全部功能。JSX 生产 React "元素",你可以将任何的 JavaScript 表达式封装在花括号里,然后将其嵌入到 JSX 中。在编译完成之后,JSX 表达式就变成了常规的 JavaScript 对象,这意味着你可以在 if 语句和 for 循环内部使用 JSX,将它赋值给变量,接受它作为参数,并从函数中返回 它