面试题

2021-02-28  本文已影响0人  allen_tian

一、HTML 押题

1.(必考) 你是如何理解 HTML 语义化的?

第一种举例:段落用 p,边栏用 aside,主要内容用 main 标签
第二种:最开始是 PHP 后端写 HTML,不会 CSS,于是就用 table 来布局。table 使用展示表格的。严重违反了 HTML 语义化。后来有了专门的写 CSS 的前端,他们会使用 DIV + CSS 布局,主要是用 float 和绝对定位布局。稍微符合了 HTML 语义化。再后来,前端专业化,知道 HTML 的各个标签的用法,于是会使用恰当的标签来展示内容,而不是傻傻的全用 div,会尽量使用 h1、ul、p、main、header 、button等标签语义化的好处是已读、有利于SEO(搜索引擎优化)等。
HTML5新增的语义化标签
<header>头部标签
<nav>导航标签
<article>内容标签
<section>块级标签
<aside>侧边栏标签
<footer>尾部标签

二、CSS

1.(必考) 说说盒模型。(描述下盒模型)

盒模型的概念:盒模型是css布局的基石,它规定了网页如何显示,以及元素和元素之间的相互关系,css定义了所有元素都可以拥有盒子一样的外形和平面空间,即包含内容区、填充区、边框、外边距
举例:
W3C的标准盒模型:content-box: width == 内容区宽度
IE的怪异盒模型:border-box: width == 内容区宽度 + padding 宽度 + border 宽度
盒模型又称框模型(Box Model),包含了元素内容(content)、内边距(padding)、边框(border)、外边距(margin)几个要素


image.png

2.css reset 和 normalize.css 有什么区别?

考英文:
reset 重置,之前的样式我不要,a{color: red;},抛弃默认样式
normalize 让所有浏览器的标签都跟标准规定的默认样式一致,各浏览器上的标签默认样式基本统一。

3.(必考)如何居中?

4.CSS优先级怎么确定?

选择器越具体,优先级越高。 #xxx 大于 .yyy
同样优先级,写在后面的覆盖前面的。
color: red !important; 优先级最高。

4.BFC是什么

block formatting context 直译为块级格式化上下文 ,它是一个独立的渲染区域,并且这个区域与外部毫不相干。
规则:
1.内部box会垂直放置;
2.同一个bfc的box的margin会重叠;
3.bfc不会和float盒子重叠;
4.bfc在页面上是隔绝的独立容器,bfc里的子元素不会影响到外面的子元素;
5.计算bfc高度的时候,浮动元素也参与计算;
如何创建bfc:
float 不是none;position 的值不是static和re'lative;display的值是inline-block、table-cell、flex、inline-flex;
BFC能解决什么问题:
解决margin重叠的问题,设置其中一个为bfc(overflow:hidden);
解决自适应两栏问题,左边浮动,右边变为bfc(overflow:hidden);
清除浮动,子元素浮动,父元素坍陷的问题,给父元素清楚浮动设置为bfc。

三、js

1.js有哪些数据类型

string、undefined、null、number、symbol、bool、object
5个falsy值
undefined, null ,0 ,NaN ,'' ''
==和===
==会做数据类型转换
”1“==true,==会把”1”变为1,true变为1,所以返回true
"1" ===true,===严格比较,左边是字符串,右边bool,所以返回false

2.promise

https://www.liaoxuefeng.com/wiki/1022910821149312/1023024413276544
Promise 是异步编程的一种解决方案,有了Promise对象,就可以将异步操作以同步操作的流程表达出来,可以避免出现异步操作层层嵌套的回调函数。
promise好处:执行请求代码和结果处理代码清晰分离;可以串行执行异步任务;

1、对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
2、一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。

Promise也有一些缺点。

首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。
其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
手写promise:
function xxx(){
return new Promise(function(resolve,reject){
setTimeout(()=>{
resolves/reject
},3000)
})
}
xxx().then(resolve,reject);

3.手写ajax

let xhr = new XMLHttpRequest()
xhr.open("POST","/XXXX);
xhr.onreadystatechange=function(){
if(xhr.readyState ===4 &&xhr.status ===200){
console.log(xhr.responseText)
}
};
xhr.send();
xhr.readyState用来获取ajax状态码,共有5个
xhr.readyState为0 请求未初始化,未调用 open()
xhr.readyState为1 请求已建立,但还未发送请求(未调用 send)
xhr.readyState为2 已发送请求(已调用 send)
xhr.readyState为3 请求正在处理,响应中已有部分数据可以用了
xhr.readyState为4 请求已完成,可以获取服务器的响应

4.闭包

闭包是指有权访问另一个函数作用域里变量的函数
在一个立即执行函数里,有一个变量a和一个函数b,函数b能访问外部的a,那么a和函数b构成一个闭包,闭包的作用是间接访问一个变量;
function () {
let a = 0;
function b(){
a+=1;
}
}

5.this的理解

call(),apply(),bind()
this并不是指向函数本身,也不是指向函数作用域,它是在运行的时候绑定,它的指向完全取决于哪里被调用,也就是说谁调用,谁负责;
而bind()、call()、apply(),这三个方法则是可以改变this指向的方法;
函数调用fn(xx,xx) ==fn.call(undefined,xx,xx),this就是call方式的第一个参数,这样情况fn()的this就是windows;strict mode严格模式来说
,this就是undefined;a.fn() 这个情况下的this是a ;还有一些new f(),那么this就是new后的实例;箭头函数的this和箭头函数外的this相同;

fn() 里面的 this 就是 window
fn() 是 strict mode,this 就是 undefined
a.b.c.fn() 里面的 this 就是
new F() 里面的 this 就是新生成的实例
() => console.log(this) 里面 this 跟外面的 this 的值一模一样

6.(必考)什么是立即执行函数?使用立即执行函数的目的是什么?

立即执行函数是一个作用域,用来防止污染全局变量;
ES6里{
let a = 0
}

7.async/await 语法了解吗?目的是什么?

有个promise方法,在调用时可用async/await,目的是让异步代码变成同步代码,等到调用promise结束后有返回才执行后面的语句

8.如何实现深拷贝?

有两种方法
第一种用JSON.parse()
let b = JSON.parse(JSON.stringify(a));a不是能函数、正则、undefined、日期等
第二种是递归
不是很懂

8.1 深拷贝和浅拷贝的区别

浅拷贝是增加一个指针指向已经存在的地址;
深拷贝是增加一个指针并开辟一个内存,新增的指针指向新内存;

8.2 typeof 和 instanceof 的区别

typeof返回的是string类型的名称,instanceof是返回bool,true/false
typeof(a)=数据类型,array, object,null,都是返回object;
instanceof
循环引用

9.数组去重

includes 判断数组里是否有这个值,有为true,没有为false;
let a = [1,2,3,4,1,2,3,5]
let b = []
let c = a.forEach(item => {
if (!b.includes(item)) {
b.push(item)
}
})
console.log(b)
console.log(c)
let d = a.map((item, index) => {
if (a.indexOf(item) === index) {
b.push(item)
}
})
console.log(b)
let e = Array.from(new Set(a))
console.log(e)

10.js原型是什么

数组a=[1,2,3] 的key 1,2,3,length 四个
a数组同时拥有push(),join()等方法,这些方法是在——proto__里,——proto_=== Array.prototype, a的原型Array.prototype;原型就是类型所共有的一些属性和方法。

11.ES6中的原型链

举例 let a = ["1","2"],a控制台输出的时候除了有它本身值以外还有length,还有——proto-,a数组有的push,join方法都是在——proto里,--proto--是继承了Arrayproto的属性,arrayproto它自己也会有--proto--,他的--proto--的属性是objectproto。这一条属性的指向就是原型链。

12.节流和防抖

防抖:任务频繁的被触发的情况下,当触发的时间超过设定的时间时,任务才会被执行。
应用场景:避免重复提交(登录、支付)

节流:指定时间间隔内只会执行一次任务
应用场景:window.resize和scroll事件

13.js事件循环机制

js是单线程的,没有事件循环机制会造成阻塞。
js在解析时,同步代码会放到执行栈中,异步代码会放到任务队列中,解析完后会执行执行栈中的代码,执行栈中的代码执行完后,会扫描任务队列,如果任务队列里有异步代码,把异步代码放到执行栈中执行,执行完毕后再扫描任务队列,循环反复,这就是js的事件循环。
异步任务又分为宏任务和微任务,微任务优先于宏任务执行
宏任务:setTimeout、setInterval
微任务:Promise.then

14.常用的es6语法有哪些

let const 箭头 函数 展开操作符... 对象数组解构 import export

15.vue和react优缺点

相同点:
都有虚拟DOM
都有组件化思想
都推崇单向数据流
都有成熟社区,都是服务端渲染
虚拟DOM+diff算法
vue react通用流程:vue template react jsx——render函数——生成Vnode——UI发生变化,生成新的Vnode和缓存旧的Vnode进行对比——再使用diff算法去更新真实的DOM
不同点:
核心思想不一样:vue渐进式开发,灵活易用,数据可变,双向数据绑定;react推崇函数式编程,纯组件,数据不可变及单向数据流。
写法不同:vue推崇template,react推崇jsx(js的语法扩展,像是一种模板语言)。
api不同、社区差异:vue的api和概念较多;react的api非常少,知道setState就能开发,react核心就是虚拟Dom和diff算法。
https://juejin.cn/post/6844904158093377549

16.ES6 模块与 CommonJS 模块的差异

ES6实现了模块功能,它的模块功能是通过import和export实现的,import用于引入其他模块提供的功能,export是输出模块对外接口
区别:
1.commonJs输出的是一个值的拷贝,ES6输出的是值的引用
2.commonjs模块是运行时加载,ES6是编辑时输出接口(编译时加载)
commonjs模块是个对象,输入时加载这个模块时需要先生成一个对象,然后从这个对象里读取方法,这种方式叫运行时加载。
ES6模块不是对象,通过export输出显示某段代码,import是指定加载某个输出值,不是加载整个模块,这种方式是编译时加载。

17.MVVM的原理

双向数据绑定就是Mvvm,数据层model-视图层view-数据视图层viewmodel
1.修改View层,Model对应数据发生变化。
2.Model数据变化,不需要查找DOM,直接更新View。

18.var let const区别

let const 是ES6的语法,var有变量提升,let const没有变量提升,const 赋值的是简单类型不能更改,const 如果是赋值复杂类型(对象、数组)则对象数组的属性和属性值能更改,let赋值后可以更改,let不可以重复定义,const和let定义的变量不会挂到window下,var定义的变量会挂到window下。

19.数组的相关操作

let a = [1,2]
数组的遍历

1.forEach. forEach能遍历所有项,forEach没有返回值

a.forEach(function(value,index){
console.log(value+ '/' + index);
})

2.map

image.png

3.for for只能遍历数组的下标为数字的项

for(var i = 0; i < arr.length;i++){
console.log(arr[i]);
}

4.for in for..in..推荐遍历对象,因为循环出来的是key,ES5的标准

image.png

5.for of 推荐遍历数组,因为循环出来的vaule,ES6的标准,存在兼容问题,不能遍历普通对象,需要和Object.keys() 搭配使用

image.png

Object.keys(),只取key


image.png

6.some() 判断数组里有没有某一项,只要数组中有一项在callback上就返回true

image.png

7.find()

image.png

8.filter()

image.png

9.includes()

判断某个值在不在数组里,如果在返回true,不在返回false

10.indexOf()返回值第一次出现的下标位置

image.png

11.

2、sort:排序方法

var arr = [1,2,3,4]
arr.sort()//不传参数,默认从小到大排序
arr.sort(function(x,y){ return x-y})

3、join:连接数组的每个元素

var arr = [1,2,3,4]
arr.join()//不传参数默认使用,连接,等同于 arr+'' ,其实是arr调用了toString()

4、concat: 连接数组

var arr = [1,2,3,4]
var b = ['a','b','c']
arr.concat(b)

18.怎么判断是数组

1、a instanceof Array
2、Array.isArray(a)
3、a.proto === Array.prototype

19.es5与es6继承区别

ES5和ES6的区别
ES5的继承,实质是先创建子类的this,再把父类的函数和属性给到子类的this(parent.apply(this));
ES6的继承,实质是先把父类的方法和属性给到this, 然后在子类的构造函数里去调用super()方法,这样才能去用this.

20.伪数组有哪些,怎么让伪数组变为数组?

伪数组有:
arguments(是所有函数(除箭头函数)都可以用的局部变量,可以使用arguments对象在函数中引入函数的参数)、
通过document.getElements..获取到的内容(获取元素标签集合)

ES5方法
Array.prototype.slice.call(arguments)
[].slice.call(arguments),这两个方法相等,slice()方法是可以从已有的数组中返回指定的参数,call这个方法是把this指向改为传进去arguments
ES6方法
Array.from(arguments);

21.call(),apply(),bind()

bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用
this并不是指向函数本身,也不是指向函数作用域,它是在运行的时候绑定,它的指向完全取决于哪里被调用,也就是说谁调用,谁负责;
而bind()、call()、apply(),这三个方法则是可以改变this指向的方法;

四、DOM押

1.DOM事件模型

捕获阶段:从外部到内部;目标阶段;冒泡阶段:从内部到外部


image.png

2.事件委托

父元素下有4个子元素,监听父元素,看触发的是那个子元素,这就是事件委托,事件委托还可以监听没有生成的子元素。
事件委托的优点是省监听器,省内存。
代码没看懂:
function listen(element, eventType, selector, fn) {
element.addEventListener(eventType, e => {
let el = e.target
while (!el.matches(selector)) {
if (element === el) {
el = null
break
}
el = el.parentNode
}
el && fn.call(el, e, el)
})
return element
} // 工资 12k+ 的前端写的事件委托
listen(ul, 'click', 'li', ()=>{})
ul>li*5>span

五、HTTP

1.状态码有哪些?

200-请求成功
301-请求重定向 永久重定向
302-临时重定向
404-请求的资源不存在
500-内部服务器错误

2.HTTP缓存

强制缓存:如果缓存里有资源,浏览器直接从缓存中取,如果没有则重新请求资源,cache-control:max-age:seconds
协商缓存:服务端对比客户端给的缓存数据标识和现在的资源数据标识进行对比,如果相同则不给资源,如果不同则返回资源。

Cache-control:max-age=<seconds>表示资源能够被缓存(保持新鲜)的最大时间,在这个时间内不会发请求要资源,当事件过了的时候重新发请求要资源。
ETag:服务端会将客户端的etag和当前版本的etag做对比,如果是一致的则不需要重新请求,返回不带资源的304,表示客户端缓存可用;如果是不一致,重新请求资源;

3.Cookie 是什么?Session 是什么?

HTTP响应通过set-cookie设置cookie
cookie存在浏览器端
coookie用来存储用户数据
session在服务端
session一般通过在cookie里存sessionID实现
sessionID是随机数

4.LocalStorage和cookie的区别?

LocalStorage不会随着cookie发送到服务端
LocalStorage 和sessionStorage的区别
都是用来存储客户临时信息对象的,都是只能存字符串
类型。
LocalStorage存储的信息是永久的,除非用户手动清楚
sessionStorage一旦窗口和标签被关闭了,通过sessionStorage存储的信息都会被清空。

5.get和post区别

get:请求体在url后
post:请求体通过body传
post比get安全,但实际两个都不安全;
get参数有长度限制1024个字符,post参数没有长度限制(10mb)
get请求只需要发一个包,post请求需要发2个以上的包
get用来读数据,post用来写数据

6.跨域是什么,jsonp是什么?

当一个请求url的协议、域名、端口三者之间的任何一个和当前页面的url不一样即为跨域
可用postMessage()对不同网页传递信息、页面和iframe传递信息
jsonp是通过script标签里的src属性来实现跨域的,通过将前端方法作为参数传给服务端,然后由服务端注入参数再返回,所以只支持get请求不支持post请求。
可用jsonp,jsonp是服务端和客户端跨源通信的常用方法,只支持get,部支持post

7.从输入URL到页面展示发生了什么?

DNS解析:域名解析为IP
TCP连接(三次握手)
发送http请求
后台处理请求
http响应
下载CSS
解析CSS
下载JS
解析JS
下载图片
解析图片
渲染DOM结构
执行js

(1)缓存取
(2)DNS:
本地hosts-本地DNS服务(中国移动)-根DNS服务-域服务器-域解析服务器-返回域名和id的对应关系;
(3)TCP链接,三次握手(。主要目的防止server端一直等待,浪费资源。)
应用层:HTTP发请求
传输层:TCP发报文(对数据进行分割)
网络层:IP协议和mac地址
链路层:以太网协议,数据分成一帧一帧的形式发送
(4)http向服务端发请求
| 请求方法URI协议/版本
| 请求头(Request Header)
  | 请求正文


image.png

(5)服务端处理请求,反向代理Nginx
(6)服务端返回HTTP响应
HTTP响应与HTTP请求相似,HTTP响应也由3个部分构成,分别是:
l  状态行
l  响应头(Response Header)
l  响应正文


image.png

HTML 解析:
解码:把二进制码通过UTF-8解析为字符串
预解析:提前加载资源
符号化(Tokenization):
符号化是词法分析的过程,将输入解析成符号,HTML 符号包括,开始标签、结束标签、属性名和属性值。
构建树:

CSS 解析:
CSS 匹配规则
其实这就是一个 DOM 树和 CSS 规则树合并的过程。
注意:渲染树会忽略那些不需要渲染的节点,比如设置了display:none的节点。
计算
通过计算让任何尺寸值都减少到三个可能之一:auto、百分比、px,比如把rem转化为px。
级联
浏览器需要一种方法来确定哪些样式才真正需要应用到对应元素,所以它使用一个叫做specificity的公式,这个公式会通过:
标签名、class、id
是否内联样式
!important
然后得出一个权重值,取最高的那个。
渲染阻塞
当遇到一个script标签时,DOM 构建会被暂停,直至脚本完成执行,然后继续构建 DOM 树。
但如果 JS 依赖 CSS 样式,而它还没有被下载和构建时,浏览器就会延迟脚本执行,直至 CSS Rules 被构建。
所有我们知道:
CSS 会阻塞 JS 执行
JS 会阻塞后面的 DOM 解析
为了避免这种情况,应该以下原则:
CSS 资源排在 JavaScript 资源前面
JS 放在 HTML 最底部,也就是 </body>前
另外,如果要改变阻塞模式,可以使用 defer 与 async,

  1. 布局与绘制
  2. 合并渲染层
  3. 回流与重绘

JavaScript 编译执行
词法分析:JS 脚本加载完毕后,会首先进入语法分析阶段,它首先会分析代码块的语法是否正确,不正确则抛出“语法错误”,停止执行
JS 有三种运行环境:
全局环境
函数环境
eval
每进入一个不同的运行环境都会创建一个对应的执行上下文,根据不同的上下文环境,形成一个函数调用栈,栈底永远是全局执行上下文,栈顶则永远是当前执行上下文。
创建执行上下文
创建执行上下文的过程中,主要做了以下三件事:

创建变量对象
参数、函数、变量
建立作用域链
确认当前执行环境是否能访问变量
确定 This 指向
js执行
js事件循环
微任务的执行在宏任务的同步任务之后,在异步任务之前

8.重绘和回流是什么?

回流是指,html的元素增加或者宽高度的改变,这时候页面布局发生了该百年,所以重新渲染DOM结构。
重绘是元素颜色改变,不会改变dom结构。回流一定伴随和重绘

9.优化

1.css放头部,js放尾部,为了尽快构建dom树和cssom树,为了加载js不因找不到dom而报错。
2.设置强制缓存或者是协商缓存,避免相同资源频繁请求
3.js,css,html能压缩就尽量压缩,减小体积,加快下载速度,插件的js,css使用体积小的生产版本。
4.使用webpack打包根据路由进行懒加载,不要初始的时候加载全部,这样文件体积会很大。

前端七大优化
①减少请求数量:合并文件,使用字体图片代替图片,减少重定向,使用缓存,css少使用@import,避免使用空的href和src;
②减小资源大小:压缩css,html,js,图片,使用生产版本的依赖;
③优化网络链接:使用CDN,内容分发网络,它能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的是使用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度;
使用DNS预解析,使用<link rel="dns-prefecth" href="https://www.google.com">对提前解析可能会用到的域名;
④优化资源加载
1、CSS文件放在head中,先外链,后本页
2、JS文件放在body底部,先外链,后本页
3、处理页面、处理页面布局的JS文件放在head中,如babel-polyfill.js文件、flexible.js文件
4、body中间尽量不写style标签和script标签
模块按需加载
资源懒加载和资源预加载
⑤减少重绘回流
class,图片定义大小,不要用table

image.png
⑥webpack优化
动态导入和按需加载
https://www.cnblogs.com/xiaohuochai/p/9178390.html

10.什么是 XSS 攻击?如何预防?

使用html, 在标签<script>里执行js代码
其实归根结底,XSS的攻击方式就是想办法“教唆”用户的浏览器去执行一些这个网页中原本不存在的前端代码。

预防:
不要使用 innerHTML,改成 innerText,script 就会被当成文本,不执行;
如果你一样要用 innerHTML,字符过滤
把 < 替换成 <
把 > 替换成 >
把 & 替换成 &
把 ' 替换成 '
把 ' 替换成 "
代码 div.innerHTML = userComment.replace(/>/g, '<').replace...

11.什么是Csrf

攻击就是在未经你许可的情况下用你的名义发送恶意请求
防御CSRF攻击:
目前防御 CSRF 攻击主要有三种策略:验证 HTTP Referer 字段;在请求地址中添加 token 并验证;在 HTTP 头中自定义属性并验证。
根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,比如需要访问 http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory,用户必须先登陆 bank.example,然后通过点击页面上的按钮来触发转账事件。这时,该转帐请求的 Referer 值就会是转账按钮所在的页面的 URL,通常是以 bank.example 域名开头的地址。而如果黑客要对银行网站实施 CSRF 攻击,他只能在他自己的网站构造请求,当用户通过黑客的网站发送请求到银行时,该请求的 Referer 是指向黑客自己的网站。因此,要防御 CSRF 攻击,银行网站只需要对于每一个转账请求验证其 Referer 值,如果是以 bank.example 开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求。
Referer 的值是由浏览器提供的,就是把安全性都依赖于第三方(即浏览器)来保障;如果设置了要检查referer,如果用户自己设置浏览器访问时不提供
在请求地址中添加 token 并验证
在 HTTP 头中自定义属性并验证

六、react面试题

https://blog.csdn.net/xiaoxinshuaiga/article/details/80766369
https://blog.csdn.net/qq_40055200/article/details/108549121
https://blog.csdn.net/eyeofangel/article/details/88797314

算法押题

排序算法(背诵冒泡排序、选择排序、计数排序、快速排序、插入排序、归并排序)
二分查找法
翻转二叉树

上一篇下一篇

猜你喜欢

热点阅读