Giter VIP home page Giter VIP logo

fe-interview's Introduction

Now is no time to think of what you do not have. Think of what you can do with what there is.

fe-interview's People

Contributors

suukii avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar

fe-interview's Issues

如何实现图片懒加载?

方案一:clientHeight + scrollTop + offsetTop

先给图片一个占位资源,然后通过监听 scroll 事件来判断图片是否到达视口,再给图片设置真实的 src 属性。最好对 scroll 事件做节流处理,以免频繁触发。

img-lazyload

方案二:getBoundingClientRect

在方案一的基础上换了一种方式来判断图片是否到达视口,使用 imgEle.getBoundingClientRect.top() < clientHeight 来判断。

方案三:IntersectionObserver

这个浏览器 API 实现了监听window的scroll事件判断观察对象是否在视口中 以及 节流 三大功能。

什么是CSP,它有什么用?

CSP 指的是内容安全策略,它的本质是建立一个白名单,告诉浏览器哪些外部资源可以加载和执行。我们只需要配置规则,如何拦截由浏览器自己来实现。

通常有两种方式来开启 CSP,一种是设置 HTTP 首部中的 Content-Security-Policy,一种是设置 meta 标签的方式。

CSP 内容安全策略

关于 webpack loader

因为 webpack 只能处理 js 文件,所以对于项目中的其他资源,我们都需要指定一个或多个 loader 来处理它们。loader 本质上是一个函数,输入模块内容,返回处理后的结果,如果指定了多个 loader,那么它们都按从右往左的顺序依次执行,上一个 loader 的输出会作为下一个 loader 的输入。

常用的一些 loader

打包图片

  • file-loader
    • 将图片移到 dist 目录下并重命名
    • 将文件名返回给引入模块的变量中
  • url-loader
    • 将文件打包为 base64 编码,小图片(1~2k)适用,可通过 limit 配置项

打包样式

  • css-loader: 能帮我们分析出几个 CSS 文件之间的关系
  • style-loader: 将 css-loader 生成的文件挂载到 header 标签中
  • sass-loader: 将 Sass 文件转换成 CSS 文件
  • postcss-loader: 通过 postcss.config.js 进行配置,比如使用 autoprefixer 这个插件来自动添加厂商前缀

打包字体

  • file-loader

说一下点击劫持

READING

LAB


点击劫持是一种视觉欺骗的攻击手段,攻击者将需要攻击的网站通过 iframe 的方式嵌入自己的网页中,一般是设为一个透明元素,或者伪装成另外一个元素,诱导用户点击。

对于这种攻击方式,一般推荐以下两种防御方式:

  • 客户端:JS 防御,保证当前的 frame 是最顶层的 window。
  • 服务端: Content Security Policy (CSP) frame-ancestors 指令 (用以替换 X-Frame-Options)。

JS 防御

对于某些低版本的浏览器,只能通过 JS 的方式来防御点击劫持。

<head>
  <style id="click-jack">
    html {
      display: none !important;
    }
  </style>
</head>
<body>
  <script>
    if (self == top) {
      var style = document.getElementById("click-jack");
      document.body.removeChild(style);
    } else {
      top.location = self.location;
    }
  </script>
</body>

CSP frame-ancestors

用于指定哪些源可以通过 <iframe> 等方式来展示当前页面,可以指定一或多个源。

Content-Security-Policy: frame-ancestors <source> <source>;

e.g.

Content-Security-Policy: frame-ancestors 'none';

Content-Security-Policy: frame-ancestors 'self' https://www.example.org;

X-Frame-Options

X-Frame-Options 是一个 HTTP 响应头,用来控制浏览器是否渲染 <frame><iframe> 中的内容,可以设置的值有 3 个:

  • DENY: 表示当前页面不允许通过 iframe 的方式来展示。
  • SAMEORIGIN: 相同域名下,页面可以通过 iframe 的方式来展示。
  • ALLOW-FROM: 允许在指定 URL 中通过 iframe 的方式展示当前页面。

如何实现事件的防抖和节流?

节流

节流的核心**是:如果在定时器的时间范围内再次触发事件,就什么都不做,只有等当前定时器结束后,才能启动新的定时器。
代码思路:用一个 flag 来标识当前是否可以启动定时器,当我们启动一个定时器时,把 flag 设为 false,等这个定时器结束后再把 flag 设为 true。

防抖

每次事件触发时都删除原来的定时器,然后启动一个新的定时器。

加强版防抖

在防抖的情况下,如果事件触发得太频繁,会导致一次响应也没有,但我们希望到了固定时间时必须给用户一个响应。
代码思路:记录上一个定时器结束的时间 last,当事件触发时,计算当前时间与上一个定时器结束时间的差距 now - last,如果时间差大于我们预设的固定时间,就立即执行一次函数。

GET 和 POST 有什么区别?

最直观的就是语义上的区别,一般 GET 用于获取资源,POST 用于提交数据。

具体的区别有:

  • 从缓存的角度:GET 请求会被主动缓存下来,留有历史记录,而 POST 默认不会;
  • 从编码的角度:GET 只能进行 URL 编码,只接收 ASCII 字符,而 POST 没有限制;
  • 从参数的角度:GET 的参数一般放在 URL 中,而 POST 则放在请求体中,更适合传输对一般用户敏感的信息,不过,把参数放在请求体中并没有比放在 URL 中更安全;
  • 幂等性:GET 请求是幂等的,POST 不是;
  • 从 TCP 的角度:GET 请求的报文会被一次性发送出去,而 POST 则会被分成两个 TCP 数据报,header 部分先发送,等待服务器响应 100(continue) 后,再发送 body 部分。

防抖和节流的应用场景有哪些

防抖

防抖是为了避免把一次事件误认为是多次,重在清零(clearTimeout),单位时间内事件重复触的话计时器会被重置。

  • 登录、发信息等按钮避免用户点击太快导致发送了多次请求,需要防抖
  • 调整浏览器窗口大小时,为避免 resize 事件触发过于频繁造成计算过多,需要用到防抖
  • 文本编辑器实时保存时,当无任何更改操作一秒后进行保存,这个需求可以用防抖来实现

节流

节流是控制事件发生的频率,比如控制事件发生频率为 1s,那么即使在 1s 内多次触发了事件,我们都当作它只发生了 1 次,单位时间内事件重复触发的话也只会被处理一次。

  • scroll 事件,使用节流每隔 1 s 才计算位置信息之类的
  • 浏览器播放事件,每秒进行一次进度信息的计算
  • input 框实时搜索并发送请求展示下拉列表,每隔 1 s 发送一次请求(也可以做防抖)

说说 TCP 三次握手的过程?为什么是三次而不是两次或四次?

三次握手的过程其实就是为了确认通信双方的发送能力和接收能力。

第一次是客户端主动发起请求,向服务器发送 SYN,确认了客户端的发送能力。

第二次是服务器收到 SYN 后,给客户端返回 SYN + ACK,确认了服务器的接收能力和发送能力。

第三次是客户端收到服务器的 SYN + ACK 后,发送 ACK,确认了客户端的接收能力。

如果只有两次,那就无法确认客户端的接收能力。

为什么不是四次?因为三次握手已经足以确认通信双方的发送能力和接收能力,当然四次也能确认,但三次已经足够了,再多也没什么意义。

VUE 的生命周期

总共分为 8 个

  • 创建前后 (beforeCreate, created)

    • 在 beforeCreate 阶段,VUE 实例的挂载元素 el 还不存在。
  • 挂载前后 (beforeMount, mounted)

    • 在 beforeMount 阶段,VUE 实例的 $eldata 都已经初始化了,但还是虚拟 DOM 节点,模板中的 data.message 还未替换。
    • 在 mounted 阶段,VUE 实例挂载完成,模板中的 data.message 成功渲染。
  • 更新前后 (beforeUpdate, updated):

    • data 发生变化时会触发这两个生命周期函数
  • 销毁前后 (beforeDestroy, destroyed):

    • 在执行 destroy 方法之后,对 data 的修改不会再触发生命周期函数,此时 VUE 实例已经解除了事件监听和 DOM 绑定,但 DOM 结构依然存在。

能不能讲讲 DNS 查询过程?

DNS 的工作就是将域名映射为 IP

一开始我们会请求本地 DNS 服务器,它再分别去请求根域名名称服务器顶级域名名称服务器次级域名名称服务器,多个来回之后拿到了我们想要的 IP 地址,这时它拿到的可能是一个也可能是多个 IP 地址。如果收到的是多个 IP 地址,客户端就可以从中随机选择一个发起请求,这样就实现了负载均衡。

更详细的过程

  1. 用户在浏览器中输入域名,发起请求;
  2. 本地 DNS 服务器将请求路由到根名称服务器,根名称服务器告诉它去某个顶级域名名称服务器查询;
  3. 本地 DNS 服务器再将请求路由到那个顶级域名名称服务器,顶级域名名称服务器告诉它可以去哪些次级域名名称服务器查询;
  4. 本地 DNS 服务器再将请求路由到某个次级域名名称服务器,次级域名名称服务器把最终的 IP 地址返回;
  5. 本地 DNS 服务器拿到 IP 地址后返回给浏览器;

更更详细的解释

【每日一题】- 2020-04-03 - DNS 查询是递归查询还是迭代查询? --suukii
【每日一题】- 2020-04-03 - DNS 查询是递归查询还是迭代查询? --lucifer

能不能说说浏览器的本地存储?各自的优劣如何?

浏览器的本地存储主要分为 CookieWebStorageIndexDB,其中 WebStorage 又分为 localStoragesessionStorage

Cookie

Cookie 是用来做状态存储的,它有几个缺陷:

  • 容量小,上限只有 4K。
  • 有性能缺陷,因为在同域名下的所有请求都会携带完整的 Cookie,即使是在不需要 Cookie 的情况下,如果这种请求很多,会造成性能浪费。
  • 有安全缺陷,因为 Cookie 是以纯文本形式传递的,容易在发送到服务器之前被截获、篡改,另外,HTTPOnlyfalse 的 Cookie 可以通过 JS 读取。

localStorage

localStorage 是持久化存储,它的优点有:

  • 容量较大,同一个域名的上限是 5M。
  • 不参与和服务器的通信,避免了 Cookie 的性能和安全问题。
  • 封装了接口,使用方便。

sessionStorage

sessionStorage 跟 localStorage 一样,除了一个本质的区别,sessionStorage 的存储是会话级别的,在页面关闭之后不会再存在。

IndexDB

IndexDB 是运行在浏览器上的非关系型数据库,为大型数据的存储提供了接口,它的存储容量理论上是无限制的。

能不能说说 CSRF 攻击

概念

Cross-site request foregery,跨站请求攻击,指的是攻击方诱导用户进入第三方网站(可能是攻击方自己的网站,也可能是其他网站),在第三方网站中,利用用户在被攻击网站的登录状态,向被攻击网站发起跨站请求,绕过被攻击网站后台的用户验证,达到冒充用户对被攻击网站进行某项操作的目的。

CSRF 的攻击原理是诱导用户跳转到新的页面,利用服务器的验证漏洞和用户之前的登录状态来冒充用户进行操作。

CSRF 一般流程

  • 用户登录 aaa.com,保留了登录凭证 Cookie;
  • 攻击方引诱用户打开了 bbb.com;
  • 在 bbb.com 中,攻击方发起了一个请求:aaa.com/act=boom,由于用户在 aaa.com 登录了,这个请求会带上 aaa.com 的 Cookie;
  • aaa.com 的服务器收到请求,验证 Cookie,以为这是用户自己发的正常请求,以该用户的名义执行了请求的内容;
  • 攻击完成,攻击方在用户不知情的情况下,让 aaa.com 执行了他自定义的操作。

webpack plugin 有什么用

插件有点像一个生命周期函数,可以在 webpck 打包过程中的某些时刻做一些事情。

  • html-webpack-plugin: 会在打包结束后自动生成一个 html 文件,并自动引入打包生成的 JS 文件。
  • clean-webpack-plugin: 在打包前先清空 dist 目录

什么是中间人攻击 MITM


中间人攻击是攻击方拦截了通信双方的连接,并重新与它们分别建立连接,控制整个通信过程。比如在一个 HTTP 通信中,攻击方会拦截客户端和服务器的 TCP 连接,并分别建立 客户端 <-> 攻击方 以及 攻击方 <-> 服务器 的 TCP 连接,此时攻击方就相当于一个代理,不仅可以获得双方的通信信息,还能对通信信息进行修改,而通信双方对此毫不知情。

通常来说不建议使用公共的 Wi-Fi,因为很可能会发生中间人攻击的情况,如果在通信过程中传送了敏感信息,就完全泄露给了攻击方。

当然 HTTPS 是一种防御中间人攻击的手段,通过增加一个安全通道来传输信息。不过中间人攻击同样也是可以用于 HTTPS 连接的,只是多了一个 SSL 连接,攻击方先跟客户端建立 SSL 连接,再和服务器建立 SSL 连接。一般这种情况下客户端会提醒用户当前证书是不安全的,但也有可能在某些情况下,攻击方破解了服务器的证书,或者攻击方的证书来自可信赖的 CA 并且 CN 和服务器的一样,这样客户端就不会弹出警告了。而且,攻击方还可能通过某些方式将 HTTPS 降级为 HTTP 从而实现中间人攻击。

axios vs fetch

axios fetch
兼容性 兼容性好,甚至支持 IE11 兼容性没那么好,但是可以通过 whatwg-fetch 这样的 polyfill 库来弥补
超时设置 可以通过 timeout 属性设置超时时间 可以通过 AbortController API 加上定时器来实现
数据格式 会自动把数据转换成 JSON 格式(可以改写) 需要自行转换数据格式
拦截器 提供拦截器拦截 HTTP 请求 可以通过改写原生的 fetch 方法来实现拦截器的效果
进度条 通过 axios progress bar 模块能轻松实现 在响应数据 body 中提供 ReadableStream 实例,可以通过这个实例来实现进度条功能
并行请求 提供 axios.all()axios.spread() 可以借助 Promise.all()

HTTP 请求方法和报文结构

如何理解 HTTP 请求方法

  • GET:通常用来获取资源
  • POST:上传数据
  • OPTIONS:查询可对资源实行的请求方法,用来进行跨域预请求
  • HEAD:获取资源的元信息
  • PUT:修改数据
  • DELETE:删除资源
  • CONNECT:建立连接隧道,用于代理服务器
  • TRACE:追踪请求-响应的传输路径

HTTP 报文结构是怎样的

HTTP 报文的组成是 起始行 + 头部 + 空行 + 实体

  • 起始行:请求报文的起始行包括请求方法 + 路径 + HTTP 版本,响应报文的起始行包括 HTTP 版本 + 状态码 + 状态码文字解释
  • 头部:是一系列 字段名: 值
  • 空行:用来区分头部和实体
  • 实体:具体的数据

webpack 配置文件

webpack.config.js 是 webpack 的默认打包配置文件,也可以通过 npx webpack --config [name] 来设置。

常用配置项

  • mode:打包环境,分为 productiondevelopment,生产环境下代码会被压缩
  • 多入口:在 entry 中指定多个值
  • 为打包后的 JS 加前缀:在 output 中指定 publicPath
  • devtool:就是去配置 sourcemap,方便调试,准确定位到代码错误:
    • cheap:定位到行,不定位到列
    • module:把依赖模块中的代码一并做映射
    • eval:使用 eval 形式做 sourcemap 映射
    • inline:行内的映射关系

推荐的 devtool 配置:

// dev
devtool: 'cheap-module-eval-source-map'

// prod
devtool: 'cheap-module-source-map'

webpack 中的性能优化

减小打包体积

  1. 按需加载:如果我们将代码全部打包进一个 JS 文件中,虽然减少了请求数,但同时也加载了很多暂时不需要的代码,耗费了更长时间,而且,在 HTTP/2 中,这种做法已经算不上有优势了。为了能更快地呈现页面,每个页面需要加载地文件体积当然要越小越好,这时候我们就可以使用按需加载,将每个路由页面单独打包。

  2. Tree Shaking:删除项目中未被使用的代码,在 webpack4 中生产环境会启动开启这个优化功能。

  3. Scope Hoisting:会分析模块之间的依赖关系,然后在打包过程中尽可能把多个模块合并到一个函数中,减少代码量。在 webpack4 中可以通过 optimization.concatenateModules 开启这个功能。

什么是 MVVM

Model-View-ViewModel 是一种设计**:

  • Model 层代表数据模型,可以在这里定义数据和操作数据的逻辑;
  • View 层代表 UI 组件,负责将数据模型转化成 UI 展示出来;
  • ViewModel:是一个负责同步 View 和 Model 的对象;

在 MVVM 架构下,View 和 Model 没有直接联系,而是通过 ViewModel 进行交互,ViewModel 通过双向数据绑定把两者连接起来,把 Model 的数据变化反应到 View 上,同时也把 View 的数据变化同步到 Model 中,这同步工作是自动的,无需人为干涉。因此开发者只需要关注业务逻辑,不需要手动操作 DOM,也不需要关注数据状态的同步问题。

什么是运营商劫持

概念

运营商是指提供宽带服务的 ISP,比如移动、电信、联通;运营商劫持是指运营商为了卖广告或者其他经济利益,劫持了用户的访问,比较常见的有两种劫持方式:DNS 劫持HTTP劫持

DNS 劫持

DNS 劫持是通过攻击 DNS 服务器或者伪造 DNS 服务器,

  1. 将用户想要访问的目标网站的域名解析成错误的 IP 地址,导致用户无法访问目标地址,错误的 IP 地址可能会将用户导航到导航纠错页,而该页面上有广告。
  2. 直接将用户导航到指定的网站页面,可能是恶意网站或者广告页

DNS 劫持常见于使用自动的 DNS 地址,所以尽量不要使用运营商默认的 DNS 地址。

HTTP劫持

在 HTTP 劫持中,DNS 解析没有问题,但在用户和网站进行交互通信的过程中,运营商劫持了用户的请求,在服务器响应之前就给用户返回了信息,通常是弹窗广告之类。

什么是 XSS

文章看完了,之后有空再把拓展和文献也看了吧

概念

全称是 Cross-Site Scripting(跨站脚本攻击),是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户浏览器中运行,从而获取用户的敏感信息如 Cookie 和 SessionID 等,或者利用这些信息冒充用户向网站发起攻击者定义的请求。

XSS 的本质是:恶意代码未经过滤,和网站正常的代码混在一起,浏览器无法分辨哪些是可信脚本,哪些是恶意脚本,导致恶意脚本被执行。

攻击来源

在处理输入时,以下内容都不信:

  • 来自用户的 UGC 信息
  • 来自第三方的链接
  • URL 参数
  • POST 参数
  • Referer (可能来自不可信的来源)
  • Cookie (可能来自其他子域注入)

XSS 分类

  • 存储型:会被保存到数据库
  • 反射型:通过 url 参数直接注入
  • DOM型:取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞

什么是词法作用域

作用域是定义变量的一块区域,它规定了变量的访问规则,也就是当前执行的代码能够访问哪些变量。

JS 采用的词法作用域,也就是静态作用域,是指变量的访问规则在词法分析阶段就已经决定了,也就是说,我们写代码、定义函数的时候它们的作用域就已经确定了,函数的作用域取决于它定义的位置,而与它调用的位置无关。

动态作用域

与之相对的是动态作用域,是指函数的作用域要在函数调用时才能确定。

箭头函数与普通函数有什么不同?

  • 箭头函数的 this 绑定的是它外层第一个非箭头函数的 this

  • 无论是否严格模式,箭头函数都不能有同名参数,普通函数在非严格模式下定义重名参数不会报错,而是后定义的覆盖先定义的。

  • 箭头函数没有自己的 arguments 绑定,但是它可以获取到外层第一个非箭头函数的 arguments 对象。

  • 箭头函数不可以作为构造函数被调用,因为箭头函数本身就是为了处理 this 动态性的问题,而 new 操作会修改 this 的指向,两者相互矛盾了。

  • 因为箭头函数不能作为构造函数,所以它没有 prototype 属性,内部也没有绑定 new.target

说说TCP和UDP的区别

首先它们的基本区别是:TCP 是一个面向连接的、可靠的、基于字节流的传输层协议,而 UDP 是一个面向无连接的传输层协议。

和 UDP 相比,TCP 有三个核心的特性:

  • 面向连接:也就是说在客户端和服务器互相通信之前,TCP 需要通过 3 次握手来建立连接,而 UDP 并没有相应的建立连接的过程。

  • 可靠性:可靠性体现在两个方面,有状态和可控制。有状态是指 TCP 会精准记录哪些数据被发送了、哪些数据被接收了、哪些数据没有被接收,而且会保证数据有序到达。可控制指的是,在意识到丢包或者在网络环境不佳的情况下,TCP 会相应地调整自己的行为,重新发送数据包或者控制发送速度。

  • 基于字节流:TCP 为了维护状态,将 IP 包变成了字节流,而 UDP 只是继承了 IP层的特性,所以数据传输是基于数据报的。

说说 TCP 四次挥手的过程

第一次是客户端准备断开连接的时候,向服务器发送 FIN,同时客户端进入“半关闭”状态,不能再向服务器发送数据,但仍然可以接收数据;

第二次是服务器收到 FIN,返回 ACK 进行确认,接着,服务器会把还没有发送的数据继续发送完;

第三次是服务器把剩下的数据发送完成后,向客户端发送 FIN;

第四次是客户端收到 FIN 后,发送 ACK,然后等待 2 MSL(报文最大生存时间) 后,如果没有收到服务器要求重发报文的 FIN,就断开连接,否则就重发 ACK。

为什么要等待 2 MSL

  • 1 个 MSL 用来确认客户端发送的 ACK 能够到达服务器。
  • 1 个 MSL 用来确认服务器在没有收到 ACK 情况下发送的要求重发报文的 FIN 能够到达客户端。

为什么是四次挥手而不是三次
服务器在接收到客户端请求断开连接的 FIN 后,会立刻返回一个 ACK 进行确认,这就是多出来的一次挥手。如果服务器没有立刻返回 ACK,而是等把所有数据发送完之后再同时返回 ACK + FIN,那在服务器返回之前的这段时间延迟可能会让客户端误以为服务器没有接收到它发的 FIN,从而会不断地重发 FIN。

说说模块化

因为前端项目一直在变复杂,JS 代码量也越变越大,必须要做拆分。但如果只是简单地把一个 JS 文件拆成几个文件,会有一些问题:

  1. <script> 标签的引入顺序要手动控制
  2. 需要加载的 JS 文件过多可能会导致页面加载速度变慢
  3. 污染了命名空间,虽然是拆成了几个文件,但运行时它们都是在同一个作用域中。

模块化可以解决上面的问题。

执行上下文和执行上下文栈

执行上下文栈(Execution Context Stack, ECS)是 JS 引擎用来管理执行上下文的,而执行上下文就是在执行一段代码前要进行的一些准备工作。

在 JS 中,可执行代码分为 3 种:全局代码、函数代码、eval 代码。JS 引擎碰到一段可执行代码时,会先创建一个执行上下文并压入执行上下文栈,然后开始执行代码,等到这段代码执行完毕之后,再把这个执行上下文弹出。

所以,在运行一个应用程序之前,JS 引擎会先创建一个全局上下文压入执行上下文栈中,在程序运行期间,全局上下文一直存在栈底,直到程序运行结束。

webpack 中的 hash、chunkhash、contenthash 区别

hash 一般是结合 CDN 缓存来使用的,文件内容改变会导致生成文件名中的 hash 值改变,也就是对应的 HTML 引用的 URL 地址会改变,这样就能触发 CDN 服务器从源服务器上拉取新的资源,更新缓存。

不过这几种 hash 计算有以下区别:

  1. hash: 跟整个项目的构建有关,只要项目中有文件更改,hash 值就会改变,在项目构建中全部文件都用同一个 hash 值

  2. chunkhash: 第一个 hash 计算方式根本就达不到缓存的效果,所以我们需要换一种。 chunkhash 是根据不同的入口文件(entry)进行依赖文件解析、构建对应的 chunk、生成对应的 hash 值。所以我们可以把公共库和程序的入口文件分开,各自打包构建,采用 chunkhash 方式生成不同的 hash 值,这样只要我们不改动公共库的代码,它们的 hash 值就不会变。

  3. contenthash: 即使是使用 chunkhash 的方式,按入口文件分开生成了 hash,但在同一个入口中,如果一个模块改变了,跟它有依赖关系的模块也会受到影响。这些模块即使没有发生改变,但还是要重复构建,生成新的 hash 值。这时,我们可以使用 extra-text-webpack-plugin 里面的 contenthash 值,来保证只要某个模块的内容不变,它所处的模块中其他文件的变化不会导致它重复构建。

SameSite Cookie

一个 cookie 除了 key=value 对以外,还有一系列可选属性可以设置,这些属性用来控制 cookie 的使用场景,比如 Max-Age 指定 cookie 的过期时间,Secure 指定 cookie 只能用于 https 请求。服务器通过 Set-Cookie 响应头部在浏览器中设置 cookie。

Set-Cookie: promo_shown=1; Max-Age=2600000; Secure

曾经的 cookie

浏览器在发送请求时,会带上同域名下设置的所有 cookie,不管是谁发起的请求,这会导致两个问题:

  1. 可能会导致性能问题,如果一个网站的 cookie 设置过多,可能会延长请求发送的时间。要避免这个问题,需要合理地设置 cookie,比如设置合适的过期时间,不要让 cookie 的存活时间不必要的长。

  2. 可能会导致安全问题。假设你在浏览器中打开了 A.com 并登录,登录成功后 A.com 在你的浏览器中设置了一个 cookie sessionid 来保存登陆状态,紧接着你打开了 B.com,B.com 上有一张图片 A.com/img.png,于是浏览器发送请求去获取这张图片,由于域名相同,这个请求会带上 A.com 中设置的 sessionid 这个 cookie,这就是 CSRF 攻击。

第三方请求携带 cookie 这个行为也不一定是不好的。比如你在网站 A 中看到了一个 B 站的嵌入视频,你点了“稍后再看”,如果此时你在另一个标签页登录了 B 站,你点击“稍后再看”按钮向 B 站发起的这个请求就会带上 B 站登录状态的 cookie,网站 A 也就不用再要求你先登录 B 站了。

SameSite cookie

SameSite 属性出现后,我们就可以通过它来控制 cookie 是否可以被第三方(跨站)请求携带了,设置方式如下:

Set-Cookie: promo_shown=1; SameSite=Strict

可以设置的值:

  1. Strict:表示跨站网站发起的请求不能携带这个 cookie
  2. Lax
  3. None:跟以前一样,本站和跨站的请求都会带上这个 cookie

如果不设置这个属性,以前的默认行为是 SameSite=None,现在:

  • 不指定 SameSite 属性的 cookie 会被默认设置 SameSite=Lax
  • 设置了 SameSite=None 的 cookie 还必须设置 Secure 属性

chrome 80 已经实现了这两个默认行为,其他现代浏览器也在实现中。

实际上显式设置 SameSite=Lax 和不设置 SameSite 属性还是有轻微不同的。learn more

warning: SameSite=None 属性是后来加的,有些浏览器版本可能会不支持。

package-lock.json 有什么用

简单地说,就是锁定安装时依赖包的版本号,保存在 git 中可以保证其他人在 npm install 的时候下载的依赖包版本号一致。这个文件是在 npm install 的时候生成一个文件用来记录当前状态下安装的各个依赖包的来源和版本号。

VUE 的双向绑定原理是什么

VUE 采用的是 数据劫持 + 发布-订阅模式 这种方式,通过 Object.defineProperty() (VUE3 是通过 Proxy) 来劫持 data 各个属性的 settergetter,在 getter 中进行依赖函数收集(订阅),在 setter 中,也就是数据变动时,触发订阅者的监听回调。

具体步骤

  1. Observer 对 data 中的属性进行递归遍历,给它们加上 settergetter
  2. Compile 解析模板指令,将模板中的变量替换成数据,初始化渲染页面视图,将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据发生变动就更新视图。
  3. Watcher 是 Observer 和 Compile 之间通信的桥梁,主要做了:
    • 在自身实例化时往属性订阅器 (dep) 里添加自己
    • 自身必须有一个 update() 方法
    • 等属性变动 dep.notice() 通知时,能调用自身的 update() 方法,触发 Compile 中绑定的回调
  4. MVVM 作为数据绑定的入口,整合 Observer、Compile 和 Watcher 三者,通过 Observer 来监听 Model 数据变化,通过 Compile 来解析编译模板指令,最终利用 Watcher 搭起 Observer 和 Compile 之间的通信桥梁,达到 数据变化 -> 视图更新视图交互变化(input) -> 数据 Model 变更 的双向绑定效果

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.