面经

面经刷题

洗牌算法

注意分号的使用,当以”(“、”[“、”/“、”+”、”-“为行的开头,可能与前一行形成调用或者元素引用。

1
2
3
4
5
6
7
8
9
arr=[1,2,3,4,5,6]
function myShuffle(arr){
for(let i=arr.length;i;i--){
let j = Math.floor(Math.random()*i);
[arr[i-1],arr[j]]=[arr[j],arr[i-1]];
}
return arr
}
myShuffle(arr)

CSS两列布局

将content右栏margin-left,main主栏float,sidebar定宽并设置float,margin-left;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>

<style>
*{
margin:0;
padding:0
}
.main {
float:left;
width:100%;
}
.main .content{
margin-left:200px;
}
.sidebar{
width:200px;
float:left; // 先设置float布局,下一步margin-left才有效
margin-left:-100%; // 向左移动一个屏幕的距离
}
</style>

</head>
<body>
<div class="main">
<div class="content">
content-right
</div>
</div>
<div class="sidebar">
sidebar-leftsidebar-leftsidebar-left
</div>
</body>
</html>

这他娘的为啥不行!无语

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
*{
margin:0;
padding:0
}
.main {
overflow:hidden;
border: 1px solid red;
}
.content{
background:red;
margin-left:200px;
height: 200px;
}
.sidebar{
float:left;
width:200px;
height: 200px;
background:skyblue;
}

content右栏position:absolute,left:200px

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>

<style>
*{
margin:0;
padding:0
}
.content{
position:absolute;
left:200px;
right:0;
top:0;
}
.sidebar{
width:200px;
}
</style>

</head>
<body>
<div class="content">
content-right
</div>
<div class="sidebar">
sidebar-leftsidebar-leftsidebar-left
</div>
</body>
</html>

flex布局:设置sidebar的order为-1,长度为200px;content右栏flex:1;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>

<style>
*{
margin:0;
padding:0
}
.main{
display:flex;
}
.content{
flex:1; // 我的理解是:在没有其他元素的情况下,flex-grow:1可以霸占剩余区域
}
.sidebar{
flex:0 0 200px;
order:-1;
}
</style>

</head>
<body>
<div class="main">
<div class="content">
content-right
</div>
<div class="sidebar">
sidebar-leftsidebar-leftsidebar-left
</div>
</div>
</body>
</html>

浏览器渲染过程

参考链接

  1. 解析HTML文档->DOM树;(JS脚本的加载会阻塞DOM树的生成)
  2. 解析CSS规则->CSSOM树;(会阻塞涉及CSS的JS脚本与对应DOM树的构建)
    CSS解析与DOM解析可同时进行;
  3. 构建渲染树:遍历DOM树,对每个节点查找对应的CSS规则(去除display:none,script,meta,link;visibility或opacity隐藏的节点依然存在)
  4. 回流:(布局)在设备视口确切位置与尺寸大小;
  5. 绘制:将可见节点转换为屏幕的具体像素,绘制在浏览器上。

触发:

  1. 开始渲染;
  2. 浏览器窗口变化;
  3. DOM元素添加或删除;
  4. 元素尺寸大小,位置;
  5. 元素内部内容改变;
  6. style属性改变。

如何优化:

  1. css样式改变最小化;
  2. 动画元素脱离文档流;
  3. 先在脱离文档流的情况下构建好,再插入到主文档中:
    (display:none/fragment构建子树/拷贝到脱离文档的节点中)
  4. 避免触发同步布局事件;
  5. css3硬件加速(GPU加速)。

typeOf的返回值

undefined,string,number,boolen,function,object(null,array);
基本类型:string number boolen null undefined;
引用类型:function object array data regexp;

BFC

参考链接
块级格式化上下文:盒子模型,独立的块,包含内部所有元素,除了被包含在新BFC下的元素;隔离的独立容器,不受外部元素的影响,内部也不会影响到外部元素。
特性:
在垂直方向上一个接一个放置;
属于一个BFC的相邻margin会重叠(防止外边距合并)
不与外部float box重叠(自适应两栏);
计算内部float box的高度(清除浮动)
产生方法:
float不为none;
position:absolute,fixed;
display:inline-block,table-cell,flex,table-caption,inline-flex;
overflow不为visible;

观察者模式与发布-订阅模式

参考链接
相同点:Observer订阅,Subject接受事件,以及notify通知观察者;
不同,
观察者模式同步,发布者与订阅者直接连接,单个应用程序空间中实现;
发布-订阅模式异步,中间有消息代理进行通信,松散耦合,交叉应用模式。

函数运算符优先级等综合练习

参考链接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Foo() {
getName = function () { alert (1); };
return this;
}
Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
var getName = function () { alert (4);};
function getName() { alert (5);}

//请写出以下输出结果:
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();

Foo.getName() // 2

  1. 静态属性与静态方法在没有初始化实例时就能访问;
  2. 要调用公有属性、公有方法,必须new;公有方法不能调用私有属性与方法;
  3. 外部不可调用私有属性和方法。

getName() // 4

函数声明发生变量提升,被同名函数表达式覆盖;

Foo.getName() // 1

Foo()函数执行返回window全局对象,其中getName覆盖函数;

getName() // 1

全局对象的getName()函数;

new Foo.getName() // 2

运算符优先级:.=new有参>new无参>函数调用
所以

  1. 先Foo.getName得到静态方法;
  2. 再new得到该方法的实例;
  3. 最后调用。

new Foo().getName() // 3

  1. 先new有参,初始化Foo实例(实例返回引用类型this,则为实例对象);
  2. .操作符,获得函数getName(沿原型链);
  3. 执行函数;

new new Foo().getName() // 3

  1. 先new有参(第2个new),初始化Foo实例;
  2. .操作符,获得函数getName(沿原型链);
  3. new无参(第1个new),得到该方法实例;
  4. 最后调用。

什么是闭包?优缺点?

定义

匿名函数引用了它的包含函数内的变量,该函数在外部被调用时,产生了闭包,可以使用包含函数的变量,使其可以常驻内存,不随函数销毁而销毁。

优点

  1. 变量长期驻扎在内存中;
  2. 私有成员避免污染全局变量;

    缺点

  3. 变量占用内存,导致性能下降;循环引用Html元素会内存泄漏;
  4. 闭包是操作包含函数变量的共有方法,不能随意改变该变量值;

三次握手 四次挥手

参考链接

进程与线程

  1. 进程表示资源调度的基本单位,线程是CPU调度的最小单位;
  2. 进程内即同一进程的线程数据共享,而不同进程之间数据不共享;
  3. 进程表示程序进入到CPU后:获取程序上下文+CPU执行+保存程序上下文的过程;
  4. 线程则是在CPU执行过程中,分为不同的块;
  5. 进程消耗较大的计算机资源;
  6. 进程:互斥锁、信号量;

promise

参考链接
状态仅由异步操作的结果决定resolve/reject 不可更改 可实现回调链
用维护状态、传递状态的方式使回调函数能及时调用
简单、灵活
then catch Promise.all Promise.race

箭头函数

简化了函数定义,相当于匿名函数;
不同的是匿名函数的this为windows或为undefined,
而这个this按照词法作用域绑定了,即指向外层调用者。

generator生成器

参考链接
特性:function与函数名之间又一个*号,函数内部yield表达式;
功能:自动生成并返回迭代器,调用next方法开始运行,移动迭代器指针,直到移到函数末尾,返回undefined。
如果给next传参数,那么该参数作为上一个yield语句的返回值;
注:为异步操作。

vue双向数据绑定

  1. 遍历data对象;
  2. 添加Observer对象:Object.defineProperty()数据劫持————getter、setter;
    getter中初始化Watcher,用于依赖收集Dep;setter触发数据变更事件notify通知Watcher,用于派发更新;

    手写一个单例模式

    直接执行函数,闭包封装instance

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    var A;
    (function(name){
    var instance;
    A=function(name){
    if(instance){
    return instance;
    }
    instance=this
    this.name=name
    }
    }());
    var a=new A();
    var b=new A(); // a===b

变量提升

var,let,function都会发生变量提升;
var:变量声明首先进入内存,相当于提升到了当前作用域顶部,但是没有初始化和赋值;
可以在还没有声明赋值时调用该变量,值为undefined;
let:也存在变量声明,不同的是出现暂时性死区,在赋值之前不允许该值调用;
function:变量提升,同时函数赋值也放到了顶部。

JS事件循环

JavaScipt是单线程的;
同步任务:在执行栈中按顺序执行,后面的任务必须等待前面任务执行完成;
异步任务:挂载出来的任务,不会进入主线程,而进入任务队列;当异步任务完成,则在任务队列中增加进入标志,主线程可在同步任务执行完成后,读取该任务到执行栈中,执行回调函数;

settimeout异步任务,在经过等待的时间后,才有可能被读取到执行栈中,或者是继续等待执行栈中同步任务与任务队列前面的异步任务执行结束。

node.js事件循环

nextTick:在读取任务队列前进行,即在所有异步任务之前;
setImediate:在下一个eventloop时执行,即所有异步任务之后。

原型链

所有的构造函数都有存在一个原型对象,prototype指针指向该原型对象;
由该函数构造的实例都可继承原型对象,__proto__指向;
该原型对象存在constructor属性指回构造函数。
原型链即原型对象为另外一个对象的实例,构成原型链条;
当读取当前实例属性或方法时,从实例,到原型,再由下至上去父类的原型中找,最终到Object的原型;
因为所有函数都由Object继承而来,原型链的最顶部是Object的原型。

es6

键头函数的this指向和普通函数的区别

Vue Router生命周期

网页的优化

怎么判断数组

webpack原理?有没有自己配过

项目整理

统一入口平台

如何部署项目pm2

带有负载均衡功能的Node应用的进程管理器,避免多个终端同时开启,并且可以实现进程永远活着。

1
2
3
4
npm run pm2 // npm启动pm2
pm2 deploy deploy.yaml production setup // 首次部署项目
pm2 start 项目启动文件 --name myname//启动node项目
pm2 list // 列出pm2管理的所有进程信息

权限多选树

el-tree组件的改进;封装新el-tree与el-select,得到mutil-select-tree;
为实现调用该多选树的父组件与相应子组件的通信:
父->子传递数据:
父组件在引用时,设置组件属性:data=xxx;子组件中设置props-data 同名属性;
(加冒号表示属性为变量或表达式)
子->父传递数据:
子组件定义事件childevent:emit(“eventname”,事件中携带的数据);子组件绑定方法@click=’childevent’;父组件在引用子组件时定义@childevent,并编写相应的取数据代码。
组件间调用方法:设置refs。

传片系统

路由懒加载

异步组件:将代码分段,防止打包文件过大;使用工厂函数引入全局/局部组件,当需要该组件时,才调用工厂函数,执行异步解析组件,并保存供未来渲染。

vuex

定义:状态管理模式,集中式存储管理应用的所有组件的状态,并保证状态以一种可预测的方式发生变化;
解决问题:多个视图依赖同一状态,不同视图需要对同一状态进行操作;
state:在计算属性中获得状态:this.$store.state.count/…mapState({});
getter:认为是store的计算属性,根据依赖值缓存,对state进行过滤等操作;
使用方法:this.$store.getters.doneTodosCount/this.$store.getters.getTodoById(2)/…mapGetters([]);
mutation:更改状态的唯一方式是提交mutation,同步操作,事件类型+回调函数;
触发:store.commit({
type: ‘increment’,
amount: 10
}) /
…mapMutations([])
action:提交mutation,可以包含任意异步操作;
触发:store.dispatch(‘increment’)/…mapActions([])

页面权限控制

钩子函数,在每一个路由变化中,判断是否存在token;
true:不为登录页则获取当前用户信息;
false:不在白名单中则跳转回登录页;
router.beforeEach(async(to,from,next))

vue生命周期钩子函数

beforeCreated created beforeMounted mounted beforeUpdated updated beforeDestoryed destroyed
created创建实例,获取data属性;(在这里执行DOM操作时一定要放在Vue.nextTick()回调函数中;
mounted渲染DOM,获取el属性。

vue-router钩子函数

全局:beforeEach,afterEach;
路由:beforeEnter,afterEnter;
组件:beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave.

nextTick

原理:Vue异步执行DOM更新,当数据改变时,Vue开启队列,存放与该事件循环相关的数据改变;
当下一次事件循环tick中,再清空该队列,并且执行相关操作。
使用情况:created中涉及DOM操作;在数据变化后中需要进行涉及随数据改变的DOM的操作;

AJAX

通过少量数据交换,实现页面部分的异步更新;
vue.js 2.0 推荐使用axios;
基本使用方法:axios.post(url,{}).then().catch();
请求配置项:url,method,baseURL,headers,params,data,timeout,responseType;
响应信息:data,status,statusText,headers,config;
可设置拦截器:axios.interceptors.request.use();
可默认设置配置:axios.default.baseURL;

http头部信息

请求:
User-Agent浏览器信息;
Accept:接受的数据格式;
Content-Type:服务器文件类型;
connection:连接形式:保持连接keep-alive/关闭close;
Authorization:客户端回应身份验证信息;
If-None-Match:对应Etag,判断上次的资源标志是否有更改;
If-Modified-Since:对应Last-Modified,判断上次的更改时间后是否有更改;
响应:
status:服务器处理结果;
Expires:实体过期时间;
Cache-Control:告诉客户端缓存规则;
Last-Modified:最近一次修改时间;
Etag:资源标志;
Age:距离上次缓存没更新的时间;

vue-cli脚手架快速搭建项目

可自动生成vue项目,webpack打包;

vue全家桶

vue-cli+vue-router+vuex+ElementUI

chart组件式开发

定义子组件并引出

export default{
name:…,
props:{ // 自定义图表组件传递属性给echart:
className:{
type:String,
default:’…’
}
}
data(){
return {

    }
}
methods:{

}

}

父组件中引入子组件

import
再引出给别的组件作子组件
要设置:components:{children}
页面中使用```

chart resize防抖

mounted阶段:

1
2
3
4
5
6
this.__resizeHandler = debounce(() => { // 防抖
if (this.chart) {
this.chart.resize()
}
}, 100)
window.addEventListener('resize', this.__resizeHandler) // 添加事件监听

beforeDestory:

1
2
3
4
5
6
if (!this.chart) {
return
}
window.removeEventListener('resize', this.__resizeHandler) // 移除事件监听
this.chart.dispose()
this.chart = null

el-tabs 选项卡切换

1
2
3
4
5
6
7
8
 <el-tabs v-model="activeName" type="card" @tab-click="handleClick">
<el-tab-pane v-for="item in tabMapOptions" :key="item.key" :label="item.label" :name="item.key">
<keep-alive>
<tab-pane v-if="item.key==='yes'" />
<tann-pane v-if="item.key==='no'" />
</keep-alive>
</el-tab-pane>
</el-tabs>

tab-pane与tann-pane为子组件,以v-if判断item.key,显示对应的界面。
keep-alive 对经常使用的界面保存组件状态,直接从缓存中读取,避免重复渲染。

SCSS

CSS预处理器,先有SASS,后有SCSS;
分段加载scss文件,将其组合为完整的css规则;

  1. $嵌入变量,#{}嵌入字符串;
  2. &表示父选择器;
  3. 可嵌套;
  4. 引入:@import …;
  5. mixin声明需要复用的CSS声明,include调用该片段:@mixin @include;
  6. 继承:%style @extend
  7. 可用操作符计算样式;
  8. 命名空间内嵌套属性;
  9. @if @else @for;
  10. 方法定义@function;

服务器读取图片

1
2
3
4
5
6
this.$http.get('http://localhost:8088/project/image/byname/' + this.piclocal,
{ responseType: 'arraybuffer' }).then(response => {
const data = response.data
console.log(response)
this.url = 'data:image/png;base64,' + btoa(new Uint8Array(data).reduce((data, byte) => data + String.fromCharCode(byte), ''))
})

后台将byte数组传送给前端,前台解析图片在页面上展示:
btoa方法转换base-64编码;
reduce为Array对象的一个方法,接受一个函数作为累加器,数组从左到右开始累加,
reduce(function(total,currentValue,currentIndex,arr),initialValue);

字节面经

css怎么实现动画

  1. animation设置
    animation-duration:动画时间;
    animation-delay:动画延迟播放时间;
    animation-timing-function:速度时间函数linear;
    animation-direction:进行下一个动画方向alternative;
    animation-iteration-count:重复播放次数infinite;
    animation-play-state:动画状态paused|running;
  2. transition设置
    transition: property duration timing-function delay
    在hover上设置变化属性;

css怎么画三角形

1
2
3
4
5
6
7
.triangle {
width:0;
height:0;
border-width:0 50px 100px 50px;
border-color:transparent transparent red transparent;
border-style:solid;
}

css怎么画圆形

1
2
3
4
5
6
.circle {
width:100px;
height:100px;
border-radius:50%;
background:red;
}

css画扇形

利用border 设置radius,其他border颜色设置为transparent,可得出一个90度的扇形;

1
2
3
4
5
6
7
8
9
10
.sector
{
width:0;
height:0;
border-width:50px 50px 50px 50px;
border-color:transparent yellow transparent transparent;
border-style:solid;
border-radius:50%;
transform:rotate(-45deg);
}

画多个角度的
不知道为啥??不行!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.circle {
width:100px;
height:100px;
position:relative:
overflow:hidden;
border-radius:50%;
background:red;
}
.slice
{
position:relative;
transform-origin:0% 100%;
overflow:hidden;
top:0;
right:0;
width:50%;
height:50%;
}
.slice-one
{
background:green;
transform:rotate(30deg) skewY(-30deg);
}

setTimeout setInterval requestAnimationFrame的区别

setTimeout在一段时间过后执行某种操作,setInterval以一定的时间间隔执行某种操作;
setInterval即使执行报错,也会循环执行;
使用上述两个进行动画操作,控制DOM,会有掉帧、抖动的情况,因为JS事件循环机制,操作不一定会在特定时间内执行,还有固定时间的原因;
所以引入requestAnimationFrame,提供动画API;
与setTimeout的几点区别:

  1. JS引擎;GUI引擎,与显示屏刷新频率保持一致;
  2. 页面隐藏或最小化时,在后台执行;屏幕刷新任务停止;
  3. 以固定的时间刷新界面;自动优化。