字节跳动 ---- (一面)

第一题:Array中,使用reduce实现map
第一步:我们应该利用Array原生对象得prototype在原生对象Array重写map

Array.prototype.map = callBack

第二步:我们要开始写callBack回调函数

 const callBack = () => {
  console.log('this', this)
 }
 Array.prototype.map = callBack
 console.log([1, 2, 3].map(item => item * 2))

这样我们发现我们并没有通过this获取到我们的实例对象数组[1, 2, 3],这是因为箭头函数没有this这个概念,其内部this指向的是其父类this,所以上述thiswindow

OK,那我们将callBack改成function定义,如下

 function callBack() {
  console.log('this', this) // [1, 2, 3]
 }
 Array.prototype.map = callBack
 console.log([1, 2, 3].map(item => item * 2))

第三步:分析原生Array.prototype.map函数和Array.prototype.reduce函数
mapmap函数用于遍历实例数组,返回值为新数组,内部元素为callBack回调函数每次执行所返回结果值,若没有返回值,则数组元素为undefined

reducereduce函数用于遍历累加【累加逻辑写在callBack中】数组,返回值为最后一次callBack回调函数返回值。值得注意的是,关于reduce函数的callBack中的参数,及遍历次数。

 /*
 * pre: 累加器,若不自定义赋值初始值,则会为数组第一个元素,且.reduce方法会从index = 1开始遍历,也就是遍历arr.legth - 1 遍
 * item:callBack遍历当前的数组元素,若pre没有自定义设置初始值,则开始值为arr[1],.reduce方法会从index = 1开始遍历
 * index:callBack遍历当前的数组元素索引,若pre没有自定义设置初始值,则开始值为1,.reduce方法会从index = 1开始遍历
 */
[1, 2, 3].reduce((pre, item, index) => {
 pre = pre + item
 return pre
})

 /*
 * initPre: 外部pre自定义初始值,可以为对象,数组,基本类型值,且.reduce方法会从index = 0开始遍历,也就是遍历arr.legth遍
 * pre: 累加器,初始值为initPre
 * item:callBack遍历当前的数组元素,开始值为arr[0],.reduce方法会从index = 0开始遍历
 * index:callBack遍历当前的数组元素索引,开始值为0,.reduce方法会从index = 0开始遍历
 */
[1, 2, 3].reduce((pre, item, index) => {
 pre = pre + item
 return pre
}, initPre)

第四步:利用reduce函数中的循环代替map,用reduce中的累加逻辑实现map函数逻辑

 Array.prototype.map = function (cb) {
  return this.reduce((pre, item, index) => {
   pre.push(cb(item, index))
   return pre
  }, [])
 }
 // 结束了,哈哈哈

第二题:前端安全问题及预防
1、XSS(跨站脚本)
XSS,即为(Cross Site Scripting),因为避免与CSS混淆,就称为XSS。中文名称为跨站脚本,是发生在目标浏览器层面上,是在渲染DOM中发生了没有预期JS执行了相关操作,这就是XSS攻击。关于XSS攻击总的来说是有三大类型,反射型、存储型、DOM自身缺陷型。

反射型
特点
反射型XSS攻击,也称非持久性XSS攻击。简单来说就是通过前台发送一个包含恶意代码字段的请求,后台服务器响应,返回数据中包含这段恶义代码,此时浏览器就会执行这段JS代码,XSS攻击也就发生

攻击手法:
通过登录或其他操作发送请求,传入非法字段,比如传入name字段'<srcipt>alter('XSS攻击')</script>',若此请求返回结果包含字段name,则在获取用户name字段成功后就引入了我们植入的'<srcipt>alter('XSS攻击')</script>'这段JS代码,从而发生XSS攻击。

存储型
特点
存储型XSS攻击,也称持久性XSS攻击。简单来说就是通过前台发送一个包含恶意代码字段的请求,后台服务器响应并存储在相关数据库中,等到其他接口需要获取这个包含恶意代码字段并成功请求时,此时浏览器就会执行这段JS代码,XSS攻击也就发生。与反射型不同的是,它是将恶意代码植入到对方数据库中,也就意味着只需要一次植入恶意代码的操作即可。

攻击手法:
通过注册或其他操作发送请求,传入非法字段,比如传入name字段'<srcipt>alter('XSS攻击')</script>'存储在对方的数据库用户表。若之后其他操作所发送的请求,返回结果包含字段name,则在获取用户name字段成功后就引入了我们植入的'<srcipt>alter('XSS攻击')</script>'这段JS代码,从而发生XSS攻击。

DOM自身缺陷型
特点
DOM XSS代码的攻击发生的可能在于我们编写JS代码造成的。例如我们知道eval语句有一个作用是将一段字符串转换为真正的JS语句,因此在JS中使用eval很危险的事情,容易造成XSS攻击

攻击手法:
若用户知道我们代码结构中eval语句中值的传入源传入方式,用户则可以通过前台的某些输入操作,将恶意代码'<srcipt>alter('XSS攻击')</script>'植入到我们写的eval语句中,从而发生XSS攻击。

预防手段
前台对接口敏感参数及DOM敏感元素过滤或编码化比如(<script>等标签);
前台对用户ui界面输入值进行校验编码,防止用户输入恶意代码段;
后台对接口敏感参数过滤或编码化比如(<script>等标签);

千言万语一句话:对于XSS攻击,简单来说就是病从口入,口包括请求、用户与服务器交互参数等。
防护手段第一条:对于我们的口(前台),要学会拒绝或改造不良食品;对于我们的胃(后台),要学会对垃圾食物的排除或改造。

2、跨站请求伪造及防护
特点
借助用户已登录存储的 Cookie,从而利用浏览器会为之后的每个请求(用户已登陆网站所发请求)自动在请求头部添加 Cookie 这一特性,在同一浏览器的其他网站伪造用户发送相关请求,实现某些操作(crud啊)。

简单来说
用户用账号和密码打开了庄园大门,并给大门上的 Cookie 锁记录了行为识别认证。从此之后只要是用户拥有的行为方式(请求url),Cookie 锁就自动识别并认证通过。因此坏人们就可以在其他地方模仿用户拥有的某些行为方式(在同一浏览器上别的网站发送请求url)从而做些坏事(crud)

防护手段
增加 Token 令牌,因为 Token 是一个随机数生成,因此黑客也很难猜到。其次,Token 浏览器并不会自动添加到获取 Token 之后的每一个请求头中,这也保证了黑客无法利用浏览器的相关特性。

简单来说
用户用账号和密码打开了庄园大门,并给大门上的 Cookie 锁记录了行为识别认证并获取到了大门上的另外一把锁 Token 的钥匙。从此之后只要是用户拥有的行为方式(请求url),Cookie 锁就自动识别,但是这并不能认证通过,因为 Token 锁是需要每次手动的开启(手动给请求头添加自定义字段 Token )。因此即使坏人们可以在其他地方模仿用户拥有的某些行为方式(在同一浏览器上别的网站发送请求url)但是由于没有 Token 锁的钥匙,从而也做不了坏事(crud)

第三题:Promise内部同步
我们知道 Promise 是用来处理异步操作的,但是其参数回调函数内的的同步代码是怎么执行的呢?
1、Promise本身只是个容器,没有什么异步之说
2、其内部参数函数也是一个同步函数,只是内部可以进行相应的异步操作放在其中
3、其内部参数函数如果存在错误,并且没有显示调用catch回调函数,会内部隐式通过try…catch捕捉并将错误传给reject回调函数。且因为reject回调函数是个异步函数,处于微任务当中,因此不会中断 Promise 对象外部接下来的同步代码,但是待同步代码执行完毕后最终还是会报错。
4、因为其内部参数函数如果存在错误,会内部隐式通过try…catch捕捉并将错误传给reject回调函数。因此Promise参数函数之后代码程序会被错误中断,因为Promise已经隐式调用了reject函数,改变了Promise状态,终止Promise内部函数继续执行。

第四题:http 缓存
1、为什么会出现 http 缓存?
当客户端向服务端请求一个 A文件时。假设客户端发起请求时,请求无请求实体,只有请求头时,体积为 1 KB;服务端返回请求时,响应主体大小设 10 KB,响应头大小为 1 KB。这样一个完整请求到响应过程所消耗流量为 12 KB,倘若客户端又发起一次请求 A文件时,但是服务端 A文件实则没有任何变化,结果是则又需要耗费 12 KB流量传输,且占用服务器资源。为了解决这种不必要的资源消耗,则就出现了 http缓存。

2、http缓存是什么,缓存在哪里
http缓存是将客户端第一次向服务端请求获得的请求资源进行缓存,避免多次无必要请求。资源将会被缓存在 memory cache(内存)和 disk cache(磁盘)中,至于什么文件会存储在什么缓存中,没有清晰的定义。

3、资源文件怎么缓存的?
第一阶段(强缓存) Expires
最开始人们利用的是响应请求头中的字段 Expires。当客户端第一次请求获取服务器资源时,响应头部带有 Expires字段(值为一个GMT 格式的时间字符串)时,则表明服务器告知客户端在这个时间之前不需要再向服务器发送请求获取资源,直接从缓存了上次请求所获资源的 cache 中获取。

优点:一段时间内不需要重复向服务器发送请求获取资源;加快了客户端加载网页的速度

缺点:机械重复化请求,造成无法及时获取服务端最新资源以及重复获取相同资源;因为Expires值是一个绝对时间点,当客户端刻意更改本地时间或与服务端存在时间偏差时,会造成缓存命中机制混乱

第二阶段(强缓存) Cache-Control
为了解决Expires字段所存在的当客户端刻意更改本地时间或与服务端存在时间偏差时,会造成缓存命中机制混乱的缺点。人们开始使用响应请求头中的字段 Cache-Control来解决,因此当Expires和Cache-Control同时存在时,Cache-Control优先级高于Expires。关于Cache-Control字段值,有以下这么几个常见值:

no-cache:禁止使用强缓存,但是可以使用协商缓存。
no-store:禁止使用缓存(强缓存和协商缓存)。
max-age=number:number数量级为秒,表示在某个相对时间段内不需要再次向服务器发起请求,直接从缓存中获取资源。例如:max-age=3600 表示从获得请求资源后 60分钟内,不需要再向服务器发送请求,直接从缓存中获取。

优点:一段时间内不需要重复向服务器发送请求获取资源;因为是一个相对时间段,当客户端刻意更改本地时间或与服务端存在时间偏差时,也不会造成缓存命中机制混乱;加快了客户端加载网页的速度

缺点:机械重复化请求,造成无法及时获取服务端最新资源以及重复获取相同资源

第三阶段(协商缓存) Last-Modify/If-Modify-Since
关于协商缓存,它是对强缓存机制缺点的补充。当服务器给客户端的有效时间过期后,则会使用协商缓存。最初阶段的协商缓存是利用了获取资源的响应请求头部字段 Last-Modify (所请求资源在服务器最新的一次修改记录时间)和后面当服务器给客户端的有效时间过期后,向服务器发送资源请求头部中的 If-Modify-Since 构成,且 If-Modify-Since 值就是获取资源的响应请求头部字段 Last-Modify值。当服务端发现客户端传来的 If-Modify-Since值与所请求资源最新修改记录时间是一致的,则不返回响应的主体,状态码为304 Not Modified【没有改变】 (注意:虽然状态码为 3XX 类型,但是与资源重定向没有任何关系)。

优点:弥补了当强缓存有效时间过期,但资源可能没有被修改,所造成的重复获取资源所带来的流量及服务器资源的浪费;加快了客户端加载网页的速度

缺点:客户端每次都要发送资源请求;当请求资源在服务器只是被修改但是内容部分却没有变化所造成的资源的重复获取(例如:对服务器一个文件进行添加一个空格,再删除一个空格,此时文件最新的修改记录已被刷新,但是内部内容确实和之前修改记录之前的文件内容没有出入);

第四阶段(协商缓存) Etag/If-None-Match
第二阶段的协商缓存是利用了获取资源的响应请求头部字段 Etag (所请求资源内容的唯一标志)和后面当服务器给客户端的有效时间过期后,向服务器发送资源请求头部中的 If-None-Match 构成,且 If-None-Match 值就是获取资源的响应请求头部字段 Etag 值。当服务端发现客户端传来的 If-None-Match值与所请求资源内容的唯一标志是一致的,则表明所请求资源内容无变化,就不返回响应的主体,状态码为304 Not Modified【没有改变】 (注意:虽然状态码为 3XX 类型,但是与资源重定向没有任何关系)。关于 Etag/If-None-Match 是为了解决 Last-Modify/If-Modify-Since 存在的当请求资源在服务器只是被修改但是内容部分却没有变化所造成的资源的重复获取的缺点,因此当 Etag/If-None-Match 和 Last-Modify/If-Modify-Since 同时存在时,Etag/If-None-Match优先级高于 Last-Modify/If-Modify-Since。(注意: Etag值是所请求资源内容的唯一标志,也就是当你所请求资源内部的内容发生改变时,Etag 才会变化)

优点:弥补了当强缓存有效时间过期,请求资源在服务器只是被修改但是内容部分却没有变化所造成的资源的重复获取所带来的流量及服务器资源的浪费;加快了客户端加载网页的速度

缺点:客户端每次都要发送资源请求

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值