Skip to content

Latest commit

 

History

History
271 lines (182 loc) · 17.5 KB

鹅肠前端一面面经.md

File metadata and controls

271 lines (182 loc) · 17.5 KB

https://www.nowcoder.com/discuss/69339?type=2&order=0&pos=22&page=1

  • 腾讯

    • ​ 3.16 一面 (45分钟)

    • ​ 问题

      • ​ 描述下原型链

      • ​ js作用域

      • ​ 闭包

      • ​ 垃圾回收:Garbage Collecation

        • http://blog.csdn.net/oliver_web/article/details/53957021
        • JS是有自动垃圾回收机制的,原理是垃圾收集器会周期性的找出不在继续使用的变量然后释放内存
        • 那么必须跟踪变量到底是不是会被继续使用:标记清除和引用计数
          • 标记清除(常用)
            • 在函数中声明一个变量,就将这个变量标记为进入环境。函数执行完毕,变量就被标记为离开环境,被回收
          • 引用计数,跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1
            • 但是循环引用就会导致内存泄漏
            • 手动接触引用计数,设置为null
        • 垃圾回收策咯
          • JS引擎的基础GC测出咯,就是标记清除,遍历所有可访问的对象,回收已经不可访问的对象。
          • 但是GC时会停止所有响应,对JS游戏动画等连贯性要求高的应用非常麻烦
          • 优化策咯
            • 分代回收 generation GC
              • 目的是通过区分“临时”与“持久”对象;多回收“临时对象”区(young generation),少回收“持久对象”区(tenured generation),减少每次需遍历的对象,从而减少每次GC的耗时
            • 增量GC
              • 这个方案的思想很简单,就是“每次处理一点,下次再处理一点,如此类推”。如图
      • 如何读取对象属性不在原型链上找

        • 比如说myObject.foo = "bar",这里分为以下的几种情况: 如果myObject对象中包含名为foo的普通数据访问属性,那么修改已有的属性值; 如果foo不存在于myObject对象中,它的原型链就会被遍历,如果原型链中没有foo属性,那么foo属性被添加到myObject对象里; 如果foo属性存在于原型链中,那么又会分为三种情况: a:原型链中存在foo属性,但没有被标记为只读(writable:true),那么就会在myObject中添加一个foo属性,屏蔽原型链中的属性; b:原型链中存在foo属性,但被标记为只读(writable:false),那么无法修改已有属性或者在myObject上创建屏蔽属性。代码如果运行在严格模式下,代码会报错。否则,这条赋值语句会被忽略。总之,就是不发生屏蔽; c:原型链中存在foo属性,但它是一个setter(自己定义的赋值函数)。这种情况下,foo不会被添加到myObject中,也不会重新定义setter。

        • 当检查对象上某个属性是否存在时,hasOwnProperty 是唯一可用的方法。同时在使用 for in loop 遍历对象时,推荐总是使用 hasOwnProperty 方法,这将会避免原型对象扩展带来的干扰,我们来看一下例子:

          for(var i in foo) {
              if (foo.hasOwnProperty(i)) {
                  console.log(i);
              }
          }
          

      • ​ cookie一些属性

        • 在chrome控制台中的resources选项卡中可以看到cookie的信息。

          一个域名下面可能存在着很多个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

      • ​ 浏览器缓存 :

        • 协议层的缓存

          • 强制缓存

            • http1.0的时候是Expires缓存,字段表示缓存到期时间,是有效时间+当时服务器时间,设置在header中返回给服务器,时间是绝对时间

              • 缺点:由于是绝对时间,用户可能会将客户端本地的时间进行修改,而导致浏览器判断缓存失效,重新请求该资源,同时,还导致客户端与服务端的时间不一致,致使缓存失效。
              • http1.1的时候增加了一个字段Cache-Control,该字段表示资源缓存的最大有效时间,在该时间内,客户端不需要向服务器发送请求,它与expires的区别就在于cache-control是相对时间
            • Cache-Control: max-age=2592000
              
              • max-age:即最大有效时间,在上面的例子中我们可以看到
              • no-cache:表示没有缓存,即告诉浏览器该资源并没有设置缓存
              • s-maxage:同max-age,但是仅用于共享缓存,如CDN缓存
              • public:多用户共享缓存,默认设置
              • private:不能够多用户共享,HTTP认证之后,字段会自动转换成private
              • 优点:总结一下,自从http1.1开始,Expires逐渐被Cache-Control取代。Cache-Control是一个相对时间,即使客户端时间发生改变,相对时间也不会随之改变,这样可以保持服务器和客户端的时间一致性。而且Cache-Control的可配置性比较强大。
          • 对比缓存

            • Last-Modified:服务器告知客户端,资源最后一次被修改的时间,例如
            Last-Modified: Thu, 10 Nov 2015 08:45:11 GMT
            //这段信息在HTTP的response里
            
            • ​ If-Modified-Since:再次请求时,请求头中带有该字段,服务器会将If-Modified-Since(在http请求头里)的值与Last-Modified字段进行对比,如果相等,则表示未修改,响应304;反之,则表示修改了,响应200状态码,返回数据。
              • 这个字段可以和Cache-Control配合使用。
              • 缺点:
                • 如果资源更新的速度是秒以下单位,那么该缓存是不能被使用的,因为它的时间单位最低是秒。
                • 如果文件是通过服务器动态生成的,那么该方法的更新时间永远是生成的时间,尽管文件可能没有变化,所以起不到缓存的作用。
            • Etag
              • Etag存储的是文件的特殊标识(一般都是hash生成的),服务器存储着文件的Etag字段,可以在与每次客户端传送If-no-match的字段进行比较,如果相等,则表示未修改,响应304;反之,则表示已修改,响应200状态码,返回数据。
        • 应用层缓存

          • localStorage

            • localStorage突破了cookie 4K限制,永久储存在你的计算机上

            • 目前所有的浏览器中都会把localStorage的值类型限定为string类型,这个在对我们日常比较常见的JSON对象类型需要一些转换

            • localStorage本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡

            • 超过5M,就存不了,就这么写

              (function(){
                var safeLocalStorage = function(key, value) {
                  try{
                    localStorage.setItem(key,value);
                  }catch(oException){
                    if(oException.name == 'QuotaExceededError'){
                        console.log('已经超出本地存储限定大小!');
                        // 可进行超出限定大小之后的操作,如下面可以先清除记录,再次保存
                        localStorage.clear();
                        localStorage.setItem(key,value);
                    }
                  }
                }
                this.safeLocalStorage = safeLocalStorage;
              })();
              

          • sessionStorage

            • sessionstorage只要浏览器关闭,存储就消失
            • sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
      • ​ http和https协议握手过程、状态码

        • 三次握手:

          • TCP握手:
            • SYN(synchronous)是TCP/IP建立连接时使用的握手信号。在标志位上,在客户机和服务器之间建立正常的TCP网络连接时,客户机首先发出一个SYN消息,服务器使用SYN+ACK应答表示接收到了这个消息,最后客户机再以ACK消息响应。这样在客户机和服务器之间才能建立起可靠的TCP连接
            • seq是序列号,第一个seq是客户端随机生成的;
            • 确认号ack是4个字节,32个位。期待收到对方下一个报文段的第一个数据字节的序号;序列号表示报文段携带数据的第一个字节的编号;而确认号指的是期望接收到下一个字节的编号;因此当前报文段最后一个字节的编号+1即为确认号。 也就是收到的seq+1
            • 确认ACK,占1位,当ACK=1的时候,确认号Ack才有效,否则无效
            • 第一次握手
            • 主机A向主机B发送TCP连接请求数据包(syn=1),随机产生一个初始序列号seq = j。(其中报文中同步标志位SYN=1,ACK=0,表示这是一个TCP连接请求数据报文;序号seq=x,表明传输数据时的第一个数据字节的序号是x);
            • 第二次握手
              • 服务器收到syn包,必须确认客户的SYN,将标志位的SYN 和 ACK 都设置为1,ack = j+1,同时自己也发送一个SYN包(seq 随机出一个 k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
            • 第三次握手
              • 客户端收到服务器的SYN+ACK包,检查ack是不是j+1 ACK是否为1,如果是,则将标志位的ACK设置为1,向服务器发送确认包ACK(ack=k+1),此包发送完毕,Server检查ack是否为K+1,ACK是否为1,如果是,客户端和服务器进入ESTABLISHED状态,完成三次握手.
          • 第三次握手,主机A发送一次确认是为了防止:如果客户端迟迟没有收到服务器返回的确认报文,这时他会放弃连接,重新启动一条连接请求;但问题是:服务器不知客户端没收到,所以他会收到两个连接请求,白白浪费了一条连接开销。
        • TCP释放的四次握手

          • TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭

          • 假设主机A为客户端,主机B为服务器,其释放TCP连接的过程如下:

            ​ 1) 关闭客户端到服务器的连接:首先客户端A发送一个FIN,用来关闭客户到服务器的数据传送,然后等待服务器的确认。其中终止标志位FIN=1,序列号seq=u

              2) 服务器收到这个FIN,它发回一个ACK,确认号ack为收到的序号加1。  3) 关闭服务器到客户端的连接:也是发送一个FIN给客户端。   4) 客户段收到FIN后,并发回一个ACK报文确认,并将确认序号seq设置为收到序号加1。

          • 第一次挥手

            • Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态
          • 第二次挥手

            • Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态
          • 第三次挥手

            • Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态
          • 第四次挥手

            • Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手
          • 为什么是四次挥手

            • 这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。
            • 因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手
      • 同源策略、跨域解决办法

        • 同源策咯

          • 源(origin)就是协议、域名和端口号。

          • 同源:协议、域名和端口号均相同

          • 同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以a.com下的js脚本采用ajax读取b.com里面的文件数据是会报错的。

          • 不受同源策略限制的: 1、页面中的链接,重定向以及表单提交是不会受到同源策略限制的。 2、跨域资源的引入是可以的。但是js不能读写加载的内容。如嵌入到页面中的<script src="..."></script>,,,<iframe>等。

          • 跨域解决方法

            • 降域 document.domain,同源策略认为域和子域属于不同的域

              • 只能在父域名与子域名之间使用,且将 xxx.child1.a.com域名设置为a.com后,不能再设置成child1.a.com。
              • 存在安全性问题,当一个站点被攻击后,另一个站点会引起安全漏洞。
              • 这种方法只适用于 Cookie 和 iframe 窗口。
            • JSONP跨域:a.com/jsonp.html想得到b.com/main.js中的数据

            • CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。

              • 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。 刚才的例子中,在b.com里面添加响应头声明允许a.com的访问,代码: Access-Control-Allow-Origin: http://a.com 然后a.com就可以用ajax获取b.com里的数据了。

      • AJAX

        • 原生AJAX

          
          

      • ​ web安全有哪些。XSS CSRF产生原理、如何防范。具体转义哪些字符为什么

      • ​ 你觉得的自己优点和缺点

      • ​ 平时怎么学前端

    • ​ 二面(25分钟)//不知道算不算二面

      • ​ 讲项目和遇到的难点问了下一些相关
      • ​ imutable.js实现原理
      • ​ Promise解决了什么问题、如何使用ES5实现

    然后约了明天早上10点半在线写代码,祝题主好运不用那么凉2333