前端面试

前言

以下是整理一些面试中经常会遇到的经典面试题以及自己面试过程中有一些未解决的问题,通过对知识的整理以及经验的总结,重新巩固自身的前端基础知识(有些还没补全,会补全的)。

CSS

position属性值

  • static,默认值,没有定位,元素出现在正常的流中
  • relative,相对定位,相对于其在正常流中的位置进行定位,不会脱离文档流
  • absolute,绝对定位,相对于最近的一级 定位不是 static 的父元素来进行定位,会脱离文档流。
  • fixed,生成绝对定位的元素,相对于浏览器窗口进行定位。(老IE不支持)

清除浮动的方法和清除浮动理由

1.由于使用了浮动,导致在页面排版上面出现了问题:

  • 会导致父元素高度塌陷为零
  • 浮动元素甚至影响到了其父元素的兄弟元素排版

2.清除浮动的方法

  • 空标签清除浮动:

    ​ 是在所有浮动标签后面添加一个空标签 定义css clear:both. 弊端就是增加了无意义标签空标签必须是一个块级元素

  • 利用overflow:auto清除浮动

    ​ 设置overflow为hidden或者auto,给包含浮动元素的父标签添加css属性 overflow:auto; zoom:1; zoom:1用于兼容IE6。

  • 利用伪类:after清除浮动

    ​ 该方法只适用于非IE浏览器。该方法中必须为需要清除浮动元素的伪对象中设置 height:0,否则该元素会比实际高出若干像素。

    1
    2
    3
    4
    5
    6
    .clearfix:after {
    content: '.';
    height: 0;
    display: block;
    clear: both;
    }

position:absolute和float的区别

  • 共同点:对内联元素设置floatabsolute属性,可以让元素脱离文档流,并且可以设置其宽高。
  • 不同点:float仍会占据位置,position会覆盖文档流中的其他元素。

z-index属性

​ z-index只能在position属性值为relative或absolute或fixed的元素上有效

​ 原理说明:z-index的值可以控制定位元素在垂直于显示屏幕方向(z轴)上的堆叠顺序(stack order),值大的元素发生重叠时会在值小的元素上面。

CSS 盒子模型

  • 标准盒模型

    ​ 元素的宽度/高度由border + padding + content的宽度/高度决定,设置元素的width/height属性指的是content部分的宽/高,盒子的宽高为border + padding + content(宽高)+margin

  • IE盒模型

    ​ 设置width/height属性指的是border + padding + content,盒子的宽高为width/height+margin

三栏布局

  • float+margin:

    原理说明:设置两个侧栏分别向左向右浮动,中间列通过外边距给两个侧栏腾出空间,中间列的宽度根据浏览器窗口自适应。

  • position+margin:

    原理说明:通过绝对定位将两个侧栏固定,同样通过外边距给两个侧栏腾出空间,中间列自适应。

  • 双飞翼布局(float + 负margin + margin):

    原理说明:对三者设置左浮动,再设置负边距,左侧设置负左边距为100%,右侧设置负左边距为负的自身宽度;再对中间面板进行外边距设置,留出对应的空间给左右面板

  • 圣杯布局(float + 负margin + padding + position):

    原理说明:三者都设置向左浮动。设置主面板宽度为100%,设置两侧栏的宽度。设置 负边距,左侧设置负左边距为100%,右侧栏设置负左边距为负的自身宽度。设置主面板的padding值给左右两个子面板留出空间。设置两个子面板为相对定位,左侧栏的left值为负的左侧栏宽度,右侧栏的right值为负的右侧栏宽度。

垂直水平居中的方法

  • 绝对定位+margin反向偏移
  • 绝对定位+margin:auto
  • 绝对定位+transform反向偏移
  • flex垂直水平居中

display:none和visibility:hidden的区别

display:none 隐藏对应的元素,在文档布局中不再给它分配空间,它各边的元素会合拢,就当他从来不存在。

visibility:hidden 隐藏对应的元素,但是在文档布局中仍保留原来的空间。

display属性:block、inline-block和inline的区别

  • block:形成会级元素,而且前后都有换行符,可以定义元素宽高
  • inline:形成内联元素,不换行,内联元素的宽度高度由元素内部的结构撑开。定义元素宽高不生效。
  • inline-block:将对象呈递为内联对象,但是对象的内容作为块对象呈递,可以定义宽高。

link 和 @import 的区别

  1. link 是 XHTML 标签,除了加载 CSS 外,还可以定义 RSS 等其他事务; @import 属于 CSS 范畴,只能加载 CSS
  2. link 引用 CSS 时,在页面载入时同时加载; @import 需要页面网页完全载入以后加载
  3. link 是 XHTML 标签,无兼容问题; @import 是在 CSS2.1 提出的,低版本的浏览器不支持link 支持使用
  4. Javascript 控制 DOM 去改变样式;而 @import 不支持

媒体查询

解释浏览器是如何判断元素是否匹配某个CSS选择器

JavaScript

闭包

在JavaScript中,函数中的变量的作用域属于函数作用域,当函数执行完毕,作用域会自动清理而且内存也会被回收。但是闭包是建立在函数内部的一个子函数,由于子函数保持对上级函数的访问,即使当函数执行完毕,作用域也不会随之销毁,这个子函数就是闭包。

null和undefined的区别

1.null表示为“无”的对象,转为数字为0;undefined是一个表示”无”的原始值,转为数值时为NaN。

2.undefined表示该变量声明了,但是没有定义;

3.表示”没有对象”,即该处不应该有值。

4.用typeof类型判断时,null是object,undefined是undefined;表示”没有对象”,转化为布尔类型时,都是false

5.null是一个关键字,而undefined不是一个关键字

typeof null 为什么等于object?

之前只知道typeof null = object,但是却从来不知道是为什么。最新查阅资料的时候,看到了这个原理,记录下来,方便自己以后查看。

原理是这样的,不同的对象在底层都表示为二进制,在 JavaScript 中二进制前三位都为 0 的话会被判断为 object 类型, null 的二进制表示是全 0,自然前三位也是 0,所以执行 typeof 时会返回“ object ”。

这个bug是第一版Javascript留下来的。是一个历史遗留的问题,在这个版本,数值是以32字节存储的,由标志位(1~3个字节)和数值组成。标志位存储的是低位的数据。这里有五种标志位:
000:对象,数据是对象的应用。
1:整型,数据是31位带符号整数。
010:双精度类型,数据是双精度数字。
100:字符串,数据是字符串。
110:布尔类型,数据是布尔值。
最低位有一位,那么标志位只有一个1字节长度;或者是零位,标志位有3个字节长度,多出两个了字节,一共多出四种类型。

有哪些值转化成布尔型后为false?

0、-0、undefined、null、空字符串、NaN

显式和隐式强制类型转换

置换元素=>bfc

判断数据类型的方法

  • typeof(一般用于判断基本数据类型的类型)
  • instanceof(一般用于判断实例化的对象的类型)
  • Object.prototype.toString.call()

jQuery的链式调用原理

通过调用jQuery的api调用返回对象本身

$.ajax([setting])的参数详解

url,dataType(预期服务器返回的数据类型),cache,async(是否异步还是同步),type(请求方式:get or post),timeout(请求超时时间),回调函数(success,error),

数组和对象遍历

  • 数组遍历

    1
    2
    3
    //1.普通的for循环迭代遍历
    //2.for...of遍历
    //3.forEach,map,filter,reduce遍历
  • 对象遍历

    1
    2
    3
    //Object.keys(Object) =>该方法返回一个对象 o 自身包含(不包括原型中)的所有属性的名称的数组。
    //for(item in Object) =>该方法返回一个数组,它包含了对象 o 所有拥有的属性(无论是否可枚举)的名称。
    //object.getOwnPropertyNames(o)=>该方法返回一个数组,它包含了对象 o 所有拥有的属性(无论是否可枚举)的名称

Ajax

原理说明:

  • 新建XMLHttpRequest对象;var xhr = new XMLHttpRequest();
  • 同时调用xhr.open()函数创建一个请求,xhr.send()函数发送请求,设置一个回调函数xhr.onreadystatechange = callback,当xhr.readyState === 4时,xhr.responseText就是完整的接收到的数据。

绑定事件的方法

  • 嵌入dom
  • 直接绑定(例如:onclick事件)
  • 事件监听:addEventListener

跨域问题

跨域就是浏览器的同源策略(域名,协议,端口均相同)造成的,是浏览器施加的安全限制。

  • jsonp的跨域

    原理:利用script标签可以跨域请求资源的性质,向网页中动态插入script标签,来向服务端请求数据。服务端会解析请求的url,至少拿到一个回调函数(比如callback=myCallback)参数,之后将数据放入其中返回给客户端。

  • Cors(跨域资源共享)

  • 代理服务器转发

  • websocket

this

this是JavaScript的一个关键字,this是函数运行时内部创建的一个内部对象,只能在函数内部使用。this总是会指向一个对象,随着函数使用场合的不同,this的值会发生变化。this是指向调用函数那个对象。

this指向:

1、作为普通函数调用(this指向全局对象window对象)
2、作为对象的方法调用(this指向该对象)
3、构造器调用(this指向用new返回的这个对象)
4、call、apply、bind的调用(this指向第一个参数对象)

new 操作符 做了什么事

1、 创建一个新对象;
2、 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
3、 执行构造函数中的代码(为这个新对象添加属性);
4、 返回新对象。

ES6

es6是一个新的标准,它包含了许多新的语言特性和库,是JS最实质性的一次升级。比如’箭头函数’、’字符串模板’、’generators(生成器)’、’async/await’、’解构赋值’、’class’等等,还有就是引入module模块的概念。

箭头函数的特性

可以让this指向固定化,这种特性很有利于封装回调函数
(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。
(4)不可以使用yield命令,因此箭头函数不能用作Generator函数。

说说你对Promise的理解

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

Promise对象有以下两个特点:

  • 对象的状态不受外界影响,Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和Rejected(已失败)
  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果。

计算机网路

说一下页面加载过程,就是输入url到加载出页面

​ 1、输入地址

​ 2、浏览器根据请求的url进行DNS域名解析,查找到真实的IP地址,再向服务器发送请求(TCP三次握手);

​ 3、服务器接收到请求交给后台处理再返回数据,客户端接收文件(HTML、JS、CSS、图象等);

​ 4、浏览器对加载的资源文件进行语法解析,建立相应的内部数据结构(如HTML的DOM);

​ 5、载入解析到的资源文件,渲染页面,完成。

TCP/IP连接过程

三次握手

​ 1.客户端先发送一个带SYN的数据包给服务器,想要连接。

​ 2.服务器端发送一个带SYN和ACK的数据包给客户端,表示接受了你的请求,同意连接

​ 3.客户端发送一个带ACK标志的数据包给服务端,表示收到并且连接

四次挥手

​ 1.客户端发送一个请求给服务端,表示我要断开连接(客户端到服务端)。

​ 2.服务端回复一个请求给客户端,表示我收到了。

​ 3.服务端回复给客户端,表示我要断开连接咯(服务端到客户端)。

​ 4.客户端收到回复,断开连接并且发送反馈信息(嗯,可以断开)给服务器,服务器收到并且断开连接

HTTP状态码

关于HTTP状态码应该有下面的基本认识:

  • 1xx :1开头的状态码表示临时的响应
  • 2xx :请求成功
  • 3xx :请求被重定向
  • 4xx :请求错误,表明客户端发送的请求有问题
  • 5xx :服务器错误,表明服务端在处理请求时发生了错误

再说几个常用的http状态码:

  • 301 : Moved Permanently 客户端请求的文档在其他地方,新的URL在location头中给出
  • 304 : Not Modified 客户端发出了一个条件性的请求已被允许(一般是提供If-Modified-Since头表示客户端只想到指定日期后再更新文档)而文档的内容(自上次访问以来或者根据请求的条件)并没有改变。服务器告诉客户,原来缓存的文档还可以继续使用。
  • 400 : Bad Request 请求出现语法错误
  • 401 : Unauthorized 访问被拒绝,客户端试图胃镜授权访问受密码保护的页面
  • 403 : Forbidden 资源不可用。服务器理解客户的请求,但拒绝处理它。通常由于服务器文件或目录的权限设置导致。
  • 404 : Not Found 无法找到指定位置的资源。
  • 405 : Method Not Allowed 请求方法(GET、POST、PUT等)对指定的资源不适用,用来访问本资源的HTTP方法不被允许。
  • 500 : Internal Server Error 服务器遇到了意料之外的情况,不能完成客户端的请求。
  • 502 : Bad Gateway 服务器作为网管或者代理时收到了无效的响应。
  • 503 : Service Unavailable 服务不可用,服务器由于维护或者负载过中未能应答。
  • 504 : Gateway Timeout 网关超时, 作为代理或网关的服务器不能及时的应答。

get和post方法的区别

GET:一般用于信息获取,使用URL传递参数,对所发送信息的数量也有限制,一般在1024字节,Get是通过地址栏来传值。

POST:一般用于修改服务器上的资源,对所发送的信息没有限制。(常用于发送表单数据,新建、修改等),Post是通过提交表单来传值。

进程和线程的区别

cookie,localStorage和SessionStorage的区别

存储时效来说:

  • cookie可以手动设置失效期,默认为会话级
  • sessionStorage的存储时长是会话级
  • localStorage的存储时长是永久,除非用户手动利用浏览器的工具删除

访问的局限性:

  • cookie可以设置路径path,所有他要比另外两个多了一层访问限制
  • localStorage和sessionStorage的访问限制是文档源级别,即协议、主机名和端口
  • 还要注意的是,cookie可以通过设置domain属性值,可以不同二级域名下共享cookie,而Storage不可以,比如http://image.baidu.com的cookie http://map.baidu.com是可以访问的,前提是Cookie的domain设置为”.http://baidu.com“,而Storage是不可以的(这个很容易实验,就不细说了)

存储大小限制:

  • cookie适合存储少量数据,他的大小限制是个数进行限制,每个浏览器的限制数量不同
  • Storage的可以存储数据的量较大,此外他是通过占用空间大小来做限制的,每个浏览器的实现也是不同的,大家可以看这篇文章来进一进步了解Web Storage Support Test

操作方法:

  • cookie是作为document的属性存在,并没有提供标准的方法来直接操作cookie
  • Storage提供了setItem()和getItem()还有removeItem()方法,操作方便不易出错

websocket

webSocket和http一样,同属于应用层协议。它最重要的用途是实现了客户端与服务端之间的全双工通信,当服务端数据变化时,可以第一时间通知到客户端。

除此之外,它与http协议不同的地方还有:

  • http只能由客户端发起,而webSocket是双向的。
  • webSocket传输的数据包相对于http而言很小,很适合移动端使用
  • 没有同源限制,可以跨域共享资源

前端性能优化

  • 网页内容

    • 减少 http请求次数
    • 减少 DNS查询次数
    • 避免页面跳转
    • 缓存 Ajax
    • 延迟加载
    • 提前加载
    • 减少 DOM元素数量
    • 避免 404
  • 服务器

    • 使用CDN(内容分发网络)
    • 添加Expires或Cache-Control报文头
    • Gzip压缩传输文件
  • CSS

    • 将样式表置顶
    • JavaScript
  • 把脚本置于页面底部

  • 使用外部JavaScript和CSS

  • 精简JavaScript和CSS

  • 去除重复脚本

  • 减少DOM访问

  • 图片

    • 优化图像
    • 优化CSS Spirite
    • 不要在HTML中缩放图片
    • favicon.ico要小而且可缓存
    • 降低图片大小
    • 采用适当的图片宽度尺寸(响应式图片)
    • 采用雪碧图(CSS Spirite)
    • 采用字体图库代替图标(比如iconfont)
    • 图片素材太多,可以使用图片懒加载
    • 图片转化成base64位

算法

数组去重

1
2
3
4
5
6
7
8
9
10
11
12
13
//es5
function uinque(arr){
var obj = {},newArr = [];
arr.forEach((item) => {
if(!obj[item]){
obj[item] = true;
newArr.push(item);
}
})
return newArr;
}
//es6
[...new Set(arr)]

获取[n,m]的随机数

1
2
3
4
5
6
7
8
function getRandom(min,max){
//parseInt(Math.random()*(max-min+1)+min,10)
return Math.floor(Math.random()*(max-min+1)+min);
}

//Math.random()是返回一个[0,1)之间的数字,返回的整数只有一个为0
//Math.floor()对数进行向下取整
//Math.round()对数进行四舍五入

框架类

vue

  • vue的特性

  • vue的函数

  • vue的生命周期

    总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。

    创建前/后: 在beforeCreated阶段,vue实例的挂载元素$el和数据对象data都为undefined,还未初始化。在created阶段,vue实例的数据对象data有了,$el还没有。

    载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。

    更新前/后:当data变化时,会触发beforeUpdate和updated方法。

    销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在

  • vue的数据双向绑定的原理

    vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

    具体步骤:

    第一步:需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化

    第二步:compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图

    第三步:Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:

    1、在自身实例化时往属性订阅器(dep)里面添加自己

    2、自身必须有一个update()方法

    3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。

    第四步:MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。


本文由 Abert 创作,采用 知识共享署名 4.0 国际许可协议。

本站文章除注明转载/出处外,均为本站原创或翻译,转载请务必署名。