You're never really done for, as long as you‘ve got a good story and someone to tell it to.

2021年前端高频面试题

1. 什么是语义化标签

1. 语义化标签就是让页面的内容结构化,便于浏览器和搜索引擎的进行分析,
2. 在没有css的时候,也能以一种文档格式显示,便于阅读。
3. 搜索引擎的爬虫依赖于标记确认上下文和各个关键字权重,有利于SEO.

2. 那你知道有哪些标签?

行内标签:

a、span、small、strong、em、i、code、

块标签:

div 、p、h1~h6、hr、ul、ol、li、dl、dd、
form、table、header、footer、main、nav、sector、
arcitcle、pre、table、tbody、thead、th、tr、tfoot

行内块标签:

img,button,input...

3. 既然你说到块已经行内标签,那说一下区别吧

行内标签:

1. 行内标签在页面中只占据包裹自身内容的空间
2. 设置宽度属性值不生效,只依靠内容决定大小
3. 可以通过line-height设置高度
4. 设置margin和padding只有左右有效,上下无效
5. 内容过多时允许换行并断开(一般都是用于处理文字样式)

块标签:

块元素独占一行, 有标准盒子模型, 
包括margin bodrder padding 和 content 宽度默认值100%

行内块标签:

1. 默认的宽高由内容决定
2. 内容过多时不会断开
3. 可以设置宽高
4. 行内块和行内标签会有行高的概念

4. 那行内和块标签之间如何转换

1. display:none 元素隐藏
2. display:block    元素变成块元素
3. display:inline-block  变成行内块元素
4. display:inline   变成行内元素
5. display:flex    弹性盒

5. 好,你说display:none元素可以隐藏,那你说一下让一个div消失在视野中有几种方式?

1 不显示 display:none
2 设置为透明 opacity:0
3 移出浏览器 比如margin-left:3000px,或者相对定位 left:3000px
4 设置此元素的优先级最低 z-index:-999;
5 设置此元素的父元素宽高都为0
6 不可见 visibility:hidden
7 把此元素移出父元素,设置父元素 overflow:hidden
8 将此元素的font-size line-height width height 都为0

6. 你提到visibility:hidden, 和display:none 有什么区别?

一、空间占据

display: none; 是彻底消失,不在文档流中占位,浏览器也不会解析该元素

visibility:hidden; 是视觉上消失了,可以理解为透明度为0的效果,在文档流中占位,浏览器会解析该元素;

使用visibility:hiddendisplay:none性能上要好,display:none切换显示时,页面产生回流(当页面中的一部分元素需要改变规模尺寸、布局、显示隐藏等,页面重新构建,此时就是回流。所有页面第一次加载时需要产生一次回流),而visibility切换是否显示时则不会引起回流。

二、子元素继承

display:none 不会被子元素继承,但是父元素都不在了,子元素自然也就不会显示了,皮之不存,毛之安附~~

visibility:hidden 会被子元素继承,可以通过设置子元素visibility:visible 使子元素显示出来

opacity: 0 也会被子元素继承,但是不能通过设置子元素opacity: 0使其重新显示

三、事件绑定

display:none 的元素都已经不再页面存在了,因此肯定也无法触发它上面绑定的事件;

visibility:hidden 元素上绑定的事件也无法触发;

opacity: 0元素上面绑定的事件是可以触发的。

四、过渡动画

transition对于display 肯定是无效的;

transition对于visibility 也是无效的;

transition对于opacity 是有效。


7. 你刚刚还提到了opacity, 说一下opacity的兼容处理

ie678下可以使用filter兼容

filter:alpha(opacity=50);

8. 你提到了filter, 那filter还能做哪些事情?

模糊、阴影、亮度、对比度、饱和度、色相、透明度

9. 都有哪几种居中方式?

  1. 定位(父级relative 子级absolute)
    1. top left 50%, margin top left -(一半高度宽度)
    2. top left bottom right 0, margin auto
  2. css3
    1. top left 50%, transform: translate(-50%, -50%);
  3. flex
    1. 设置display flex , justify-content center, align-item center
  4. 父级 固定宽高 display: table-cell vertical-align: middle, text-align: center , 子级 display: inline-block

10. 都有哪些盒子模型?

  1. 标准盒模型 box-sizing: content-box
  2. 怪异盒模型(IE盒模型)box-sizing: border-box
  3. flex弹性布局盒模型

11. 什么是BFC, 怎么创建BFC, BFC解决了哪些问题?

BFC指的是独立渲染区域

创建bfc的方式:
1. float不是none
2. position不是relative和static
3. display的值是inline-block、table-cell、flex、table-caption或者inline-flex
4. overflow不是visible

BFC能解决哪些问题
1. 边距重叠问题
2. 盒子塌陷问题
3. 清除浮动
4. 浮动环绕文字问题


IFC

IFC(Inline Formatting Contexts)
直译为”内联格式化上下文”,IFC的line box(线框)高度由其包含行内元素中最高的实际高度计算而来(不受到竖直方向的padding/margin影响)

水平居中:当一个块要在环境中水平居中时,设置其为inline-block则会在外层产生IFC,通过text-align则可以使其水平居中。

垂直居中:创建一个IFC,用其中一个元素撑开父元素的高度,然后设置其vertical-align:middle,其他行内元素则可以在此父元素下垂直居中。

BFC的布局规则例如以下:

1.ifc中的元素会在一行中从左到右排列。
2.在一行上的所有元素会在该区域形成一个行框。

3.行宽的高度为包含框的高度,高度为行框中最高元素的高度。
4.浮动的元素不会在行框中,并且浮动元素会压缩行框的宽度。

5.行框的宽度容纳不下子元素时,子元素会换到下一行显示,并且会产生新的行框。

6.行框的元素内遵循text-align和vertical-align。


12. 几大经典布局方案

圣杯布局
双飞翼布局
==>左右固定, 中间自适应


13. 跨域

浏览器的同源策略会导致跨域。 同源策略是指同一协议、域名、端口。

跨域解决方式:

  1. jsonp

     基本原理就是通过动态创建script标签,然后利用src属性进行跨域。
    
     服务端返回js脚本,直接会执行。调用事先定义好的回调函数了,并且把数据传入了进来。
    
     回调函数也是动态创建,使用结束后销毁。
    
  2. 跨域资源共享 CORS

    1. 对于客户端,我们还是正常使用xhr对象发送ajax请求。
      唯一需要注意的是,我们需要设置我们的xhr属性withCredentials为true,不然的话,cookie是带不过去的哦,设置: xhr.withCredentials = true;
    2. 对于服务器端,需要在 response header中设置如下两个字段:
      Access-Control-Allow-Origin: http://www.yourhost.com
      Access-Control-Allow-Credentials:true
      这样,我们就可以跨域请求接口了
  3. 服务器代理

  4. document.domain

对于主域名相同,而子域名不同的情况,可以使用document.domain来跨域 这种方式非常适用于iframe跨域的情况。


14.说一下原型,原型链

prototype__proto__

  • 每个对象都有一个__proto__属性,并且指向它的prototype原型对象

  • 每个构造函数都有一个prototype原型对象

    • prototype原型对象里的constructor指向构造函数本身

原型链

每个对象都有一个__proto__,它指向它的prototype原型对象,而prototype原型对象又具有一个自己的prototype原型对象,就这样层层往上直到一个对象的原型prototypenull, 这个查询的路径就是原型链

原型链可以将公用属性存放在同一原型层中,实现继承、节省内存空间等。

当您访问实例的属性时,JavaScript 首先会检查它们是否直接存在于该对象上,如果不存在,则会 [[Prototype]] 中查找。这意味着你在 prototype 中定义的所有内容都可以由所有实例有效共享,你甚至可以稍后更改部分 prototype,并在所有现有实例中显示更改(如果需要)。


16. 什么是继承

继承是一种允许我们在已有类的基础上创建新类的机制;它为子类提供了灵活性,可以重用父类的方法和变量。子类可以使用父类的所有功能,并且对这些功能进行扩展。

实现方式:

原型链继承

将父类的实例作为子类的原型

缺点:

1.  创建子类实例无法向父类构造函数传参
2.  继承单一, 无法实现多继承
3.  所有子类的实例都会共享父类实例的属性。
(原型对象的所有属性被所有实例共享,当其中一个实例修改原型属性时, 其他实例的原型属性也会被改变)。

构造函数继承

使用.call()和.apply()将父类的构造函数用来增强子类实例

缺点:

1. 实例并不是父类的实例,只是子类的实例。
2. 只能继承父类的实例属性和方法,不能继承原型属性/方法。
3. 无法实现函数复用,每个子类都有父类实例函数的副本,影响性能

组合继承

通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用

缺点:

调用了两次父类构造函数,生成了两份实例(损耗内存), 子类的构造函数会代替原型上的父类构造函数。

原型继承

用一个函数包装一个对象, 然后返回这个函数的调用。这个函数变成一个可以随时添加属性和方法的实例或者对象。Object.create()就是这个原理。 实质上,CreateObject() 对传入其中的对象执行了一次浅复制

缺点:

1. 包含引用类型值的属性始终都会共享相应的值
2. 无法实现复用。(新实例属性都是后面添加的)

寄生继承

就是给原型式继承外面套了一个壳子, 可以在这个壳子上添加属性和方法

缺点:

 没有用到原型, 无法复用属性及方法。

寄生组合继承

通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点

  • es6 extend

参考


17. 事件委托/事件代理

可以说

事件委托是指将事件绑定到目标元素的父元素上,利用冒泡机制触发该事件

或者

事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。

好处:

  1. 减少事件注册,节省内存。比如,

    • 在table上代理所有td的click事件。
    • 在ul上代理所有li的click事件。
  2. 简化了dom节点更新时,相应事件的更新。比如

    • 不用在新添加的li上绑定click事件。
    • 当删除某个li时,不用移解绑上面的click事件。

缺点:

  • 事件委托基于冒泡,对于不冒泡的事件不支持。

  • 层级过多,冒泡过程中,可能会被某层阻止掉。

  • 理论上委托会导致浏览器频繁调用处理函数,虽然很可能不需要处理。所以建议就近委托,比如在table上代理td,而不是在document上代理td。

  • 把所有事件都用代理就可能会出现事件误判。比如,在document中代理了所有button的click事件,另外的人在引用改js时,可能不知道,造成单击button触发了两个click事件。

不支持冒泡的事件

  1. 鼠标事件
    • mouseenter
    • mouseleave
  2. 焦点事件
    • focus
    • blur
  3. UI事件
    • load
    • unload
    • resize

18. 事件流

当一个HTML元素产生一个事件时,该事件会在元素节点与根节点之间的路径传播,路径所经过的节点都会收到该事件,这个传播的过程叫
做DOM事件流

事件传播的三阶段

  1. 捕获阶段: 事件对象从window到目标父节点传播的阶段。
  2. 目标阶段: 事件对象到达目标。如果事件类型指定不冒泡,则事件对象将在此阶段完成后停止。
  3. 冒泡阶段: 事件流对象从目标父节点到达window传播的阶段。

注册事件

通常使用addEventListener注册事件,该函数的第三个参数可以是布尔值,也可以是对象,默认值为false,决定了注册的事件是捕获事件(true)还是冒泡事件。 一般来说,如果我们只希望事件只触发在目标上,这时候可以使用

target 和 currentTarget

target是触发事件的某个具体的对象,只会出现在事件机制的目标阶段,即"谁触发了事件,谁就是target"。currentTarget是绑定了当前事件类型的对象,有可能是目标节点的祖先节点。

取消默认行为

w3c的方法是e.preventDefault(),早期版本的IE浏览器使用e.returnValue = false

阻止事件在冒泡阶段传播

event.stopPropagation阻止事件在冒泡阶段传播。


19. 你所知道的http的响应码及含义?

此题有过开发经验的都知道几个,但还是那句话,一定要回答的详细且全面。

1xx(临时响应)

100: 请求者应当继续提出请求。

101(切换协议) 请求者已要求服务器切换协议,服务器已确认并准备进行切换。

2xx(成功)

200:正确的请求返回正确的结果

201:表示资源被正确的创建。比如说,我们 POST 用户名、密码正确创建了一个用户就可以返回 201。

202:请求是正确的,但是结果正在处理中,这时候客户端可以通过轮询等机制继续请求。

3xx(已重定向)

300:请求成功,但结果有多种选择。

301:请求成功,但是资源被永久转移。

303:使用 GET 来访问新的地址来获取资源。

304:请求的资源并没有被修改过

4xx(请求错误)

400:请求出现错误,比如请求头不对等。

401:没有提供认证信息。请求的时候没有带上 Token 等。

402:为以后需要所保留的状态码。

403:请求的资源不允许访问。就是说没有权限。

404:请求的内容不存在。

5xx(服务器错误)

500:服务器错误。

501:请求还没有被实现。


20. 页面渲染html的过程?

不需要死记硬背,理解整个过程即可

浏览器渲染页面的一般过程:

1.浏览器解析html源码,然后创建一个 DOM树。并行请求 css/image/js在DOM树中,每一个HTML标签都有一个对应的节点,并且每一个文本也都会有一个对应的文本节点。DOM树的根节点就是 documentElement,对应的是html标签。

2.浏览器解析CSS代码,计算出最终的样式数据。构建CSSOM树。对CSS代码中非法的语法它会直接忽略掉。解析CSS的时候会按照如下顺序来定义优先级:浏览器默认设置 < 用户设置 < 外链样式 < 内联样式 < html中的style。

3.DOM Tree + CSSOM --> 渲染树(rendering tree)。渲染树和DOM树有点像,但是是有区别的。

DOM树完全和html标签一一对应,但是渲染树会忽略掉不需要渲染的元素,比如head、display:none的元素等。而且一大段文本中的每一个行在渲染树中都是独立的一个节点。渲染树中的每一个节点都存储有对应的css属性。

4.一旦渲染树创建好了,浏览器就可以根据渲染树直接把页面绘制到屏幕上。

以上四个步骤并不是一次性顺序完成的。如果DOM或者CSSOM被修改,以上过程会被重复执行。实际上,CSS和JavaScript往往会多次修改DOM或者CSSOM。

21 怎么样从web前端方面优化性能?至少列举5点?

HTML部分

  • 语义化HTML:好处在于可以使代码简洁清晰,支持不同设备,利于搜索引擎,便于团队开发;

  • 减少DOM节点:加速页面渲染;

  • 给图片加上正确的宽高值:这可以减少页面重绘,同时防止图片缩放;

    • 防止src属性和link的href属性为空:当值为空时,浏览器很可能会把当前页面当成其属性值加载;

正确的闭合标签:如避免使用<div/>,浏览器会多一个将它解析成<div\></div\>的过程;

  • 链接为目录或首页的地址后面加”/”,如http://www.5icool.org/

  • 用LINK而不用@import方式导入样式;

  • 样式放在页头,JS放在页尾;

  • 缩小favicon.ico并缓存;

CSS部分

  • 避免使用CSS Expressions(CSS表达式):如background-color: expression( (newDate()).getHours()%2 ? “#B8D4FF” : “#F08A00″ ) ;

  • 避免使用CSS Filter(CSS滤镜);

  • 使用CSS缩写,减少代码量;

  • 通过CSSSprites把同类图片合成一张,减少图片请求;

  • 减少查询层级:如.header .logo要好过.header .top .logo;

  • 减少查询范围:如.header>li要好过.header li;

  • 避免TAG标签与CLASS或ID并存:如a.top、button#submit;

  • 删除重复的CSS;

Javscript部分

  • 尽量少用全局变量;

  • 使用事件代理绑定事件,如将事件绑定在body上进行代理;

  • 避免频繁操作DOM节点;

  • 不使用EVAL;

  • 减少对象查找,如a.b.c.d这种查找方式非常耗性能,尽可能把它定义在变量里;

  • 类型转换:把数字转换成字符串使用”” + 1,浮点数转换成整型使用Math.floor()或者Math.round();

  • 对字符串进行循环操作,譬如替换、查找,应使用正则表达式;

  • 删除重复的JS;

服务器部分

  • 尽量合并CSS、JS文件,或将其直接写在页面上,减少HTTP请求;

  • 压缩CSS、JS文件,缩短文件传输时间;

  • 避免404错误:特别要避免给404指定一个停摆页面,否则所有404错误都将会加载一次页面;

  • 一般要求减少DNS查询次数,如同一个页面的请求资源尽量少的使用不同的主机名,这可以减少网站并行下载的数量,但很多网站为了加速下载资源其实是特意用了多个主机名,这里要做一个权衡;

  • 使用CDN加速,使用户从离自己最近的服务器下载文件;

  • 减少Cookie的大小,使用无cookie的域,客户端请求静态文件的时候,减少 Cookie 的反复传输对主域名的影响;

  • 为文件头指定Expires,使内容具有缓存性;

  • 使用gzip压缩内容;

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×