前端面试/问题汇总


1. 三列布局知识:

(1)圣杯布局:

        圣杯布局使用float、负margin和relative,不需要添加额外标签。.main元素设置padding,为两侧定宽元素留出位置。内容元素设置100%宽度,占据中间位置。而两侧定宽元素通过设置负margin和relative的偏移属性配合,到达相应位置。(缺点: 并没有实现等高布局;使用了相对定位,扩展性不好)

(2)双飞翼布局:

        双飞翼布局在圣杯布局的基础上,通过为.main元素外添加一层div结构,不使用相对定位。在.main元素上设置margin。两侧的定宽列通过负margin来占据.main元素的margin区域。(缺点: 并没有实现等高布局,增加了html结构)

        总结:由于限定了主要内容元素在html结构中位于前面,通过css样式改变将其位置调换到中间的前提,所以思路并不是很多。float浮动流的元素可以通过负margin调换位置;absolute绝对定位流的元素可以通过偏移属性调换位置;flex弹性盒模型可以通过order属性调换位置;grid通过grid-area调换位置。而处于正常流中的元素除了使用relative外,使用负margin是无法调换位置的,所以table、inline-block等布局方式在此前提下不是很实用。

2. margin折叠问题

        外边距折叠,指的是毗邻的两个看或多个外边距 (margin) 在垂直方向会合并成一个外边距。
   触发条件:毗邻,没有被非空内容、padding、border 或 clear 分隔开的margin特性. 非空内容就是说这元素之间要么是兄弟关系或者父子关系。这些 margin 都处于普通流中,即非浮动元素,非定位元素

html:

<div class="outer">
    <div class="inner">Content</div>
</div> 

css:

.outer {
   b margin-top: 100px;
}

.inner {
    margin-top: 50px;
}

比邻元素的边距总是折叠。但是得除了以下几种情况:

  1. 根元素不折叠
  2. 有间隙不折叠
  3. 浮动不折叠
  4. 创建BFC与子不折叠
  5. positioned 不折叠
  6. inline-box 不折叠
  7. 兄弟有间隙不折叠
  8. 父子间有padding 和 border 不折叠
3. 手动实现debounce throttle reduce函数(跟闭包相关知识)
  • 什么是闭包:

        Closures(闭包)是使用被作用域封闭的变量,函数,闭包等执行的一个函数的作用域。通常我们用和其相应的函数来指代这些作用域。(可以访问独立数据的函数)。闭包是一个函数和声明该函数的词法环境的组合。从理论角度来说,所有函数都是闭包。

  •  debounce函数:也就是防抖函数,调用动作在一定时间后才执行操作,若这段时间内再次调用动作,则重新计算执行时间。好比手一直按着弹簧,直至手松开后才执行操作。
$('#input').on('input', debounce(inputChange, 300));
        functiondebounce (fn, ms){
            var timer;
            return function(){
                let that =this;
                timer &&clearTimeout(timer);
                timer =setTimeout(()=>{
                    console.log(this);
                    fn.call(this, 'aa','bb');
                }, ms);
            }          
        }
        function inputChange(){
            let c =$(this).val();
            console.log(arguments[0],arguments[1])
        } 
  • throttle函数:也就是节流函数,调用动作的时刻大于等于执行周期,则执行该动作,然后进入下一新周期。好比水龙头的水在不断流出,节流函数控制水龙头开关,使水以水滴形式让水流出。
function throttle(fn, ms){
      var timer;
      returnfunction(){
          if(timer) return
          timer =setTimeout(()=>{
              fn.call(this, 'change');
              clearTimeout(timer)
              timer =null;
          },ms);  
      }
}

arguments对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments对象在函数中引用函数的参数。

  • educe函数:
function meduce(arr, fn){
    var result;
    if(arr && arr.length >0){
        for(let i =0; i < arr.length; i++ ){
            if(i ==0){
                result = arr[i]
            }else{
                result = fn.call(this, result,arr[i])
            }
        }    
    }
    return result
}
function add(x,y){
    return x*y
}
let c =meduce(a, add);   

(代码自己简单实现,不一定全面,仅供参考)

4.  箭头函数的this指向问题,手动实现call, apply, bind函数

        普通函数中的this:

        1. this总是代表它的直接调用者(js的this是执行上下文), 例如 obj.func ,那么func中的this就是obj。

        2. 在默认情况(非严格模式下,未使用 'usestrict'),没找到直接调用者,则this指的是 window (约定俗成)。

        3. 在严格模式下,没有直接调用者的函数中的this是undefined。

        4. 使用call,apply,bind(ES5新增)绑定的,this指的是 绑定的对象。

        箭头函数中的this:箭头函数没有自己的this, 它的this是继承而来; 默认指向在定义它时所处的对象(宿主对象),而不是执行时的对象, 定义它的时候,可能环境是window; 箭头函数可以方便地让我们在 setTimeout ,setInterval中方便的使用this。

        call、apply、bind实现如下: 

Function.prototype.myCall=function(obj, ...arg){
     obj.newFn =this;
     obj.newFn(...arg);
     delete obj.newFn;
}
Function.prototype.myApply=function(obj, arr){
     let args = [];
     for(let i=0; i<arr.length;i++){
         args.push(arr[i]);
     }
     returnthis.myCall(obj, ...args);
 }
 Funtion.prototype.myBind=function(obj, ...arg1){
     return (...arg2)=>{
         let args = arg1.concat(arg2);
         let val;
         obj._fn_ =this;
         val = obj._fn_(...args);
         delete obj._fn_;
         return val
     }
}
5.  css里的百分比都是以谁为基数的?如何实现一个随窗口大小变化的正方形?

    百分比:

  • 相对于父元素宽度的:[max/min-]width、left、right、text-indent、padding、margin 等;
  • 相对于父元素高度的:[max/min-]height、top、bottom 等;
  • 相对于主轴长度的:flex-basis 等;相对于继承字号的:font-size 等;
  • 相对于自身字号的:line-height 等;
  • 相对于自身宽高的:border-radius、background-size、border-image-width、transform: translate()、transform-origin、zoom、clip-path 等;
  • 相对于行高的:vertical-align 等;
  • 特殊算法的:background-position (方向长度 / 该方向除背景图之外部分总长度)、border-image-slice (相对于图片尺寸)、filter 系列函数等;

    实现随窗口大小变化的矩形:

  •  以宽度为基准——width: 20%; padding-bottom: 20%; (两个%不等即为矩形,相等为正方形)
  •  以高度为基准——同理
6.  rem的font-size写在body里可不可以?

        不可以。当使用 rem 单位,他们转化为像素大小取决于页根元素的字体大小,即 html 元素的字体大小。根元素字体大小乘以你 rem 值。

7.  []==false {}==false结果是什么 == 的运行机制是什么?

        []==false结果是true,{}==false的结果是报错(Uncaught SyntaxError: Unexpected token ==)。

        1.  是否有NaN

        首先判断双等号两边是否有NaN,如果有的话,则一律返回false。  

        2.  是否有boolean值

        如果有的话则将true转化为1,false转化为0。

        3.  null和undefined

        遇到null或者undefined,则不会进行类型转换,它们相互的比较都返回true。

        4.  有一边是字符串

        分四种情况:

        1)同样是字符串,则直接进行字符串值的比较

        2)是数字,则需要将字符串转化为数字,然后进行比较

        3)有布尔类型,则要将布尔类型转化为0或则1,然后进行比较

        4)对象或者数组类型,则需要调用toString()或者valueOf()方法转化成简单类型,然后进行比较

        对象转化为简单类型时会优先调用valueOf方法,如果可以与简单值进行比较则会直接比较,此时不再调用toString方法。如果调用valueOf方法后无法与简单值进行比较,则会再调用toString方法,最终得到比对的结果。但是需要注意的一点是Date对象不满足上述的规则,Date对象的toString和valueOf方法都是重新定义过的,默认会调用toString方法。

8.  Event Loops :

https://zhuanlan.zhihu.com/p/33087629?iam=032797e9190b1c1a1194ff16cee19c87&utm_source=wechat_session&utm_medium=social&from=groupmessage

        task主要包含:setTimeoutsetIntervalsetImmediateI/OUI交互事件

        microtask主要包含:Promiseprocess.nextTickMutaionObserver

  • queue可以看做一种数据结构,用以存储需要执行的函数
  • timer类型的APIsetTimeout/setInterval)注册的函数,等到期后进入task队列(这里不详细展开timer的运行机制)
  • 其余API注册函数直接进入自身对应的task/microtask队列
  • Event Loop执行一次,从task队列中拉出一个task执行
  • Event Loop继续检查microtask队列是否为空,依次执行直至清空队列

        输出打印结果是多少:

console.log(1)
setTimeout(() => {
    console.log(2)
    new Promise(resolve => {
        console.log(4)
        resolve()
    }).then(() => {
        console.log(5)
    })
    process.nextTick(() => {
        console.log(3)
    })
})
new Promise(resolve => {
    console.log(7)
    resolve()
}).then(() => {
    console.log(8)
})
process.nextTick(() => {
    console.log(6)
})
@ 1,7,6,8,2,4,3,5
9.  http和websocket之间的关系是什么?注意是关系不是不同

        相同点:

        1. 都是基于TCP协议基础上,HTTP如此,websocket亦如此

        2. 都是需要经过request,response阶段,其中websocket在发起请求的时候其实相当于借用了http的头部格式,区别就在于websocket请求头部有一个upgrade:websocket这样的字段(当然还有其他字段,但是这个字段最为关键)。

        3. 如果请求失败,返回的错误编号都是相同的,例如:4**等

        再说不同点:

        1. 正如前面所说,websocket的请求的头部会跟http请求头部有区别,比如多了一个upgrade:websocket字段。

       2. websocket只能是直连,不能通过代理来转发。究其原因应该怕如果通过代理转发的话,一个代理要承受如此多的websocket连接不释放,类似于一次DDOS攻击了。

        3. websocket传输的数据是二进制流,是以帧为单位的,http传输的是明文传输,是字符串传输。

       4. websocket是全双工通信,有点类似于socket通信,在建立连接之后不必再像http那样你一个request我才回一个response了,想发就发,收发自如。

10.  ajax的get和post有什么不同

        (1)get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。post是通过HTTPpost机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。

        (2)对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。两种方式的参数都可以用Request来获得。

        (3)get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。但理论上,因服务器的不同而异。

        (4)get安全性非常低,post安全性较高。

      (5)<formmethod="get" action="a.asp?b=b">跟<form method="get" action="a.asp">是一样的,也就是说,method为get时action页面后边带的参数列表会被忽视;而<form method="post" action="a.asp?b=b">跟<form method="post" action="a.asp">是不一样的。 

11.  如何用一个div实现滴滴的logo 提示 下面的不是纯半圆 是椭圆
.box{
      margin: 50px;
      width: 100px;
      height: 100px;
      background-color: #fff;
      border-radius: 20px;
      text-align: center;
      border: 1pxsolid#eee;
      position: relative;
      box-shadow: 3px3px10px#555;
}
.didi{
      width: 60px;
      height: 50px;
      background: #fff;
      border-radius: 0%0%50%50%;
      border: 10pxsolid;
      border-color: #ff6600;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      box-sizing: border-box;
}
.didi:before{
      content: '';
      width: 10px;
      height: 10px;
      background: #fff;
      position: absolute;
      right: -10px;
      top: -10px;
}
12.  从输入URL到页面加载完成的过程中都发生了什么事情?

        (1)输入地址

        (2)浏览器查找域名的 IP 地址

        (3)这一步包括 DNS 具体的查找过程,包括:浏览器缓存->系统缓存->路由器缓存...

        (4)浏览器向 web 服务器发送一个 HTTP 请求

        (5)服务器的永久重定向响应(从 http://example.com 到 http://www.example.com)

        (6)浏览器跟踪重定向地址

        (7)服务器处理请求

        (8)服务器返回一个 HTTP 响应

        (9)浏览器显示 HTML

        (10)浏览器发送请求获取嵌入在 HTML 中的资源(如图片、音频、视频、CSS、JS等等)

        (11)浏览器发送异步请求

13.  如何优化网页的加载速度?

        1.优化图片资源的格式和大小:

        一个网页中,图片资源的大小占比是最多的,而且单个的文件的大小也很可观。因此,在保证图片质量不变的情况下,尽可能的使用高压缩率的图片格式,图片格式可以按照这个优先级选择webp > jpeg > png > bmp。同时也要根据图片展示尺寸来拉取大小最为匹配的图片资源,不要没事就把原图拉下来使用。以前我就遇到过这种情况,一个196*196大小区域展示的图片,它的文件竟然达到了几兆,最后才发现把1960*1960分辨率的原图拉下来了。

        2.开启网络压缩:

        大部分浏览器在发出请求时,会带上这个标记「Accept-Encoding:gzip, deflate」,表示这个浏览器可以接受以gzip压缩方式传输数据,如果你的网页服务器也支持gzip压缩数据,那么数据以gzip方式传输时,会减少70~80%的流量。

        3.使用浏览器缓存:

        同一个站点下面的不同页面,往往都会复用一部分资源文件,如果把这些资源文件设置为可缓存的,那么在刷新或者跳转到另一个页面时,都无须再从网络拉取相关资源,这样就大大加快了网页的加载速度。

        4.减少重定向请求:

        有的网站对于不同的终端制作了不同的页面,比如说在手机上访问微博,会从weibo.com重定向至weibo.cn,每一次重定向都会导致浏览器重新发起请求,延长加载时间。对于这种情况,应该尽可能使用响应式设计,一个weibo.com站点覆盖至所有终端。

        5.使用CDN存储静态资源:

        CDN是一种静态内容分发网络,它在每个省,甚至每个城市都部署有自己的服务器,用于分发这些静态内容,那么当某个城市的用户要拉取某个资源时,他会首选从本地的CDN服务器上拉取,这样可以保证他最快速的获得该资源。据砖家统计,网络资源中有70%的是静态资源。这就意味着,有70%的内容产生后是不会变化,那么将它们全部放在CDN上面,可以提升这70%的资源的下载速度。

        6.减少DNS查询次数:

        很多人喜欢把不同的图片挂在不同当域名下,比如说图片A挂在a.pm-teacher.com,图片B挂在b.pm-teacher.com。当一个网页同时使用图片A和图片B时,浏览器需要查询两个域名,要知道,每次解析域名都是会浪费时间的,所以尽可能的将全部图片放在一个域名下。

        7.压缩css和js内容:

        这里说的压缩和第2点并不重复,上面提到的压缩是不改变文件内容的压缩。而css和js中有大量的空格和变量命名(如hello="helloword";),如果将这些空格去除,并用简单的字母来代换变量名(如a="helloword";),那么这些css和js原文件的大小也会缩小,这样也对加快拉取速度是有帮助的。

        不知道你有没有看出来,上面提到的优化方案的核心就3点:减少请求数、减少资源大小、找最快的服务器,如果你是一个网站的产品经理,快去找你们的开发确认是否有做过类似的优化吧。

14.  CSS3实现0.5px的边框

        方法一:利用渐变

        关于渐变可以看下面两篇文章做深入了解:

        CSS3 渐变(Gradients

        深入理解CSS3gradient斜向线性渐变

        实现原理:

        把元素的伪类高度设为1px,背景渐变,一半有颜色,一半透明。

.container{
       width: 500px;
       margin: 0px auto;
 }            
.border-gradient{
       position:relative;
       padding: 10px;
}
 
.border-gradient:after {
       content: " ";
       position: absolute;
       left: 0;
       bottom: 0;
       width: 100%;
       height: 1px;
       background-image: linear-gradient(0deg, #f00 50%, transparent 50%);
} 

        方法二:利用缩放

        原理:transform:scale()来达到压缩一半的目的。

.container{
      width: 500px;
      margin: 0px auto;
}
.border-scale{
      position:relative;
      padding: 10px;
 }
.border-scale:after{
      content: "  ";
      position: absolute;
      left: 0;
      bottom: 0;
      width: 100%;
      height: 1px;
      background-color: #f00;
     /*如果不用 background-color, 使用border-top:1px solid #f00; 效果是一样的*/
      -webkit-transform: scaleY(.5);
      transform:scaleY(.5);
}
15.  原型,构造函数

        结果输出多?

Object.prototype.a ='zhaolandelong';
Function.prototype.b ='chenjianming';
functionmyfun(){} var p =newmyfun(); 
console.log(p.a);
console.log(p.b);
console.log(myfun.b);
//zhaolandelong    undefined  chenjianming

16.  bootstrap 实现的 clearfix

       

.clearfix { 
     *zoom: 1; 
} 
 
.clearfix:before, 
.clearfix:after { 
     display: table; 
     line-height: 0; 
     content: ""; 
} 
 
.clearfix:after { 
     clear: both; 
} 

小知识:

1、json转对象的方法:

    举例:
    var str = '{"name":"小明","age":18}';
    将字符串转化json对象:
    1. var json = JSON.parse(str);
    2. var json = eval("(" + str + ")");

    3. var json = (new Function("return " + str))();


阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页