美文网首页
前端面试中遇到的问题总结

前端面试中遇到的问题总结

作者: 韩智超 | 来源:发表于2018-01-11 11:51 被阅读1085次

    一、css相关

    • 盒子模型都有什么

    padding ,margin,border,content


    image
    • CSS margin 属性

    margin:10px 5px 15px 20px;

    上外边距是 10px
    右外边距是 5px
    下外边距是 15px
    左外边距是 20px

    margin:10px 5px 15px;

    上外边距是 10px
    右外边距和左外边距是 5px
    下外边距是 15px

    • CSS 绝对定位 相对定位问题

    absolute相对谁定位:最近一级的父级定位
    下面这段css应该怎么显示

    .house-search{
    
      width: 100px;
      height: 100px;
      background-color: red;
      position: relative;
      bottom: 50px;
      right: 50px;
    
    
      div{
        width: 50px;
        height: 50px;
        position: absolute;
        bottom: 50px;
        right: 50px;
      }
    
    }
    
    • 设置宽度和高度为200,又设置了padding ,怎么可以让容器不被撑开,而打乱布局

    1.ie盒子和标准盒子的区别:
    标准盒子的宽度指的是内容快大小的宽度,而ie盒子的宽度指的是边框+填充+内容快的宽度
    W3C标准盒子 = (边框 + 填充 + 内容块大小) ,牵一发而动全身
    传统IE6盒子 = 整体宽高(边框,填充和随盒子大小而调整变化)
    2.怎么设置盒模型:
    CSS3:box-sizing
    box-sizing:content-box : 标准的W3C盒子模型
    box-sizing:border-box: 传统IE6的盒子模型
    box-sizing:padding-box: 目前只对火狐生效,也是减去适应..但是从padding开始
    3.js如何获取盒模型
    window.getComputedStyle(dom).width/height

    • 请解释一下为什么需要清除浮动?清除浮动的方式

    清除浮动是为了清除使用浮动元素产生的影响。浮动的元素,高度会塌陷,而高度的塌陷使我们页面后面的布局不能正常显示。
    3、常规的使用一个class;
    .clearfix::before, .clearfix::after {
    content: " ";
    display: table;
    }
    .clearfix::after {
    clear: both;
    }
    .clearfix {
    *zoom: 1;
    }

    • 垂直居中的几种方法

    利用 flex 布局
    实际使用时应考虑兼容性

     .container {
    display: flex;
    align-items: center;        /* 垂直居中 */
    justify-content: center;    /* 水平居中 */
    

    }
    .container div {
    width: 100px;
    height: 100px;
    background-color: pink; /* 方便看效果 /
    }
    单行文本:
    text-align:center/line-height等于行高
    未知容器的宽高,利用 transform 属性:
    div {
    position: absolute; /
    相对定位或绝对定位均可 /
    width:500px;
    height:300px;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: pink; /
    方便看效果 */
    }

    • position的值relative和absolute定位原点是?

    absolute
    生成绝对定位的元素,相对于值不为 static的第一个父元素 进行定位。fixed (老IE不支持)
    生成绝对定位的元素,相对于浏览器窗口进行定位。(滴滴面试的时候问到了)
    relative
    生成相对定位的元素,相对于其正常位置进行定位。
    static
    默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right z-index 声明)。
    inherit
    规定从父元素继承 position 属性的值。

    • 对BFC规范(块级格式化上下文:block formatting context)的理解?

    (W3C CSS 2.1 规范中的一个概念,它是一个独立容器,决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。)
    一个页面是由很多个 Box 组成的,元素的类型和 display 属性,决定了这个 Box 的类型。
    不同类型的 Box,会参与不同的 Formatting Context(决定如何渲染文档的容器),因此Box内的元素会以不同的方式渲染,也就是说BFC内部的元素和外部的元素不会互相影响。

    • 解决BFC的几种方法

    overflow:hidden/overflow:auto/float != none
    BFC还可以用来清除浮动

    • vertical-align的默认值

    默认是:baseline
    baseline :元素放置在父元素的基线上
    top:把元素的顶端与行中最高元素的顶端对齐
    middle:把此元素放置在父元素的中部

    • 页面三栏布局(左右200px,中间自适应) 5种方法

    1.浮动布局(float:left,float:right)
    优点:兼容性比较好
    缺点:需要指定高度,需要处理周围浮动元素
    2.绝对布局(absolute)
    优点:比较好处理
    缺点:需要指定高度,脱离了文档流,之后的元素也要脱离
    3.flexbox布局
    优点:写法容易,移动端用的很多,不需要指定高度,内容会自动撑开

    缺点:不兼容ie8
    4.表格布局(display:table-cell)
    优点:写法容易 如果不指定高度,内容会自动撑开
    缺点:如果超出表格高度,其余表格也需要同时调整高度
    5.网格布局
    display: grid;
    grid-template-rows: 100px;
    grid-template-columns: 300px auto 300px;
    缺点:需要指定高度

    • 优雅降级和渐进增强的区别

    渐进增强 progressive enhancement:针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。

    优雅降级 graceful degradation:一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。

    区别:优雅降级是从复杂的现状开始,并试图减少用户体验的供给,而渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要。降级(功能衰减)意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处于安全地带。

    • 左边固定,右边自适应及左边自适应,右边固定布局的几种方法

    一、左边固定,右边自适应的布局

    1. 左边左浮动,右边加个overflow:hidden;
      .lt{ float: left;width:200px; background: #ff0;}
      .rt{ overflow: hidden; background: #f0f;}

    2. 左边左浮动,右边加个margin-left;
      .lt{ float: left; width:200px; background: #ff0;}
      .rt{ margin-left: 200px; background: #f0f;}

    3. 左边绝对定位,右边加个margin-left;
      .lt{ position: absolute; top:0; left:0; width:200px; background: #ff0;}
      .rt{ margin-left: 200px; background: #f0f;}

    4. 左右两边绝对定位,右边加个width,top,left,right
      .lt{ position: absolute; top:0 ; left:0 ;width:200px; background: #ff0;}
      .rt{ position: absolute; top:0 ; left:200px; width: 100% ; rigth:0;background: #f0f;}

    二、右边固定,左边自适应的布局

    1. 左边左浮动,margin-left负值,右边右浮动;
      .lt{float:left; width:100%;background: #00f;margin-right: -200px;}
      .rt{float: right; width: 200px;background: #ff0;}

    2. 右边绝对定位,左边margin-right;
      .lt{margin-right:200px; background: #00f;}
      .rt{ position: absolute; right:0; top:0; width: 200px;background: #ff0;}

    3. 左右两边绝对定位,左边加个width,top,left,right
      .lt{ position: absolute; top:0; left:0; rigth:0; width: 100% ; background: #f0f;}
      .rt{ position: absolute; top:0; left:200px; width:200px; background: #ff0;}

    二、js相关

    • call和apply的区别

    call和apply两个方法基本上是一个意思,区别在于 call 的第二个参数可以是任意类型,而apply的第二个参数必须是数组。
    call还可以用于多重继承

    • DOM事件类

    DOM事件的级别
    DOM事件模型:捕获、冒泡
    DOM事件流:捕获-》目标阶段-》冒泡
    捕获的具体流程:window->document->html->body->目标元素
    冒泡的具体流程:目标元素->body->html->document->window

    • event对象的常见应用

    1.event.preventDefault() 阻止默认行为
    2.event.stopPropagation() 阻止冒泡 -》如果子级元素和父级元素都绑定了不同的点击事件,如果需要执行不同点击事件,这时候需要阻止冒泡
    3.event.stopImmediatePropagation()-》事件响应优先级
    4.event.currentTarget-》当前所绑定的事件(父级元素)
    5.event.target -》获取被点击的事件

    事件捕获以及自定义事件的写法
     <body>
      <div id="ev">
        <style media="screen">
          #ev{
            width: 300px;
            height: 100px;
            background: red;
            color: #fff;
            text-align: center;
            line-height: 100px;
          }
        </style>
        目标元素
      </div>
      <script type="text/javascript">
        var ev = document.getElementById('ev');
    
        ev.addEventListener('click', function (e) {
            console.log('ev captrue');
        }, true);
    
        window.addEventListener('click', function (e) {
            console.log('window captrue');
        }, true);
    
        document.addEventListener('click', function (e) {
            console.log('document captrue');
        }, true);
    
        document.documentElement.addEventListener('click', function (e) {
            console.log('html captrue');
        }, true);
    
        document.body.addEventListener('click', function (e) {
            console.log('body captrue');
        }, true);
    
        var eve = new Event('test');
        ev.addEventListener('test', function () {
            console.log('test dispatch');
        });
        setTimeout(function () {
            ev.dispatchEvent(eve);
        }, 1000);
      </script>
      </body>
    
    • vue的事件流程

    1.事件对象:
    通过show($event)把事件对象传到方法里
    2.事件冒泡:

    <script type="text/javascript">
        window.onload = function(){
            var vm = new Vue({
                el:'#box',
                methods:{
                    show:function(){
                        alert(1);
                    },
                    show1:function(){
                        alert(2);
                    }
                }
            });
        }
    </script>
    </head>
     <body>
    <div id="box">
        <div @click="show1()">
            <input type="button" value="按钮" @click="show()"> 
        </div>
    </div>
    </body>
    

    点击按钮的话他会,执行show ,show1方法,依次弹出1,2。

    3.阻止事件冒泡:
    event.cancelBubble = true;
    利用vue的方法阻止冒泡:给HTML元素绑定click事件的时候,改为@click.stop="show()"
    处理事件冒泡和阻止浏览器默认行为,个人喜欢串联使用,@click.stop.prevent,相当于同时执行:
    event.stopPropagation();
    event.preventDefault();

    • 有一个ul,4个li,执行li分别弹出0,1,2

    (1)闭包的形式

    <ul id="testUL">
      <li> index = 0</li>
      <li> index = 1</li>
      <li> index = 2</li>
      <li> index = 3</li>
    </ul>
    <script type="text/javascript">
     var nodes = document.getElementsByTagName("li");
     for(i = 0;i<nodes.length;i+= 1){
         nodes[i].onclick = (function(i){
                   return function() {
                      console.log(i);
                   } //不用闭包的话,值每次都是4
                 })(i);
     }
    </script> 
    

    (2)vue2的形式

    <div class="house-search">
      <ul id="testUL" @click="show($event)">
        <li value="0"> index = 0</li>
        <li value="1"> index = 1</li>
        <li value="2"> index = 2</li>
        <li value="3"> index = 3</li>
      </ul>
    </div>
    
    import Vue from 'vue'
    import html from './index.html'
    
    window.onload = function(){
      new Vue({
        template: html,
        methods:{
          show(event){
            console.log(event.target.value);
          }
        }
      }).$mount('app')
    }
    
    • 数据类型转换
    • js数组去重,二叉树,排序,闭包

    • js中map的使用

    JS的默认对象表示方式为{}键值对方式,但是键都是字符串,所以引用了Map
    var m = new Map([['micheal',99],['bob',90],['baobao',100]]);
    m.get('micheal');
    也可以这样:
    var m = new Map(); // 空Map m.set('Adam', 67); // 添加新的key-value m.set('Bob', 59); m.has('Adam'); // 是否存在key 'Adam': true m.get('Adam'); // 67 m.delete('Adam'); // 删除key 'Adam' m.get('Adam'); // undefined

    • 如何设计开发一个图片轮播组件?简述要点或写代码。
    • 前端性能优化大概分为以下几类:

    1.内容方面
    减少http请求
    代码压缩
    js代码写在</body>之前
    浏览器缓存(cookie/sessionStorage/localStorage)
    将静态资源放置在子域名下,实现并行下载数目增加
    缓存ajax结果
    减少DOM节点数

    2.服务器方面
    cdn加速
    gzip压缩

    3.js
    引用压缩过的库(.min)
    减少操作DOM节点,必要时将节点缓存起来(离线更新);
    少用递归或者用尾递归优化
    减少全局变量
    懒加载
    预加载

    4.css
    精简css代码的编写,减少嵌套层次
    使用sprite图
    尽量采用简写
    用link代替@import
    动画要用在脱离文档流的元素上

    5.图片处理
    图片一般要压缩到小于200k(banner等)
    可将资源放至子域名下
    用iconfont代替小图标

    • 异步的几种方式

    一、回调函数

    function f1(callback){
    
        setTimeout(function () {
    
          // f1的任务代码
    
          callback();
    
        }, 1000);
    
      }
    

    回调函数的优点是简单、容易理解和部署,缺点是不利于代码的阅读和维护,各个部分之间高度耦合(Coupling),流程会很混乱,而且每个任务只能指定一个回调函数。

    二、事件监听
    为某个函数绑定事件(比如onclick事件)

     function f1(){
    
        setTimeout(function () {
    
          // f1的任务代码
    
          f1.trigger('done');
    
        }, 1000);
    
      }
    

    这种方法的优点是比较容易理解,可以绑定多个事件,每个事件可以指定多个回调函数,而且可以"去耦合"(Decoupling),有利于实现模块化。缺点是整个程序都要变成事件驱动型,运行流程会变得很不清晰。

    三、观察者模式
    我们假定,存在一个"信号中心",某个任务执行完成,就向信号中心"发布"(publish)一个信号,其他任务可以向信号中心"订阅"(subscribe)这个信号,从而知道什么时候自己可以开始执行。这就叫做"发布/订阅模式"(publish-subscribe pattern),又称"观察者模式"(observer pattern)

    //首先,f2向"信号中心"jQuery订阅"done"信号。
    jQuery.subscribe("done", f2);
    
    //f1函数
      function f1(){
    
        setTimeout(function () {
    
          // f1的任务代码
    
          jQuery.publish("done");
             //jQuery.publish("done")的意思是,f1执行完成后,向"信号中心"jQuery发布"done"信号,
             //从而引发f2的执行。
    
        }, 1000);
    
      }
    
    //f2完成执行后,也可以取消订阅(unsubscribe)。
    jQuery.unsubscribe("done", f2);
    

    这种方法的性质与"事件监听"类似,但是明显优于后者。因为我们可以通过查看"消息中心",了解存在多少信号、每个信号有多少订阅者,从而监控程序的运行。

    四、promises对象
    简单说,它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。比如,f1的回调函数f2,可以写成:

    f1().then(f2);
    
    function f1(){
    
        var dfd = $.Deferred();
    
        setTimeout(function () {
    
          // f1的任务代码
    
          dfd.resolve();
    
        }, 500);
    
        return dfd.promise;
    
      }
    
    //比如,指定多个回调函数:
    f1().then(f2).then(f3);
    

    它还有一个前面三种方法都没有的好处:如果一个任务已经完成,再添加回调函数,该回调函数会立即执行。所以,你不用担心是否错过了某个事件或信号。这种方法的缺点就是编写和理解,都相对比较难。

    • 用过哪些vue的库

    vue-router、vuex、vue-loader,vue-spinner, swiper,iview

    • iview和element比较

    1.使用率(npm 平均下载频率,组件数量,star, issue…):
    element 生态更好,使用频率远超过iview ,element开发团队实力更强
    一些小众组件上各有所长 整体iview 更丰富(时间轴,加载进度条,气泡卡片 ,BackTop,图钉)

    2.API风格:
    两者api 总体比较 ,iview 要比element 简洁许多

    3.打包优化:
    首屏优化,第三方组件库依赖过大 会给首屏加载带来很大的压力,一般解决方式是 按需求引入组件

    4.与设计师友好性:
    element 提供了 Sketch 和 Axure 工具 对设计人员友好

    • vue-router如何传递参数
    //(1)路由配置传参
    router.map({
      '/history/:deviceId/:dataId': {
        name: 'history', // give the route a name
        component: { ... }
      }
    })
    
    //(2)v-link传递参数
     <a v-link="{ name: 'history', params: { deviceId: 123, dataId:456 }}">history</a>
    
    //获取参数
    this.$route.params.deviceId
    
    • webpack的一些配置
    // HTML
      const defaultHtmlConfig = customs[name] || {};
      const htmlConfig = {...defaultHtmlConfig, ...html};
      htmlConfig.template = htmlConfig.template || `src/_commons/tpl/${framework}Tpl.hbs`;
    
    //mara-hd的项目的 px2rem
      const px2remConfig = {
        remUnit     : 75,
        remPrecision: 8,
        ...px2rem
      };
    
    • 为什么要在html下font-size下设置:62.5%?

    因为rem的初始值是16px,当设置了body{font-size: 62.5%;}时,1em则=16px*62.5%=10px,1.2em则=12px,这是不是就简单多了,设了62.5%后就有1rem = 10px,便于用rem来指定元素的尺寸,这样响应式的时候可以直接改变font-size而无需计算其他各种样式中出现的尺寸了。 用rem定义尺寸的另一个好处是更能适应缩放/浏览器设置字体尺寸等情况(因为rem相对于字体大小,会同步改变)。
    《响应式Web设计实践》中提到过这一点:最重要的不是屏幕实际的像素大小,屏幕上文字的可读性才是最重要的。

    • postcss和autoprefixer

    postcss是平台,autoprefixer是插件,
    比如,我们用 SASS 来处理 box-shadow 的前缀,但是使用 PostCSS 我们只需要按标准的 CSS 来写就行了,因为最后 autoprefixer 会帮我们做添加这个事情~

    SASS等工具:源代码 -> 生产环境 CSS
    PostCSS:源代码 -> 标准 CSS -> 生产环境 CSS
    SASS + PostCSS模式

    • 要求写一个函数,参数为m,n,生成一个长度为m,每一项都是n的数组,不能用循环。递归

    function creatAry(m, n) {
    var ary = [];
    function aryPush(m, n) {
    if (ary.length == m)return ary;//递归结束条件
    ary.push(n);
    return aryPush(m, n);//这里必须要写return,否则输出为undefined
    }
    return (aryPush(m, n))
    }
    console.log(creatAry(3, 4));

    • var,let,const区别以及js变量提升

    使用var声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象;
    使用let声明的变量,其作用域为该语句所在的代码块内,不存在变量提升;let 允许把变量的作用域限制在块级域中。与var不同处是:var 申明变量要么是全局的,要么是函数级的,而无法是块级的。let的作用域是块,而var的作用域是函数。
    使用const声明的是常量,在后面出现的代码中不能再修改该常量的值。

    let不存在变量提升,所以变量一定要在声明后使用,否则报错。
    const命令声明的变量也不提升,同样存在暂时性死区,只能在声明后使用。同样不可重复声明变量。

    我们可以利用这种块级作用域的特性来避免闭包中因为变量保留而导致的问题,譬如如下两种异步代码,使用 var 时每次循环中使用的都是相同变量;而使用 let 声明的 i 则会在每次循环时进行不同的绑定,即每次循环中闭包捕获的都是不同的 i 实例:

    for(let i = 0;i < 2; i++){
            setTimeout(()=>{console.log(`i:${i}`)},0);
    }
    
    for(var j = 0;j < 2; j++){
            setTimeout(()=>{console.log(`j:${j}`)},0);
    }
    
    let k = 0;
    for(k = 0;k < 2; k++){
            setTimeout(()=>{console.log(`k:${k}`)},0);
    }
    
    // output
    i:0
    i:1
    j:2
    j:2
    k:2
    k:2
    
    • javascript中的深拷贝和浅拷贝?

    浅拷贝:浅拷贝只会将对象的各个属性进行依次复制,并不会进行递归复制,而 JavaScript 存储对象都是存地址的,所以浅复制会导致 obj.arr 和 shallowObj.arr 指向同一块内存地址;

    var obj1 = obj;仅仅是指向同一个地址,并不是浅拷贝,浅拷贝后的值类型数值是互不影响的

    导致的结果就是:
    shallowObj.arr[1] = 5;
    obj.arr[1]   // = 5
    

    *json数组转object对象

          this.mapLists = {};
          this.lists.forEach((v)=>{
            this.mapLists[v.level] || (this.mapLists[v.level] = []);
            this.mapLists[v.level].push(v);
          })
          conso
    

    *vue ajax通信

    import axios from 'axios'
    require('es6-promise').polyfill();
    //Note that URLSearchParams is not supported by all browsers, but there is a polyfill available (make sure to polyfill the global environment).
    import qs from 'qs'
    
    
    
    //简单版本 后期升级
    export function ajaxPost(url, params,headers={}) {
      var sendPromise = axios.post(url,qs.stringify(params),headers);
      return getResult(sendPromise);
    };
    
    export function ajaxGet(url, params,headers={}) {
      var sendPromise = axios.get(url,{params : params,headers:headers});
      return getResult(sendPromise);
    };
    export function setHeader(key,value) {
      axios.defaults.headers.common[key] = value;
    };
    function getResult(promise){
      return new Promise((resolve,reject) => {
        promise.then((result)=>{
          resolve(result.data);
        }).catch((error)=>{
           reject(error.response.data);
        })
      })
    }
    

    三、HTTP协议相关

    • http状态码
    • 浏览器缓存机制
    • http协议的主要特点

    无连接,无状态,简单快速,灵活

    • http报文包含几部分

    请求报文:请求头,请求行,空行,请求体
    响应报文:状态行,响应头,空行,响应体

    • http方法

    GET -> 获取资源
    POST -> 获取资源
    PUT -> 更新资源
    DELETE -> 删除资源
    HEAD -> 获得报文首部

    • POST和GET的区别
    • GET在浏览器回退的时候是无害的,而POST会再次提交请求
    • GET产生的URL地址可以被收藏,而POST不可以
    • GET请求会被浏览器主动缓存,而POST不会,除非主动设置
    • GET请求在URL中传送参数有长度限制,而POST没有限制
    • GET比POST更不安全,因为参数是直接暴露在URL上的,不能用来传递敏感信息
    • sessionStorage 、localStorage 和 cookie 之间的区别

    共同点:都是保存在浏览器端,且同源的。

    区别:cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递;cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下。存储大小限制也不同,cookie数据不能超过4k,同时因为每次http请求都会携带cookie,所以cookie只适合保存很小的数据,如会话标识。

    而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。

    数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。

    作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。Web Storage 支持事件通知机制,可以将数据更新的通知发送给监听者。Web Storage 的 api 接口使用更方便。

    相关文章

      网友评论

          本文标题:前端面试中遇到的问题总结

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