2019.7月-前端面试总结(H5+C3+JS+ES6+Vue+浏览器)

第二次面试

HTML

  1. HTML5中的新标签,举例一下

    canvas绘画,本地离线存储localStorage,sessionStorage,video和audio元素,语义化元素,表单类型(date,time,email等),地理定位等

CSS

  1. CSS3新的标签

    边框:圆角border-radius,阴影box-shadow,边框图片border-image
    背景:背景定位区域background-origin,背景大小支持百分比background-size
    文字效果:文字阴影text-shadow,长单词拆分word-wrap
    2D转换:transform:对元素进行移动translate(),缩放scale(),转动rotate(),拉伸skew()
    3D转换:transform:对元素进行x轴旋转rotateX(),y轴旋转rotateY()
    过渡,动画, 多列等等

  2. 如何垂直居中一个浮动元素

    • 父盒子有宽高

    父元素相对定位,子元素绝对定位,top:50%;left:50%。margin负的左右二分之一的height,width

    .content{
    position: absolute;
    top: 50%;
    left: 50%;
    100px;
    float: left;
    height: 100px;
    background-color: #ff6700;
    margin-top: -50px;
    margin-left: -50px;
    }

    • 父盒子没有高宽

    父盒子相对定位,子盒子决定定位,上下左右都为0,margin:auto;

     .content{
          200px;
         height: 200px;
         background-color: #ff6700;
         float: left;
         margin: auto;
         position: absolute;
         left: 0;
         top: 0;
         bottom: 0;
         right: 0;
     }
    
  3. nth选择器

    CSS3 :nth-child() 选择器

    规定属于其父元素的第二个子元素的每个 p 的背景色:

    p:nth-child(2)
    {
    background:#ff0000;
    }

  4. CSS外边距(margin)重叠及防止方法

    详解:
    https://github.com/zuopf769/notebook/blob/master/fe/CSS%E5%A4%96%E8%BE%B9%E8%B7%9D(margin)%E9%87%8D%E5%8F%A0%E5%8F%8A%E9%98%B2%E6%AD%A2%E6%96%B9%E6%B3%95/README.md

    1. 相邻marign重叠的问题

      1.1 示例:

       <style>
       *{
           margin:0;
           padding: 0;
       }
       .divout{
            100px;
           height: 100px;
           background: yellow;
           margin-bottom: 50px;
           border: 1px solid black;
       }
       .divout1{
           50px;
           height: 50px;
           background: yellow;
           margin-top: 80px;
               /*float:left;*/
           /*position:absolute;*/
           border: 1px solid black;
       }
       </style>
       <body>
           <div class="divout">        
           </div>
           <div class="divout1">        
           </div>
       </body>
      

      1.2 外边距重叠计算方式

      • 全部都为正值,取最大者;

      • 不全是正值,则都取绝对值,然后用正值的最大值减去绝对值的最大值;

      • 没有正值,则都取绝对值,然后用0减去最大值。

      1.3 解决办法

      • 底部元素设置为浮动 float:left;
      • 底部元素的position的值为absolute/fixed
      • 在设置margin-top/bottom值时统一设置上或下
    2. 元素和父元素margin值问题
      父元素无 border、padding、inline content 、 clearance时,子元素的margin-top/bottom会与父元素的margin产生重叠问题。

      示例

       <style>
       *{
           margin:0;
           padding: 0;
           color: black;
       }
       #parrent{
           300px;
           height:150px;
           margin-top: 20px;
           background:teal;
       }
       #box1{
           100px;
           height:100px;
           background:aqua;
           margin:100px 0;
       }
      
       <body>
           <div id="parrent">
               <div id="box1">
               我是box1
               </div>
               我是内容
           </div>
       </body>
      

      2.1 解决办法
      外层元素添加padding
      外层元素 overflow:hidden;
      外层元素透明边框 border:1px solid transparent;
      内层元素绝对定位 postion:absolute:
      内层元素 加float:left;或display:inline-block;

  5. 说一下flex弹性布局的属性

     justify-content: //子元素水平排列的方式
                     center  //居中
                     space-between  //两端对齐
                     space-around   // 子元素拉手分布
                     flex-start     // 居左
                     flex-end      //居右
     
     align-items  :  // 子元素的垂直居中的排列方式
                     enter    // 居中
                     flex-end   //底部
                     flex-start   //开始
     
     align-content :  //多行的时候,子元素的垂直排列方式
                      center    //居中
                      flex-end   //底部
                      flex-start   //开始
                      flx-direction:  // 排列方式row 横向排列
                      row-reverse    //横向反向排列
     
     flex-wrap : //子元素是否在一行显示
                     no-wrap   //不换行
                     wrap    //换行
    
  6. 说你对rem的理解

    • 相对长度单位,相对于根元素(即html元素)font-size计算值的倍数。简单来说,就是一个相对单位,相对根元素子体大小的倍数。
    • 例如:html的font-size:12px;那么使用rem作为单位的,1rem等价于12px,2rem等价于24px;
    • 按定高宽设计出来页面,然后转换为rem单位,配合js查询屏幕大小来改变html的font-size,完美自适应大屏小屏。
  7. px、rem和em的区别

    px:相对长度单位。像素px是相对于显示器屏幕分辨率而言的。特点:

    • IE无法调整那些使用px作为单位的字体大小;
    • 国外的大部分网站能够调整的原因在于其使用了em或rem作为字体单位;
    • Firefox能够调整px和em,rem,但是96%以上的中国网民使用IE浏览器(或内核)。
    • em:是相对长度单位。相对于当前对象内文本的字体尺寸。如当前未设置,则相对于浏览器的默认字体尺寸。特点:
    • em的值并不是固定的;
    • em会继承父级元素的字体大小;
    • rem:相对长度单位,相对于根元素(即html元素)font-size计算值的倍数。

JavaScript

  1. JavaScript的数据类型

    值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。

    引用数据类型:对象(Object)、数组(Array)、函数(Function)。

    注:Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值。

  2. 深拷贝和浅拷贝的区别

    1.浅拷贝: 将原对象或原数组的引用直接赋给新对象,新数组,新对象/数组只是原对象的一个引用

    2.深拷贝: 创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”

  3. 深拷贝 JS 实现

    详解:https://juejin.im/post/5b20c9f65188257d7d719c1c

  4. 原型和原型链

    原型:

    JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象。我们可以把所有对象实例需要共享的属性和方法直接定义在 prototype 对象上。这个对象的所有属性和方法,都会被构造函数的所拥有。

    Prototype作为对象的内部属性,是不能被直接访问的,我们一般通过__proto__这个属性进行访问。

    在原型对象中还有一个属性constructor,这个属性对应创建所有指向该原型的实例的构造函数

    原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置到原型对象中。

    原型链:

    在JavaScript中万物都是对象,对象和对象之间也有关系,并不是孤立存在的。对象之间的继承关系,在JavaScript中是通过prototype对象指向父类对象,直到指向Object对象为止,这样就形成了一个原型指向的链条

    当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用。如果没有则去原型的原型中寻找,直到找到Object对象的原型,Object对象的原型没有原型,如果在Object原型中依然没有找到,则返回undefined。

  5. 事件机制和事件委托

    事件流的三个阶段:

    1. 事件捕获
    2. 处于目标阶段
    3. 事件冒泡

    事件委托:

    1. 事件委托是利用了事件的冒泡原理实现的,子元素的事件通过冒泡形式委托父元素执行
  6. 数组的去重

    • 一、利用ES6 Set去重(ES6中最常用)

        function unique (arr) {
          return Array.from(new Set(arr))
        }
        var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
        console.log(unique(arr))
         //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}]
      
    • 二、利用for嵌套for,然后splice去重(ES5中最常用)

        function unique(arr){            
                for(var i=0; i<arr.length; i++){
                    for(var j=i+1; j<arr.length; j++){
                        if(arr[i]==arr[j]){         //第一个等同于第二个,splice方法删除第二个
                            arr.splice(j,1);
                            j--;
                        }
                    }
                }
        return arr;
        }
        var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
            console.log(unique(arr))
            //[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}]     //NaN和{}没有去重,两个null直接消失了
      
    • 三、利用indexOf去重

        function unique(arr) {
        if (!Array.isArray(arr)) {
            console.log('type error!')
            return
        }
        var array = [];
        for (var i = 0; i < arr.length; i++) {
            if (array .indexOf(arr[i]) === -1) {
                array .push(arr[i])
            }
        }
        return array;
        }
        var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
        console.log(unique(arr))
           // [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}]  //NaN、{}没有去重
      
    • 四、利用sort()

    • 五、利用对象的属性不能相同的特点进行去重(这种数组去重的方法有问题,不建议用,有待改进)

    • 六、利用includes

    • 七、利用hasOwnProperty

    • 八、利用filter

    • 九、利用递归去重

    • 十、利用Map数据结构去重

    • 十一、利用reduce+includes

    • 十二、[...new Set(arr)]
      [...new Set(arr)]
      //代码就是这么少----(其实,严格来说并不算是一种,相对于第一种方法来说只是简化了代码)

    详解:https://segmentfault.com/a/1190000016418021

  7. 数组怎么拼接

     var a = [1,2,3];
     var b = [4,5,6];
    

    1、concat

    js的Array对象提供了一个叫concat()方法,连接两个或更多的数组,并返回结果。

     var c = a.concat(b);//c=[1,2,3,4,5,6]
    

    
这里有一个问题,concat方法连接a、b两个数组后,a、b两个数组的数据不变,同时会返回一个新的数组。这样当我们需要进行多次的数组合并时,会造成很大的内存浪费,所以这个方法肯定不是最好的。

2、for循环

大概的思路是:遍历其中一个数组,把该数组中的所有元素依次添加到另外一个数组中。直接上代码:

	for(var i in b){
	    a.push(b[i]);
	}

这样的写法可以解决第一种方案中对内存的浪费,但是会有另一个问题:丑!这么说不是没有道理,如果能只用一行代码就搞定,岂不快哉~

3、apply

函数的apply方法有一个特性,那就是func.apply(obj,argv),argv是一个数组。所以我们可以利用这点,直接上代码:

	a.push.apply(a,b);

调用a.push这个函数实例的apply方法,同时把,b当作参数传入,这样a.push这个方法就会遍历b数组的所有元素,达到合并的效果。

这里可能有点绕,我们可以把b看成[4,5,6],变成这样:

	a.push.apply(a,[4,5,6]);
        然后上面的操作就等同于:
	a.push(4,5,6);

    
这样就很清楚了!

另外,还要注意**两个小问题**:

1)以上3种合并方法并没有考虑过a、b两个数组谁的长度更小。

所以好的做法是预先判断a、b两个数组哪个更大,然后使用大数组合并小数组,这样就减少了数组元素操作的次数!

2)有时候我们不希望原数组(a、b)改变,这时就只能使用concat了。

JQuery

  1. Jquery的美元符号$有什么作用

    jQuery中就是通过这个美元符号来实现各种灵活的DOM元素选择的,例如$(“#main”)即选中id为main的元素。

  2. Jquery中有哪几种类型的选择器?

    从我自己的角度来讲,可以有3种类型的选择器,如下:

    • 1、基本选择器:直接根据id、css类名、元素名返回匹配的dom元素。

    • 2、层次选择器:也叫做路径选择器,可以根据路径层次来选择相应的DOM元素。

    • 3、过滤选择器:在前面的基础上过滤相关条件,得到匹配的dom元素。

    • 4、请使用jQuery将页面上的所有元素边框设置为2px宽的虚线?

ES6

  1. es6的箭头函数和普通函数有什么区别

     let f = function(v) {
     return v;
     };
     let f = v => v;
    
  2. promise

    Promise 是异步编程的一种解决方案.简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,可以从改对象获取异步操作的消息。

     // 1. 创建promise实例,在实例中执行异步操作(比如发送网络请求)
     // 2. 异步操作成功时,调用reslove函数传递数据
     // 3. 异步操作失败时,调用reject函数传递错误信息
     const promise = new Promise(function(resolve, reject) {
         // 异步操作
         if (/* 异步操作成功 */){
             resolve(value);
         } else {
             reject(error);
         }
     });
     //  使用promise实例then方法接收reslove或reject返回的数据
     promise.then(function(value) {
         // 此处数据即为reslove回来的数据
         // success
     }, function(error) {
         // 此处数据即为reject回来的数据
         // failure
     });
    
  3. 字符串扩展

    1. includes断字符串中是否包含子字符串,第一个参数表示要测试的子字符串,第二个参数表示从那个位置开始查找,不传默认从索引0开始。
    2. startsWith判断字符串是否以特定的字符串开始
    3. endsWith判断字符串是否以特定的字符串结束
    4. 字符串填充:padStart()和padEnd()可以对字符串进行填充
  4. 扩展运算符-合并数组

     let arr2 = [4,5,6];
     let arr3 = [...arr1,...arr2];
     console.log(arr3); // [1,2,3,4,5,6]
    

Vue

  1. MVVM

    1. MVVM是一种分层次开发思想,它是CommonJS规范的实现
    2. M代表module模型层
    3. V代码view视图层
    4. VM模型层和视图层之间没有任何的联系,而VM会充当一个调度者,将他们联系起来,实现双向数据绑定
  2. vue-router路由模式有几种,原理分别是什么?

    vue-router路由库是用哪种技术实现的,总共有两种,分别叫hash模式和history模式,默认是hash模式

    • hash模式:地址上带有#号;url地址可以放在任意标签中打开;可以兼容低版本的浏览器

    hash模式原理:监听hashchange事件,可以调用window.location.hash获取到锚点值,和路由规则进行匹配,匹配到之后将路由规则中定义的组件渲染到页面

    history模式:地址上没有#号,更加符合URL形式;url地址不能重复打开;

    • history模式原理:利用HTML5新提供的history.pushState API 来完成 URL 跳转而无须重新加载页面

    history模式需要后台进行相关配置:要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面

  3. Vuex怎么用,它相对与localstorage有什么优点和缺点

    vuex的核心是:state,getter,actions,mutations

    • state用来定义存放公共数据
      this.$store.state.msg

    • mutations定义方法
      this.$store.commit('change','我是被修改的数据')

    • getters用于获取数据 进行一些操作 类似于Vue实例中的过滤器和计算属性
      this.$store.getters.fixmsg

    • actionactions和mutations都是定义对数据进行操作的方法,mutations中都是同步方法,mutations中定义异步方法
      this.$store.dispatch('asyncchange','我是被异步修改的数据')

    区别

    localstorage无法实现双向数据绑定,模型层的数据改变视图中数据不会发生改变,vuex数据不能持久化,需要结合localstorage使用,比较臃肿,小型项目不建议使用

  4. axios 是什么?怎么使用?描述使用它实现登录功能的流程

    axios 是请求后台资源的模块。 npm i axios -S

    如果发送的是跨域请求,需在配置文件中 config/index.js 进行配置

    详解:https://segmentfault.com/a/1190000013128858

  5. vue常用的指令

    v-text v-bind v-for v-if v-on

  6. 说一下单向数据流

    组件之间的传值,数据从父级组件传递给子组件,只能单向绑定。

    父组件向子组件传值

    在父组件中定义数据,通过属性绑定的形式绑定到子组件上,在子组件中定义props接收传递过来的变量

    子组件向父组件传值

    在子组件中使用this.$emit触发一个自定义的方法名,然后传递数据第一个参数就是自定义的方法名,第二个参数就是需要传递给父组件的数据

     this.$emit('func',this.msg)
    

    在父组件中使用子组件时,绑定一个事件,事件名称和子组件触发的方法名同名

     <div id='app'>
        <son @func = 'getmsg'></son>
     </div>
    
  7. 双向绑定和原理

    v-model指令、数据视图同步更新、使用的是ES5提供的Object.defineProperty()这个方法实现数据劫持

    数据如何从模型同步到视图?当模型中数据发生变化时会触发Object.defineProperty的set方法,在这个方法内部能够劫持到数据的改变,然后就可以在该方法内部通知视图更新

    视图中的数据如何同步到模型中?(v-model指令是怎么实现改变了元素中的数据同步到模型中)监听表单元素的change事件,在change事件中可以拿到用户输入的数据,然后给模型中的数据赋值

浏览器

  1. SEO优化

    详解:https://segmentfault.com/a/1190000002994538

    SEO:搜索引擎优化.

    白帽SEO:改良和规范网站设计,使之对搜索引擎和用户更加友好,是一种搜索引擎推荐的做法。

    黑帽SEO:利用或者放大搜索引擎的缺陷,使用不正当竞争获取更多的访问量。(例如最近花千骨电视剧热播,马上有一些网站使用这个标题标题,但是内容却是推销广告的,给广大网名造成很大困扰)。

    SEO的主要方面:

    • 网站标题、关键字、描述
    • 网站内容优化
    • 合理设置Robot.txt文件
    • 生成对搜索引擎友好的网站地图
    • 增加外链引用
    • 其中最重要的是以下2个方面:
    • 网站结构布局优化
    • 网页代码优化

    Tips:

    • 将重要html代码放在最前面,广告等不重要的部分放在整个文档的最后,然后利用CSS样式控制广告div左右浮动。
    • 重要内容不要使用js输出。
    • 尽量少使用iframe框架。
    • 对于暂时不需要显示的元素应该使用z-index属性而不是display:none;这样的代码,因为Spider会过滤display属性为none的内容。
    • 尽量精简代码。
  2. cookies , sessionStorage和localStorage区别

    • cookies:数据大小不超过4k,cookies过期之前一直有效,会自动传递到服务器
    • sessionStorage:存储大小相对cookies大得多(5M或更大),关闭浏览器窗口后自动删除,仅存本地
    • localStorage:存储大小相对cookies大得多(5M或更大),除非手动删除,关浏览器后不会删除,仅存本地
  3. 浏览器缓存机制

    从缓存位置上来说分为四种,并且各自有优先级,当依次查找缓存且都没有命中的时候,才会去请求网络。

    • Service Worker
    • Memory Cache
    • Disk Cache
    • Push Cache

    详解:https://www.jianshu.com/p/54cc04190252

  4. 网页性能

    • 减少http请求:图片地图,CSS Sprites(精灵图)。
    • 使用CDN:内容发布网络(CDN)是一组分布在不同地理位置的Web服务器,用于更加有效的向用户发布内容。
    • 添加Expires头:告诉客户端可以使用一个组件的当前副本,直到指定时间为止。
    • 压缩组件,代理缓存
    • 样式防头部,脚本放底部
    • 避免CSS表达式
    • 使用外部的js和css
    • 减少DNS查找
    • 精简javascript
    • 避免重定向
    • 删除重复脚本
    • 配置ETag
    • 使Ajax缓存

    详解:http://www.cnblogs.com/MarcoHan/p/5295398.html

  5. 跨域问题如何解决

    • 1、 通过jsonp跨域
    • 2、 postMessage跨域
    • 3、 跨域资源共享(CORS)
    • 普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。
    • 4、 nginx代理跨域:nginx配置解决iconfont跨域 ,nginx反向代理接口跨域
    • 5、 nodejs中间件代理跨域: vue框架的跨域webpack.config.js部分配置
    • 6、 WebSocket协议跨域

    详解:https://segmentfault.com/a/1190000011145364

  6. 优雅降级和渐进增强
    优雅降级:一开始就构建站点的完整功能,然后 针对浏览器测试和修复 。比如一开始使用 CSS3 的特性构建了一个应用,然后逐步针对各大浏览器进行 hack 使其可以在低版本浏览器上正常浏览
    渐进增强:一开始就针对低版本浏览器进行构建页面,完成基本功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。

项目打包

  1. webpack

    webpack是一个模块打包工具,可以使用它管理项目中的模块依赖,并编译输出模块所需的静态文件。它可以很好地管理、打包开发中所用到的HTML,CSS,JavaScript和静态文件(图片,字体)等,让开发更高效。对于不同类型的依赖,webpack有对应的模块加载器,而且会分析模块间的依赖关系,最后合并生成优化的静态资源。

    面试题:https://www.jianshu.com/p/bb1e76edc71e

写在最后

如果有什么错误,还请各位大佬指出在评论留言,弟弟会更改。

原文地址:https://www.cnblogs.com/hukuangjie/p/11197400.html