• 字节网上面经整理(100道面试题)一篇


    为了准备面试,看了很多字节面经,整理出来,方便复习,答案一部分是自己看完网上的知识理解的,一部分是网上摘过来的。
    1、let map={} 和newMap()的区别?
    考察的是字面量创建对象和构造函数创建对象的区别。
    字面量创建对象:1、代码量少易读。2、运行速度更快,在解析的时候会被优化,即不需要作用域解析,解析器需要顺着作用域链从当前作用域向上查找,如果在当前作用域找到了名为Object()的函数就执行,如果没找到,就继续顺着作用域链往上照,直到找到全局Object()构造函数为止。3、但是一次只可以创建一个对象,创建很多对象,会造成代码冗余度高。
    构造函数创建对象:把对象实例的创建过程委托给一个内置的函数,函数的传参会影响对象的创建。
    2、说说symbol。
    ①symbol是es6的新特性,它类似于唯一标识一个ID。②用typeof识别会返回Symbol,③用Symbol定义的变量,比较的结果为false。④如果对象里面的属性被定义为Symbol类型,则不能用Object.keys()和for in 遍历出来,因为该属性不在对象的自身属性名集合中。⑤用JSON.stringify()将对象转换成JSON字符串的时候,Symbol属性也会被排除在输出内容之外。⑥可以用Symbol来定义私有属性。⑦如果要获取以Symbol方式定义的对象属性,可以用object的API:Object.getOwnPropertySymbols()或者用新增的反射API:Reflect.ownKeys()

    3、说说js垃圾回收机制(网络答案)
    一般来说没有被引用的对象就是垃圾,就是要被清除。
    现在各大浏览器通常用采用的垃圾回收有两种方法:标记清除、引用计数。
    1、标记清除
    这是javascript中最常用的垃圾回收方式。当变量进入执行环境时,就标记这个变量为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到他们。当变量离开环境时,则将其标记为“离开环境”。
      垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记。然后,它会去掉环境中的变量以及被环境中的变量引用的标记。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后。垃圾收集器完成内存清除工作,销毁那些带标记的值,并回收他们所占用的内存空间。
    2、引用计数
    另一种不太常见的垃圾回收策略是引用计数。引用计数的含义是跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型赋值给该变量时,则这个值的引用次数就是1。相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数就减1。当这个引用次数变成0时,则说明没有办法再访问这个值了,因而就可以将其所占的内存空间给收回来。这样,垃圾收集器下次再运行时,它就会释放那些引用次数为0的值所占的内存。
    出自:链接:js垃圾回收机制
    4、循环对象的方法及区别
    1.使用for in。可以用来枚举对象的属性,也可以用来循环数组。但也会把原型上的方法名也遍历出来。遍历对象,是获取对应元素的序号,for…in是获取对象的key。
    2.使用for of。遍历对象,可以获取对应的元素,是遍历获取对象中的value。
    3.Object.keys().找到对象中所有key值的一个数组,,再forEach取得其value。
    5、判断数据类型的方法
    typeof 、instanceof 、constructor 、Object.prototype.toString.call
    6、transition和animation的区别,以及触发transition的条件
    transition是过渡属性,强调过渡,设置一个开始关键帧和一个结束关键帧。animation是动画属性,可以设置多个关键帧完成动画,设定好时间后自己执行,无需触发事件。触发transition的条件是触发一个事件,比如鼠标移动上去,焦点,点击等。
    7、js有哪些类数组,es5 es6有哪些方法可以将其转化为数组?
    arguments、NodeList、HTMLCollection.
    方法:Array.prototype.slice.call(),[].concat.apply([],arr)、Function.prototype.call.bind(Array.prototype.slice)、[].slice.call(arr)ES6类数组转化为数组 Array.from(arr)
    8、0.1+0.2 === 0.3吗?为什么?怎么才能得到想要的结果?
    不等于,在JavaScript中的二进制的浮点数0.1和0.2并不是十分精确,在他们相加的结果并非正好等于0.3,而是一个比较接近的数字 0.30000000000000004 ,所以条件判断结果为false。可以通过以下两种方法实现:
    1.ES6提供的Number.EPSILON方法

    Number.EPSILON=(function(){   //解决兼容性问题
            return Number.EPSILON?Number.EPSILON:Math.pow(2,-52);
          })();
    //上面是一个自调用函数,当JS文件刚加载到内存中,就会去判断并返回一个结果,相比if(!Number.EPSILON){
      //   Number.EPSILON=Math.pow(2,-52);
      //}这种代码更节约性能,也更美观。
    function numbersequal(a,b){ 
        return Math.abs(a-b)   }
    //接下来再判断   
        var a=0.1+0.2, b=0.3;
      console.log(numbersequal(a,b)); //这里就为true了
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    2、把计算数字 提升 10 的N次方 倍 再 除以 10的N次方。N>1.

    (0.1*1000+0.2*1000)/1000==0.3
    1
    9、重绘、重排。
    重排:当渲染树因为元素尺寸、布局、隐藏等改变而需要重建,这就称为重排(回流)。每个页面至少需要一次重排(回流),就是在页面第一次加载的时候。
    重绘:当渲染树中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘。
    10、html文件解析过程。
    解析html文件,生成dom树,然后解析css生成Css树,然后dom树和Css树结合生成render树,然后给render树布局,然后渲染render树,然后交给电脑的GPU排版合成。
    11、flex布局的grow和shink是干嘛的?
    flex弹性布局,如果子元素宽度之和大于或者小于父元素宽度,空间就会存在剩余和不够,flex默认不换行,除非设置flex-wrap,那么这种情况下,有两个重要的属性,flex-grow和flex-shrink.
    当子元素宽度之和小于父元素宽度时,给子元素设置flex-grow,会将剩余的尺寸按照比例分配的子元素。
    当子元素宽度之和大于父元素宽度时,给子元素设置flex-shink,会将多出的尺寸按照比例(元素宽度占总宽度)从子元素中减去。
    12、什么是同源策略?为什么要提出这个?
    协议、域名、端口号一致,表示同源策略。设置同源策略的主要目的是为了安全,如果没有同源限制,在浏览器中的cookie等其他数据可以任意读取,不同域下的DOM任意操作,ajax任意请求其他网站的数据,包括隐私数据。
    13、说说浏览器渲染机制,为什么用虚拟DOM?直接操作DOM有什么弊端?
    解析html文件,生成dom树,然后解析css生成Css树,然后dom树和Css树结合生成render树,然后给render树布局,然后渲染render树,然后交给电脑的GPU排版合成。用虚拟DOM可以使页面的性能更好,减少重排与重绘。直接操作DOM会影响页面的性能,会导致页面的重排和重绘。
    14、说说类数组对象。
    类数组对象和数组一样具有length与index属性,但是它是一个Object。它是js提供的一种访问原始二进制数据的机制。
    15、如何判断一个变量是数组?
    instanceof Array.isArray() Object.prototype.toString.call()
    16、如何理解html语义化?
    语义化,其实就是用恰当的标签,去展示恰当的内容。通过使用恰当语义的标签,可以让页面具有良好的结构和含义。它更省代码,有利于搜索引擎,使页面有更清晰的代码结构,可读性高,互用性强。
    17、var、let、const的区别?
    var声明的变量会挂载到全局window上,存在变量提升,同一作用域下,var可以声明同名变量。
    let和const不存在变量提升,并且会形成块级作用域,同一作用域下,不可以声明同名变量。
    const声明的基本数据类型,不能进行再次更改,复杂的数据类型,如,对象,可以更改其属性。
    暂时性死区:如果使用let const,变量在未声明之前就访问会报错,因为let const不存在变量提升,而var可以。
    18、说说闭包,列举闭包的用处。
    要理解闭包,必须要知道js变量是有局部变量和全局变量,全局变量在函数内外都可以访问到,但是局部变量,在函数内可以访问,函数外就不可以访问了,如果我们必须要拿到函数f1内部的变量,我们可以在函数内部再定义一个函数f2,根据Js的作用域链,f2这个函数可以访问到f1的变量,但是f1访问不到f2的,这时,我们再返回f2,这样以来,我们在外部调用f1函数,就可以访问到其内部的变量了,这就形成了闭包。简单的说,闭包就是访问其他函数内部变量的函数,使用闭包会造成内存泄露,因为内部变量无法释放。我们可以用立即执行函数解决闭包问题。比如,我们要给页面上的li绑定点击事件,打印出顺序。

      //给每一个li添加一个绑定事件,输出他们的顺序。
            function test() {
                var li = document.querySelectorAll('li');
                //方法一:用let声明i,而不是var
                for (let i = 0; i < li.length; i++) {
                       li[i].addEventListener('click',function(){
                           console.log(i)
                       },false)
                       //方法二:用立即执行函数
                    // (function (j) {
                    //     li[j].addEventListener('click', function () {
                    //         console.log(j)
                    //     }, false)
                    // }, (i))

                }
            }
            test();

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19、在网址上输入URL后,浏览器的变化。
    首先会在浏览器缓存里查找,是否有记录,如果没有,则再本地的hosts里查找,如果没有则查找DNS服务器,得到服务器的ip地址后,浏览器会根据ip和相应的端口号构造一个http请求,并将这个http请求封装成TCP包,这个TCP包会经过四层传输到服务器,服务器拿到之后进行解析,返回一个html给浏览器,然后浏览器开始解析html文件,渲染页面。
    21、说说BFC。
    BFC:块级格式化上下文,它是指一个独立的块级渲染区域,只有Block-level Box 参与,该区域拥有一套渲染规则来约束块级盒子的布局,且与区域外部无关。通俗的讲就是父元素和子元素或者兄弟元素之间发生margin合并。触发BFC可以用:(1) position:absolute(2)display:inline-block(3)float:left/right(4)overflow:hidden
    22、为什么a标签之间会有空白?
    a标签是行级元素,行级元素和行块级元素都是文本类元素,带有inline的元素,文本类元素会受到文本分隔符的影响,只要有空格或者回车都会空一格。
    23、如何判断JS对象为空对象?
    1.将json对象转化为字符串,判断字符串是否为空。
    2.用for in遍历对象。
    3、用Object.getOwnPropertyNames
    4.用Object.keys()
    5.用jq的$.isEmptyObject()
    24、说说TreeShaking。
    Tree shaking指的就是当我引入一个模块的时候,我不引入这个模块的所有代码,我只引入我需要的代码,这就需要借助webpack里面自带的Tree Shaking这个功能,帮助我们实现。Tree Shaking只支持ES Module(import…) 不支持require…
    25、get与post的区别。
    如果没有任何前提,不使用任何规范,只考虑语法的理论上的http协议,则get和post几乎没有什么区别,只有名字不一样。如果是基于RFC规范,理论上,get和post具有相同得到语法,但具有不同的语义,get用来获取数据,post用于发送数据,实际上,有以下不同点:

    get请求参数有长度限制,而post没有。
    get请求的数据在url中是可见的,post请求不显示在url中。
    get请求后按后退或者刷新按钮没有影响,而post请求会被再次提交。
    get请求的数据可以收藏为标签,但是post不可以。
    get的历史参数会被保存在浏览器中,而post的不会。
    get的安全性较差,因为请求的数据在url中是可见的。
    get只允许ASCII,而post没有编码限制,允许发二进制的。
    get编码类型:application/x-www-form-url.post编码类型encodeapplication/x-www-form-urlencoded。
    26、Promise.then抛出的错误能否被catch捕获到?
    Promise.then在第一个函数里抛出错误,在第二个函数里捕获不到,在catch里可以捕获到。如果promise.then在第二个函数里抛出错误,catch捕获不到。

      const pro = new Promise((resolve,reject)=>{
                resolve('111');
            })
            pro.then(data=>{
                console.log(data);//111
            },err=>{
                console.log(err);
            }).then(function(){
                throw new Error('dhdhf');
            },function(err){
                console.log(err);//打印不出来
            }).catch(err=>{
                console.log(err);//打印出抛出的错误
            })

            pro.then(function(){
            },function(){
                throw new Error('error');
            }).catch(err=>{
                console.log(err);//打印不出来,
            })

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    27、说说Vue事件修饰符。
    .prevent:阻止默认行为。
    .stop:阻止事件冒泡
    .capture:事件捕获
    .self:只有点击当前元素的时候才会触发事件
    .once:只触发一次事件触发函数
    28、Vue自定义事件会冒泡吗?
    目前还没有。只能用递归组件,监听一次emit,再emit一次。
    29、vue事件是冒泡时触发还是捕获时触发?
    30、为什么会有Vuex这样的状态管理库?
    简单数据在组件中传值我们可以使用组件通信,当涉及到复杂大量的数据或者复杂组件的数据传值时我们就需要一个存数据的库,vuex就是处理组件间复杂数据的共享问题的。
    31、说说vue双向数据绑定的实现,vue3.x为什么用proxy实现?
    vue的双向数据绑定是由数据劫持结合发布-订阅者模式实现的,利用Object.definePropery()来劫持对象属性的setter和getter操作,在数据变动时做你想做的事情。vue中使用v-model实现,主要原理是绑定了DOM对象的value属性,当它初次绑定的时候,就会触发getter,watcher就会触发, watcher通知Vue生成新的VDOM树。再通过render函数进行渲染,生成真实DOM。Object.defineProperty的缺点:(1)在Vue中,Object.defineProperty无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实时响应。(2)Object.defineProperty只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。Vue里,是通过递归以及遍历data对象来实现对数据的监控的,如果属性值也是对象那么需要深度遍历,显然如果能劫持一个完整的对象,不管是对操作性还是性能都会有一个很大的提升。proxy的优点:

    可以劫持整个对象,并返回一个新对象
    有13种劫持操作。
    Proxy是 ES6 中新增的一个特性,翻译过来意思是"代理",用在这里表示由它来“代理”某些操作。 Proxy 让我们能够以简洁易懂的方式控制外部对对象的访问。其功能非常类似于设计模式中的代理模式。
    Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
    使用 Proxy 的核心优点是可以交由它来处理一些非核心逻辑(如:读取或设置对象的某些属性前记录日志;设置对象的某些属性值前,需要验证;某些属性的访问控制等)。 从而可以让对象只需关注于核心逻辑,达到关注点分离,降低对象复杂度等目的。

    vue3.x中用proxy实现双向数据绑定:

    observe(data) {
      const that = this;
      let handler = {
       get(target, property) {
          return target[property];
        },
        set(target, key, value) {
          let res = Reflect.set(target, key, value);
          that.subscribe[key].map(item => {
            item.update();
          });
          return res;
        }
      }
      this.$data = new Proxy(data, handler);


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    32、说说vue-router按需加载原理?为什么要按需加载?
    vue-router的懒加载是vue异步组件和webpack的【代码分块点】功能结合。

    const App = () => import('../component/Login.vue');
    1
    vue这种单页面应用,如果没有懒加载,在webpack打包后的文件将会非常大,使用vue-router的懒加载即按需加载,可以有效的分担首页加载所要承担的压力,减少首页加载用时。
    33、说说Vue组件通信?
    34、说说webpack工作流程以及基本配置。

    基本配置webpack.config.js

    var path = require('path');

    module.exports = {
      mode: 'development',
      entry: './foo.js',
      output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'foo.bundle.js'
      }
    };
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    35、说说前端工程化。
    可以使用模块化、组件化、规范化、自动化实现前端工程化。
    36、说说loader和plugin的区别。
    loader是一个转换器,操作的是文件,比如,将A文件编译为B文件。plugin是一个扩展器,它丰富了webpack本身,针对是loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,执行广泛的任务。
    37、说说跨域以及你知道的实现跨域的方法。
    当要请求的url的协议、域名、端口号其中任意一个与当前页面的url不一致的时候就是跨域。
    1、jsonp.其原理是动态添加script标签,创建回调函数,script标签没有跨域限制。
    2、设置document.domain解决无法读取非同源网页的 Cookie问题.
    3、跨文档通信 API:window.postMessage()
    4、CORS
    CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。
    1、普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
    2、带cookie跨域请求:前后端都需要进行设置
    【前端设置】根据xhr.withCredentials字段判断是否带有cookie
    原文链接:跨域
    38、说说XSS攻击,了解CSRF吗?

    39、说说CommonJS和ES6模块化。
    ES6模块化
    代表:Vue
    语法:
    导入:import xxx from、import {xxx} from
    导出:export、export default
    特点:
    this指向undefined
    编译时输出接口
    可以单独加载其中的某个接口(方法)
    静态分析,动态引用。输出的是值的引用
    CommonJS模块化
    代表:node.js
    语法:
    导入:require()
    导出:module.exports、exports
    特点:
    this 指向当前模块
    运行时加载。CommonJS脚本代码在require的时候,就会全部执行。一旦出现某个模板被“循环加载”,就只能输出已经执行的部分,还未执行的部分不会输出。
    加载的是整个模块,即将所有的接口全部加载进来。
    输出的是一个值的拷贝
    链接:https://www.jianshu.com/p/08ae4f9fa802
    完整的前端模块化看链接前端模块化详解(完整版)
    40、说说websocket与ajax.
    ajax是异步javascript和XML,websocket是html5的一种协议,实现了服务器和浏览器的全双工通信。ajax是短连接,数据发送完和接收完之后就会断开,websocket是长连接,在一个会话中一直保持。ajax请求回来的数据是用户自己看的,websocket请求回来的数据其他用户也可以看到。
    41、说说fetch和普通request的区别。
    fetch:

    是基于promsie实现的接口,避免了ajax出现的回调地狱。
    以数据流的形式返回数据,数据量大和传输文件有优势。
    具有cors的支持。
    Fetch API引入三个新的对象(也是构造函数):Headers, Request和Response。headers用于设置请求头还是比较方便的。
    fetch默认不携带cookie,需要进行配置。
    fetch只对网络请求报错,400 500错误都会被视为成功。
    普通请求(如axios):

    支持promsie API
    客户端支持防止CSRF
    42、说说vue的set原理。
    Vue.set数组实现的原理:其实Vue.set()对于数组的处理其实就是调用了splice方法.
    43、说说js的继承。
    es5的继承方法:

    传统的原型链继承
    构造函数继承。
    对象组合继承(相当于构造函数继承和原型链继承的组合)
    寄生组合继承。构造一个空类,使父元素的原型等于空类的原型。子元素的原型等于空类构造出来的实例对象。
    es6的继承方法:super extends

    44、说说TCP三次握手和TCP四次挥手。
    可以参考:TCP的三次握手与四次挥手理解及面试题(很全面)
    45、说说TCP是如何实现数据的可靠性传输的。TCP和UDP有什么区别?
    可以参考:TCP/IP是如何实现可靠传输的
    TCP和UDP区别
    46、说说http、https的区别。对称加密和非对称加密,http2.0和http1.0的区别?
    47、说说常见的状态码?301 302有什么区别?浏览器有什么变化?
    200:请求成功。
    301:资源(网页)被永久转移到其他url,
    302:资源(网页)被临时移动到其他url,
    400:客户端请求的语法错误,服务器无法理解
    401:请求要求用户的身份认证。
    402:保留,将来使用
    403:服务器理解客户端的请求,但拒绝执行此请求
    404:请求的资源不存在
    500:内部服务器出现错误
    502:作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效响应。

    301和302:一个是永久的,一个是临时的,302错误通常,浏览器遇到该响应,会将访问的地址加入到历史记录中,然后重新去请求新的地址。

    48、应用层有哪些协议?
    HTTP协议、FTP协议、SMTP协议(简单邮件传输协议)
    49、说说浏览器缓存机制,请求头,响应头。
    缓存分为强缓存和协商缓存,根据响应的header内容来决定。
    强缓存相关字段有expires,cache-control,如果cache-control和expires同时存在,则前者的优先级高于后者。
    协商缓存的相关字段有Last-Modified/If-Modified-Since 、Etag / If-None-Match
    深入理解浏览器的缓存机制
    http请求中请求头和响应头包含哪些内容
    50、说说前端性能优化。
    前端性能优化有七大手段:减少请求数量,减少资源大小,优化网络连接,优化资源加载,减少重绘重排,使用性能更好的API,构建优化。

      减少请求数量:通过减少重定向,使用缓存,不适用CSS@import,避免使用空的src和href等手段

      减少资源大小:通过压缩HTML,CSS, JS,图片,此外在安卓下可以使用webp格式的图片,它具有更优的图像数据压缩算法,能带来更小的图片体积,还可以开启gzip, gzip编码是以后总用来改进web应用程序性能的技术,

      优化网络连接:使用CDN,使用DNS预解析,并行连接,

      优化资源加载,通过优化资源加载位置和时机,使用资源预加载preload和资源预读取prefetch

      减少重绘回流,1:避免使用层级较深的CSS选择器,以提高CSS渲染效率2、避免使用CSS表达式,3、给元素适当的定义高度或最小高度,否则

     

  • 相关阅读:
    javacc之路0--- 安装与使用
    CTreeCtrl动态创建从字符串创建多个根节点
    【Verilog实战】SPI协议底层硬件接口设计和功能验证(附源码)
    Babel AST代码转换、生成
    Nginx禁用TLS 1.0和TLS 1.1
    产品如何通过网络营销推广提升销售量?
    RKMEDIA--VENC/VDEC使用
    Jmeter系列(4) 线程属性详解
    基于SSM的酒店管理系统
    Linux1024一篇通俗易懂的liunx命令操作总结(第十课)
  • 原文地址:https://blog.csdn.net/BASK2312/article/details/127768177