美文网首页面试技巧
最近前端面试题整理

最近前端面试题整理

作者: 高磊_IT | 来源:发表于2020-08-31 17:32 被阅读0次
    1、解释一下CSS的盒子模型? ☆

    答:1)盒模型: 内容(content)、填充(padding)、边界(margin)、 边框(border)

    2)有两种, IE 盒子模型、标准 W3C 盒子模型;IE的content部分包含了 border 和 padding;

    image
    2、CSS水平垂直居中 ☆☆☆

    方法一:

    绝对定位方法:不确定当前div的宽度和高度,采用 transform: translate(-50%,-50%); 当前div的父级添加相对定位(position: relative;)

    图片展示:

    img

    代码如下:

    div{
        background:red;
        position: absolute;
        left:50%;
        top:50%;
        transform: translate(-50%, -50%);
    }
    

    方法二:

    绝对定位方法:确定了当前div的宽度,margin值为当前div宽度一半的负值

    图片展示: 如方法一的图片展示

    代码如下:

    div{
        width:600px;
        height: 600px;
        background:red;
        position: absolute;
        left:50%;
        top:50%;
        margin-left:-300px;
        margin-top:-300px;
    }
    

    方法三:

    绝对定位方法:绝对定位下top left right bottom 都设置0

    图片展示: 如方法一的图片展示

    代码如下:

    div.child{
        width: 600px;
        height: 600px;
        background: red;
        position:absolute;
        left:0;
        top: 0;
        bottom: 0;
        right: 0;
        margin: auto;
    }
    

    方法四:

    flex布局方法:当前div的父级添加flex css样式

    展示图如下:

    img

    代码如下:

    .box{
        height:800px;
        -webkit-display:flex;
        display:flex;
        -webkit-align-items:center;
        align-items:center;
        -webkit-justify-content:center;
        justify-content:center;
        border:1px solid #ccc;
    }
    div.child{
        width:600px;
        height:600px;
        background-color:red;
    }
    

    方法五:

    table-cell实现水平垂直居中: table-cell middle center组合使用

    展示图如下:

    img

    代码如下:

    .table-cell {
        display: table-cell;
        vertical-align: middle;
        text-align: center;
        width: 240px;
        height: 180px;
        border:1px solid #666;
    }
    

    方法六:

    绝对定位:calc() 函数动态计算实现水平垂直居中

    展示图如下:

    img

    代码如下:

    .calc{
      position: relative;
      border: 1px solid #ccc;
      width: 400px;
      height: 160px;
    }
    .calc .child{
      position: absolute;
      width: 200px;
      height: 50px;
      left:-webkit-calc((400px - 200px)/2);
      top:-webkit-calc((160px - 50px)/2);
      left:-moz-calc((400px - 200px)/2);
      top:-moz-calc((160px - 50px)/2);
      left:calc((400px - 200px)/2);
      top:calc((160px - 50px)/2);
    }  
    
    3、CSS 如何取消浮动

    答:https://www.cnblogs.com/wush-1215/p/10623243.html

    4、CSS flex布局(问:解释什么是flex)

    答:Flex是Flexible Box的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。
    布局的传统解决方案,基于盒状模型,依赖display属性+ position属性+ float属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。

    简单的分为容器属性和元素属性
    容器的属性:

    · flex-direction:决定主轴的方向(即子item的排列方法)
    .box {
    flex-direction: row | row-reverse | column | column-reverse;
    }

    · flex-wrap:决定换行规则
    .box{
    flex-wrap: nowrap | wrap | wrap-reverse;
    }

    · flex-flow:
    .box {
    flex-flow: <flex-direction> || <flex-wrap>;
    }

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

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

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

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

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

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

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

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

    · align-self:允许单个项目与其他项目不一样的对齐方式,可以覆盖align-items,默认属性为auto,表示继承父元素的align-items

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

    <!-- DOM结构 -->
    <div id="container">
      <div id="center"></div>
      <div id="left"></div>
      <div id="right"></div>
    </div>
    
    #container {
        display: flex;
    }
    
    #center {
        flex: 1;
    }
    
    #left {
        flex: 0 0 200px;
        order: -1;
    }
    
    #right {
        flex: 0 0 150px;
    }
    

    注:https://www.runoob.com/cssref/css3-pr-flex.html

    5、变量提升

    答:
    注:https://www.jianshu.com/p/864b0003d7a9?tdsourcetag=s_pcqq_aiomsg
    https://blog.csdn.net/weixin_44022064/article/details/103821052

    6、闭包 ☆☆

    答:
    (1)什么是闭包:
    闭包是指有权访问另外一个函数作用域中的变量的函数。

    闭包就是函数的局部变量集合,只是这些局部变量在函数返回后会继续存在。闭包就是就是函数的“堆栈”在函数返回后并不释放,我们也可以理解为这些函数堆栈并不在栈上分配而是在堆上分配。当在一个函数内定义另外一个函数就会产生闭包。

    (2)为什么要用:

    匿名自执行函数:我们知道所有的变量,如果不加上var关键字,则默认的会添加到全局对象的属性上去,这样的临时变量加入全局对象有很多坏处,比如:别的函数可能误用这些变量;造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链上遍历的)。除了每次使用变量都是用var关键字外,我们在实际情况下经常遇到这样一种情况,即有的函数只需要执行一次,其内部变量无需维护,可以用闭包。

    结果缓存:我们开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部的引用,从而函数内部的值可以得以保留。

    function f1(){
        var n = 999;
        nAdd = function(){
            n+=1
        }
        function f2(){
            alert(n)
        }
        return f2
    }
    var result = f1();
    result();
    nAdd();
    result();
    
    7、原型链

    答:原型本身也是一个对象,这个对象就是Object的实例,所以原型也可以调用到Object的原型,这样就组成了一个链式结构,这个就是原型链。
    注:https://www.cnblogs.com/shuiyi/p/5305435.html

    8、Event Loop(介绍node中的事件循环) ☆☆

    答:链接:https://www.nowcoder.com/questionTerminal/6c17f460e32d4baeaf66c20223354f97
    来源:牛客网

    Event Loop:
    
        1.遇到sciprt之后开始第一个宏任务
    
        2.执行过程中遇到异步请求,会将其压入任务队列,交由异步事件引擎处理
    
        3.执行完宏任务后,检测是否存在微任务,有的话会先执行微任务
    
        4.执行第二个宏任务
    
    new Promise((resolve, reject) => {
    
        console.log(1)
    
    }).then(_ => {
    
        console.log(2)
    
    })
    
    setTimeout(_ => {
    
        console.log(3)
    
    }, 300)
    
    执行顺序: 1 -> 2->3
    
    promise属于微任务, setTimeout属于宏任务
    

    注:https://segmentfault.com/a/1190000012925872?utm_source=tag-newest

    9、promise

    答:promise表示一个异步操作的最终结果,与之交互的方式主要是then方法,该方法主要注册了二个回调函数,用于接收promise的最终结果和不能执行的原因。
    promise的状态主要有三种:等待、执行、拒绝
    1、等待pending 等待进入执行或拒绝状态
    2、执行 resolve不能进入其他状态,有一个不可变的最终结果
    3、拒绝rejected 不能进入其他状态,有一个不可变的拒绝原因

    10、$nextTick ☆☆

    答:因为vue是异步更新的,$nextTick用来知道什么时候DOM更新完成。

    当修改了data的值然后马上获取这个dom元素的值,是不能获取到更新后的值,
    你需要使用$nextTick这个回调,让修改后的data值渲染更新到dom元素之后在获取,才能成功。
    
    11、vue的双向绑定原理 ☆☆☆☆☆

    答:vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变;
    核心:关于VUE双向数据绑定,其核心是 Object.defineProperty()方法。
    https://www.cnblogs.com/sweeeper/p/10829887.html

    12、vue生命周期(考察生命周期某个阶段做了什么) ☆☆

    答:每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做 生命周期钩子 的函数,这给了用户在不同阶段添加自己的代码的机会。(ps:生命周期钩子就是生命周期函数)例如,如果要通过某些插件操作DOM节点,如想在页面渲染完后弹出广告窗, 那我们最早可在mounted 中进行。

    注:vue的生命周期是:vue实例从创建到摧毁,也就是开始创建、初始化数据、编译模板、挂载DOM → 渲染、更新 → 渲染、卸载等一系列过程。

    13、vue-router 有哪几种导航钩子 ☆☆☆

    答:三种,
    第一种:是全局导航钩子:router.beforeEach(to,from,next),作用:跳转前进行判断拦截。
    第二种:组件内的钩子
    第三种:单独路由独享组件
    参考地址:https://www.cnblogs.com/goloving/p/9211295.html

    14、 await和async与promise区别 ☆

    注:https://www.jianshu.com/p/463280af23ef

    15、vue和angular区别 ☆

    注:https://www.imooc.com/article/71832?block_id=tuijian_wz

    16、ES6新特性 ☆☆


    模块化
    箭头函数
    函数参数默认值
    模板字符串
    解构赋值
    延展操作符(展开操作符)
    对象属性简写
    Promise
    Let与Const

    17、有没有用过Directive指令 ☆☆

    https://cn.vuejs.org/v2/guide/custom-directive.html

    18、vue-router路由的两种模式 ☆☆☆
    答:
    1、hash模式:vue-router默认hash模式,
       使用URL的hash来模拟一个完整的URL,于是当URL改变时,页面不会重新加载。
    2、history模式:这种模式充分利用history.pushState API来完成URL跳转而无需重新加载页面。
    //设置mode属性,设置路由模式
    const router = new VueRouter({
      mode:'history',
      routes:[..]
    })
    
    19、vue如何优化首屏加载 ☆☆
    20、vue性能优化
    21、js 实现sleep函数

    https://blog.csdn.net/qq_36711388/article/details/89787637

    22、module.export、exports、export default、export有什么区别

    https://www.cnblogs.com/little-baby/p/12783006.html

    23、如何设计前端灰度发布

    https://www.jianshu.com/p/1329b38ef5d4

    24、每页返回10000条数据,如何优化前端渲染和交互体验

    1、异步加载
    2、碎片化
    注:可能会问到滚动条的问题
    https://blog.csdn.net/weixin_34116110/article/details/87946321
    ☆☆

    25、移动端300ms延迟以及点击穿透 ☆☆
    1、禁用缩放
    <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    2、改变视口宽度
    <meta name="viewport" content="width=device-width" /> 
    3、touch-action
    设置 touch-action 属性,该设置会禁用掉该元素上的浏览器代理的任何默认行为,包括缩放,移动,拖拽等.它把所有的触摸类型的交互事件都禁止掉了,导致页面也不能滚动.感觉在稍微复杂点的实际开发中,应该不会这么设置吧.
    html {
      touch-action: none;
    }
    4、引用fastclick库
    

    参考地址:https://juejin.im/post/6854573211317698568

    26、面试官:我这样this.xxx[xxx] = xxx,在data里添加一个数据,vue能不能侦测到?为什么?(有类似的问题) ☆☆

    答:不能,在new Vue()初始化的时候,在实例的data初始化的数据,才能被侦测到;因为在生命周期beforeCreate到create钩子之间会进行将data中的数据进去双向绑定的侦测;实例初始化完之后再添加的数据,无办法完成侦测初始化

    27、JS防抖与节流(性能优化) ☆☆

    防抖:动作停止后的时间超过设定的时间时执行一次函数。注意:这里的动作停止表示你停止了触发这个函数,从这个时间点开始计算,当间隔时间等于你设定时间,才会执行里面的回调函数。如果你一直在触发这个函数并且两次触发间隔小于设定时间,则函数一直不会执行。

    简单实现:

    function debance(fn, delay) {
      let timer = null;
      return () => { 
       if (timer) { 
         clearTimeout(timer);
      }
      timer = setTimeout(() => {
        fn();
      }, delay);
    };
    } 
    window.addEventListener( 
     "scroll",
      debance(() => { 
       console.log(111); 
     }, 1000) ); 
    

    防抖应用场景:

    1. search搜索联想,用户在不断输入值时,用防抖来节约请求资源
    2. window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次

    节流:一定时间内执行的操作只执行一次,也就是说即预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期。

    简单实现: 
    //方法一:设置一个标志 
    function throttle(fn, delay) { 
      let flag = true;
     return () => { 
      if (!flag) return; 
      flag = false;
       timer = setTimeout(() => { 
        fn();
       flag = true; }, delay);
     };
     }
     //方法二:使用时间戳 
    function throttle(fn, delay) { 
      let startTime=new Date()
     return () => { 
      let endTime=new Date()
       if (endTime-startTime>=delay){ 
        fn() 
        startTime=endTime
       }else{ 
        return
       } 
      }; 
      }
     window.addEventListener(
       "scroll", 
      throttle(() => {
       console.log(111); 
      }, 1000) 
      ); 
    

    节流应用场景:

    1. 鼠标不断点击触发,mousedown(单位时间内只触发一次)
    2. 监听滚动事件,比如是否滑到底部自动加载更多(懒加载)
    28、get和post区别,哪个容易造成跨域问题,怎么解决跨域 ☆
    GET请求会被浏览器主动cache,而POST不会,除非手动设置
    get把请求的参数放在url上,即HTTP协议头上 post把参数放在HTTP的包体内
     Get 方式传输的数据量非常小,一般限制在 2 KB 左右,但是执行效率却比 >Post 方法好;而 Post 方式传递的数据量相对较大,它是等待服务器来读取数>据,不过也有字节限制(实际上IIS4中最大量为80KB,IIS5中为100KB),这是为>了避免对服务器用大量数据进行恶意攻击 
    GET请求只能进行url编码,而POST支持多种编码方式 
    GET产生的URL地址可以加入书签,而POST不可以 
    GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留
     GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息
    
    29、前端安全 ☆☆

    一、XSS攻击(跨站脚本攻击)
    防御:
    1、转义字符
    2、白名单
    二、CSRF(跨站请求伪造)
    防御:
    1、增加token在请求中放入攻击者不能伪造的信息
    2、通过Referer识别
    3、网站重要操作增加验证码

    30、强缓存和协商缓存 ☆
    31、获取当前页面中所有HTML tag的名字,以数组形式输出,不包含重复的标签
    
    const getTagNameNum = () => {
      return new Set([...document.querySelectorAll('*')].map(el => el.tagName)).size
    }
    

    参考地址:https://blog.csdn.net/weixin_30386713/article/details/98829121

    31、Vue模板编译过程

    首先会先将模版通过解析器,解析成AST(抽象语法树),然后再通过优化器,遍历AST树,将里面的所有静态节点找出来,并打上标志,这样可以避免在数据更新进行重新生成新的Vnode的时候做一些无用的功夫,和diff算法对比时进行一些无用的对比,因为静态节点这辈子是什么样就是什么样的了,不会变化。接着,代码生成器会将这颗AST编译成代码字符串,这段字符串会别Vdom里面的createElement函数调用,最后生成Vnode。

    32、computed和watch
    33、说下v-if跟v-show区别
    34、组件中的data为什么是一个函数

    答:一个组件被复用多次的话,也就会创建多个实例。本质上,这些实例用的都是同一个构造函数。如果data是对象的话,对象属于引用类型,会影响到所有的实例。所以为了保证组件不同的实例之间data不冲突,data必须是一个函数。

    35、说一下v-model的原理

    答:v-model本质就是一个语法糖,可以看成是value + input方法的语法糖。 可以通过model属性的prop和event属性来进行自定义。原生的v-model,会根据标签的不同生成不同的事件和属性。

    36、Vue中组件生命周期调用顺序说一下

    答:组件的调用顺序都是先父后子,渲染完成的顺序是先子后父。

    组件的销毁操作是先父后子,销毁完成的顺序是先子后父。

    加载渲染过程

    父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount- >子mounted->父mounted

    子组件更新过程

    父beforeUpdate->子beforeUpdate->子updated->父updated

    父组件更新过程

    父 beforeUpdate -> 父 updated

    销毁过程

    父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

    37、SSR了解吗 ☆ ☆

    答:SSR也就是服务端渲染,也就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成,然后再把html直接返回给客户端。

    SSR有着更好的SEO、并且首屏加载速度更快等优点。不过它也有一些缺点,比如我们的开发条件会受到限制,服务器端渲染只支持beforeCreate和created两个钩子,当我们需要一些外部扩展库时需要特殊处理,服务端渲染应用程序也需要处于Node.js的运行环境。还有就是服务器会有更大的负载需求。

    38、Vue-router跳转和location.href有什么区别 ☆ ☆

    答:使用location.href='/url'来跳转,简单方便,但是刷新了页面;
    使用history.pushState('/url'),无刷新页面,静态跳转;
    引进router,然后使用router.push('/url')来跳转,使用了diff算法,实现了按需加载,减少了dom的消耗。
    其实使用router跳转和使用history.pushState()没什么差别的,因为vue-router就是用了history.pushState(),尤其是在history模式下。

    39、params和query的区别 ☆ ☆
    答:用法:query要用path来引入,params要用name来引入,接收参数都是类似的,分别是this.$route.query.name和this.$route.params.name。
    url地址显示:query更加类似于我们ajax中get传参,params则类似于post,说的再简单一点,前者在浏览器地址栏中显示参数,后者则不显示
    注意点:query刷新不会丢失query里面的数据
    params刷新 会 丢失 params里面的数据。
    
    40、vue-router 是什么?它有哪些组件

    答:vue用来写路由一个插件。router-link、router-view
    参开地址:https://juejin.im/post/6844903945530245133

    41、怎么定义 vue-router 的动态路由? 怎么获取传过来的值?

    答:在router目录下的index.js文件中,对path属性加上/:id。 使用router对象的params.id。

    42、Promise.all 和 Promise.race

    Promise.all是支持链式调用的,本质上就是返回了一个Promise实例,通过resolve和reject来改变实例状态。

    Promise.myAll = function(promiseArr) {
      return new Promise((resolve, reject) => {
        const ans = [];
        let index = 0;
        for (let i = 0; i < promiseArr.length; i++) {
          promiseArr[i]
          .then(res => {
            ans[i] = res;
            index++;
            if (index === promiseArr.length) {
              resolve(ans);
            }
          })
          .catch(err => reject(err));
        }
      })
    }
    
    Promise.race = function(promiseArr) {
      return new Promise((resolve, reject) => {
        promiseArr.forEach(p => {
          // 如果不是Promise实例需要转化为Promise实例
          Promise.resolve(p).then(
            val => resolve(val),
            err => reject(err),
          )
        })
      })
    }
    

    相关文章

      网友评论

        本文标题:最近前端面试题整理

        本文链接:https://www.haomeiwen.com/subject/bsbusktx.html