2018web前端面试题总结

 

web面试题javascript

css面试 css

1、css盒模型
css中的盒子模型包括IE盒子模型和标准的W3C盒子模型。
border-sizing: border-box, inherit, content-box
标准盒子模型: 左右border+左右padding+contentwidth
IE盒子模型border-box: width = content+padding+border 元素指定的任何内边距和边框都将在已设定的宽度和高度内进行绘制
inherit: 从父类继承box-sizing的值html

2、前端一像素问题(画一条0.5px的线)
* transform: scaleY(0.5) 使用伪元素设置1px的边框,而后对边框进行缩放(s
caleY)
 实现思路:
一、设定目标元素的参考位置
二、给目标元素添加一个伪元素before或者after,并设置绝对定位
三、给伪元素添加1px的边框
四、用box-sizing: border-box 属性把边框都包进宽和高里面
五、宽和高设置为 200%
六、整个盒子模型缩小为0.5
七、调整盒子模型的位置,以左上角为基准 transform-origin: 0 0;
代码以下:
#box{position:relative;}
#box::after{
content:'';box-sizing:border-box;
position:absolute;top:0;left:0;
width:200%;height:200%;
border:1px solid red;
transform-origin:0 0;
transform:scale(0.5);
}
* border-image 设置图片的边框前端

3、4.transition和animation的区别
Animation和transition大部分属性是相同的,他们都是随时间改变元素的属性值,他们的主要区别是transition须要触发一个事件才能改变属性,
而animation不须要触发任何事件的状况下才会随时间改变属性值,而且transition为2帧,从from .... to,而animation能够一帧一帧的。

transition 规定动画的名字 规定完成过渡效果须要多少秒或毫秒 规定速度效果 定义过渡效果什么时候开始
animation 指定要绑定到选择器的关键帧的名称
vue

4、不定宽高的DIV居中
1.使用flex 在父盒子设置display: flex; justify-content: center;align-items: center
2.使用css的transform 父盒子设置:display:relative
Div 设置: transform: translate(-50%,-50%);position: absolute;top: 50%;left: 50%;
3.display:table-cell 父盒子设置:display:table-cell; text-align:center;vertical-align:middle;
Div 设置: display:inline-block;vertical-align:middle;
4.position:absolute;top:0;left:0;right:0;bottom:0;margin:auto;

5、浮动 https://juejin.im/post/5a954add6fb9a06348538c0d
特性:浮动元素影响的不只是本身,他会影响周围元素对其进行环绕
为何要清除浮动?(解决父元素高度坍陷问题)
一个块级元素若是没有设置height,其height由子元素撑开,对子元素使用了浮动以后,子元素就会脱离文档流
也就是说,父及元素中没有内容能够撑开其高度,这样父级元素height就会被忽略。这就是所谓的高度坍塌
如何清除浮动
1.给父级元素定义高度 2.让父级元素也浮动 3.父级定义display:table 4.父元素设置overflow:hidden
clearfix:使用内容生成的方式清除浮动
.clearfix:after { // :after选择器向选定的元素以后插入内容
content:""; // 生成内容为空
display: block; // 块级元素显示
clear:both; // 清除前面元素
}
不破坏文档流,没有反作用java

7、position
值:relative,static(默认值),absolute,sticky,fixed
absolute会根据上一级position的值不为static进行定位,若是向上一直没有找到position,则相对整个body进行定位
fixe相对的是视图的窗口,或者frame框架(setFram的子框架,一种html标签)node

8、css选择器分类:
基本的:
1.id选择器(id="name")
2.类选择器(class="head")
3.标签选择器(body, div, ul, li)
4.全局选择器(*)
复杂的:
1.组合选择器(.head .head_logo)
2.后代选择器 (#head .nav ul li 从父集到子孙集)
3.群组选择器 (div, span, img {color:Red} 具备相一样式的标签分组显示)
4.继承选择器
5.伪类选择器(连接样式,a元素的伪类)
6.子选择器(div>p, 带大于号>)
7.CSS相邻相邻兄弟选择器(h1+p, 带加号+)react

9、CSS优先级
不一样级别:总结排序:!important > 行内样式>ID选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性
1.属性后面加!import 会覆盖页面内任何位置定义的元素样式
2.做为style属性写在元素内的样式
3.id选择器
4.类选择器
5.标签选择器
6.通配符选择器(*)
7.浏览器自定义或继承
同一级别:后写的会覆盖先写的webpack

css选择器的解析原则:选择器定位DOM元素是从右往左的方向,这样能够尽早的过滤掉一些没必要要的样式规则和元素

10、对于行内元素,font-size指定 他们的content area的高度,因为inline box = 上下的helf-leading,若是leading为0,在这种状况下,font-size指定了inline box的高度
font-size 指的是字体的高度,可是不能指定每一个字形给定字体高度下的实际高度,致使了span的高度大于line-heightes6

11、z-index属性 z-index 属性设置元素的堆叠顺序。拥有更高堆叠顺序的元素老是会处于堆叠顺序较低的元素的前面。
position的值的属性大于z-index Z-index 仅能在定位元素上奏效(例如 position:absolute;)
元素可拥有负的 z-index 属性值,父子关系的元素z-index设置无效

12、块元素和行内元素
1.块元素会独占一行,默认状况下,其宽度自动填满父元素宽度 行元素不会占据一行,会一直排在一行,直到一行排不下
2.行元素没有宽度和高度属性,块级元素即便设置了宽度,仍是会独占一行
块级元素: div p form ul li ol dl h1-h6
行内元素:span img a i s u b a strong em
行内块元素:input

十3、如何画一个三角形: 设置宽高,而后用border去画
width:0;
height:0;
border:25px solid transparent;
border-top-color:red;

十4、伪类:link 表示连接正常状况下(即页面加载完成时)显示的颜色
hover:表示鼠标悬停时显示的颜色
visited:连接被点击时显示的位置
focus:元素得到光标焦点时的颜色
active: 元素处于激活状态
link -> visited -> hover -> focus -> active

十5、雪碧图:多个图片集成在一个图片中的图
使用雪碧图能够减小网络请求的次数,加快容许的速度
经过background-position,去定位图片在屏幕的哪一个位置

十六: Margin-top和translate  50%的区别

Margin-top默认以左上角为目标运动

Translate 默认以中心点为目标运动

十七:2px和2区别

没有单位能够用于缩放的位置ex: flex-grow

十八:line-height是针对谁设置的,继承谁?

设置数字,此数字会与当前的字体尺寸相乘来设置行间距

 

布局面试
1、flex弹性布局,
能够简单的使一个元素居中(包括水平和垂直居中)
栅格式系统布局,bootstrap grid

2、圣杯和双飞翼布局 三栏是布局(两边两栏宽度固定,中间栏宽度自适应)
方案一:position(绝对定位法) center的div须要放在最后面
绝对定位法原理将左右两边使用absolute定位,由于绝对定位使其脱离文档流,后面的center会天然流动到他们的上面去,而后margin属性,留出左右两边的宽度。就能够自适应了。
方案二:float 自身浮动法 center的div须要放到后面
自身浮动法的原理就是对左右使用float:left和float:right,float使左右两个元素脱离文档流,中间的正常文档流中,使用margin指定左右外边距对其进行一个定位。
圣杯布局:原理就是margin负值法。使用圣杯布局首先须要在center元素外部包含一个div,包含的div须要设置float属性使其造成一个BFC,而且这个宽度和margin的负值进行匹配

3、左边定宽,右边自适应
方案一:左边设置浮动,右边宽度设置100%
.left{float:left;height: 150px;width: 150px;}
.right{width: 100%;height: 200px;margin-left: 150px;}
方案二:同上将float设置为position
方案三:父容器设置display:flex right部分是设置flex:1

4、水平居中
行内元素居中(父元素text-align:center)
块状元素居中(块状元素没发用text-align)
1.宽度必定:margin:auto
2.宽度不定:块级变行内,而后在父上text-aligin
float

4、BFC https://juejin.im/post/5909db2fda2f60005d2093db
理解:BFC是css布局的一个概念,是一块独立的渲染区域,一个环境,里面的元素不会影响到外部的元素
如何生成BFC:(脱离文档流)
【1】根元素,即HTML元素(最大的一个BFC)
【2】float的值不为none
【3】position的值为absolute或fixed
【4】overflow的值不为visible(默认值。内容不会被修剪,会呈如今元素框以外)
【5】display的值为inline-block、table-cell、table-caption
BFC布局规则:1.内部的Box会在垂直方向,一个接一个地放置。
2.属于同一个BFC的两个相邻的Box的margin会发生重叠
3.BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此, 文字环绕效果,设置float
4.BFC的区域不会与float box重叠。
5.计算BFC的高度,浮动元素也参与计算
BFC做用:1.自适应两栏布局
2.能够阻止元素被浮动元素覆盖
3.能够包含浮动元素---清除内部浮动 原理::触发父div的BFC属性,使下面的子div都处在父div的同一个BFC区域以内
4.分属于不一样的BFC时,能够阻止margin重叠

js面试
1、 this的指向:https://www.cnblogs.com/pssp/p/5216085.html
1.做为普通函数,this指向window。ex: fn();//window
2.自动引用正在调用当前方法.前的对象ex: a.fn();//a
3.若是有嵌套的状况,则this绑定到最近的一层对象上;ex: o.a.fn();//a
4.构造器调用(类型.prototype.fun),this指向返回的这个对象(未来调用函数.前的子对象)。
5.箭头函数 箭头函数的this绑定看的是this所在函数定义在哪一个对象下,就绑定哪一个对象
注意:
1.this永远指的是最后调用它的对象ex:var j=o.b.fn; j(); //window
2.new Fun() ,this指向的是正在建立的新对象;ex: var a=new fn();a.uname//a
3.this碰到retuen,调用方法里return了一个对象,this指向return对象

怎么改变this的指向呢? 1.使用es6的箭头函数;2.在函数内部使用that = this;3.使用apply,call,bind; 4.new实例化一个对象

2、什么是闭包和原型链
内部函数能够访问定义他们外部函数的参数和变量。(做用域链的向上查找,把外围的做用域中的变量值存储在内存中而不是在函数调用完毕后销毁)设计私有的方法和变量,避免全局变量的污染
函数嵌套函数
本质是将函数内部和外部链接起来。优势是能够读取函数内部的变量,让这些变量的值始终保存在内存中,不会在函数被调用以后自动清除
闭包的缺陷:
1.闭包的缺点就是常驻内存会增大内存使用量,而且使用不当容易形成内存泄漏
2.若是不是由于某些特殊任务而须要闭包,在没有必要的状况下,在其它函数中建立函数是不明智的,由于闭包对脚本性能具备负面影响,包括处理速度和内存消耗。


内存溢出和内存泄漏(给的不够用| 用了不归还)
内存溢出:在程序中申请内存时,没有足够的内存空间供其使用,出现out of memory;好比申请了一个integer,但给它存了long才能存下的数,那就是内存溢出
内存泄漏:在程序申请内存后,没法释放已申请的内存空间,一次内存泄漏危害能够忽略,但内存泄漏堆积后果很严重,不管多少内存,迟到会被占光

举列子:闭包中的this,对象函数。匿名函数返回函数return function

做用域:(由当前环境与上层环境一系列的变量对象组成!!!保证 当先执行环境里,有权访问的变量和函数是有序的,做用域链变量只能被向上访问)
定义:由当前环境与上层环境的一系列变量对象组成(函数嵌套函数,内部一级级往上有序访问变量或对象)
做用是:保证当前执行环境里,有权访问的变量和函数时有序的,做用域链的变量只能被向上访问
变量访问到window对象及被终止,做用域链向下访问是不容许的
1.改变做用域有 with try..中的catch,
2.全部为定义的直接赋值的变量自动声明为全局做用域

做用域:一套规则,管理引擎如何在当前做用域以及嵌套的子做用域中根据标识符名称
查找变量(标识符就是变量或者函数名)(只用全局做用域和局部做用域)(做用域在它建立的时候就存在了)

代码执行分为两个阶段:
1.代码编译阶段:有编译器完成,将代码翻译可执行的代码,这个阶段会被肯定
2.代码执行阶段:有js引擎完成,主要执行可执行的大妈,这个阶段执行上下文被建立(对象被建立)

执行上下文:一个看不见得对象,存在若干个属性和变量,它被调用的时候建立的。函数被调用查看的this指向的object,object就是上下文(只有被调用的时候建立)

做用域链: https://blog.csdn.net/yooungt13/article/details/20581635
· 当代码在一个环境中执行时,会建立变量对象的一个做用域链,
举例子:var name ="Tom"
function sayHi () {
alert('Hi,'+name)
}
sayHi() //Hi, Tom
函数sayHi()的执行环境为全局环境,因此它的变量对象为window。当函数执行到name时,先查找局部环境,找到则换回,不然顺着做用域查找,在全局环境中,
找到name返回,这一查找变量的有序过程的依据就是做用域。

· 做用域链是保证执行环境有权访问的全部变量和函数的有序访问

原型链:函数的原型链对象constructor默认指向函数自己,原型对象除了有原型属性外,为了实现继承,还有一个原型链指针_proto_,
该指针是指向上一层的原型对象,而上一层的原型对象的结构依然相似。所以能够利用_proto_一直指向Object的原型对象上,而Object
原型对象用Object.prototype._proto_ = null表示原型链顶端。如此造成了js的原型链继承。同时全部的js对象都有Object的基本防范

3、类的建立和继承
(es5)new 一个function,在这个function的prototype里增长属性和方法, 类里面有方法和属性
(es6)中class, extends
继承:
原型链继承: function Cat(){ } Cat.prototype = new Animal(); Cat.prototype.name = 'cat'; 没法实现多继承
构造继承: 使用父类的构造函数来加强子类实例。function Cat(name){Animal.call(this);this.name = name || 'Tom';} 没法继承父类原型链上的属性跟方法 installof去检验
实例继承: 为父类实例添加新特性,做为子类实例的返回
拷贝继承: 拷贝父类元素上的属性跟方法
组合继承:构造继承 + 原型继承的组合体
寄生组合继承:经过寄生方式,在构造继承上加一个Super函数(没有实例和方法) 让他的原型链指向父类的原型链
砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性
如何判断是那种类型

4、异步回调(如何解决回调地狱)
promise、generator、async/await

promise: 1.是一个对象,用来传递异步操做的信息。表明着某个将来才会知道结果的时间,并未这个事件提供统一的api,供进异步处理
2.有了这个对象,就可让异步操做以同步的操做的流程来表达出来,避免层层嵌套的回调地狱
3.promise表明一个异步状态,有三个状态pending(进行中),Resolve(以完成),Reject(失败)
4.一旦状态改变,就不会在变。任什么时候候均可以获得结果。从进行中变为以完成或者失败
promise.all() 里面状态都改变,那就会输出,获得一个数组
promise.race() 里面只有一个状态变为rejected或者fulfilled即输出
promis.finally()无论指定无论Promise对象最后状态如何,都会执行的操做(本质上仍是then方法的特例)

5、前端事件流
事件流描述的是从页面中接受事件的顺序,事件 捕获阶段 处于目标阶段 事件冒泡阶段 addeventListener 最后这个布尔值参数若是是true,表示在捕获阶段调用事件处理程序;若是是false,表示在冒泡阶段调用事件处理程序。
一、事件捕获阶段:实际目标div在捕获阶段不会接受事件,也就是在捕获阶段,事件从document到<html>再到<body>就中止了。
二、处于目标阶段:事件在div发生并处理,可是事件处理会被当作是冒泡阶段的一部分。
三、冒泡阶段:事件又传播回文档
阻止冒泡事件event.stopPropagation()
function stopBubble(e) {
if (e && e.stopPropagation) { // 若是提供了事件对象event 这说明不是IE浏览器
e.stopPropagation()
} else {
window.event.cancelBubble = true //IE方式阻止冒泡
}
}
阻止默认行为event.preventDefault()
function stopDefault(e) {
if (e && e.preventDefault) {
e.preventDefault()
} else {
// IE浏览器阻止函数器默认动做的行为


window.event.returnValue = false
}
}
事件如何先捕获后冒泡?
在DOM标准事件模型中,是先捕获后冒泡。可是若是要实现先冒泡后捕获的效果,
对于同一个事件,监听捕获和冒泡,分别对应相应的处理函数,监听到捕获事件,先暂缓执行,直到冒泡事件被捕获后再执行捕获事件。

哪些事件不支持冒泡事件:鼠标事件:mouserleave mouseenter
焦点事件:blur focus
UI事件:scroll resize


6、事件委托(提升性能)
简介:事件委托指的是,不在事件的(直接dom)上设置监听函数,而是在其父元素上设置监听函数。经过事件冒泡,父元素能够监听到子元素上事件的触发
经过判断事件发生元素DOM的类型,来作出不一样的响应。
举例子: 最经典的就是ui和li标签的事件监听,好比咱们在添加事件的时候,采用事件委托机制,不会在li标签上直接添加,而是在ul父元素上添加
好处:能够比较合适动态元素的绑定,新添加的子元素也会监听函数,也能够有事件触发机制

7、js的new操做符作了什么?
new操做符建立了一个空对象,这个对象原型指向构造函数的prototype,执行构造函数后返回这个对象(return this)。
若是不要父类的属性跟方法,在函数的prototype上去new这个父类。

8、改变函数内部this指针的指向函数(bind,apply,call)
经过apply和call改变函数的this指向,他们两个函数的第一个参数都是同样的表示要改变指向的那个对象,第二个参数,apply是数组,而call则是arg1,arg2...这种形式。

 

bind 一个是返回一个函数,并不会当即执行 第二个是带参数(第一个参数要指向的this,后面的的参数用来传递

9、深拷贝和浅拷贝 https://juejin.im/post/5b00e85af265da0b7d0ba63f 从堆和栈都是内存中划分出来用来存储的区域开始讲起
基本类型:undefined,null,Boolean,String,Number,Symbol 在内存中占据固定大小,保存在栈内存中
引用类型:Object,Array,Date,Function,RegExp等 引用类型的值是对象 保存在堆内存中,栈内存存储的是对象的变量标识符以及对象在堆内存中的存储地址。
基本类型的复制: 其实就是建立了一个新的副本给将这个值赋值给新变量, 改变值旧对象不会改变
引用类型的复制: 其实就是复制了指针,这个最终都将指向同一个对象,改变其值新对象也会改变
基本类型的比较 == 会进行类型转换

浅拷贝:仅仅就是复制了引用,彼此操做不影响,slice() concat() object.assign
深拷贝:在堆中从新分配内存,不一样的地址,相同的值,互不影响的 JSON.parse()将一个js对象序列化为一个json字符串 JSON.stringify()将json字符串反序列化为一个js对象 es6的展开 {...}
深拷贝和浅拷贝的主要区别是:在内存中的存储类型不一样
浅拷贝:从新在堆栈中建立内存,拷贝先后对象的基本类型互不影响。只拷贝一层,不能对对象进行子对象进行拷贝
深拷贝:对对象中的子对象进行递归拷贝,拷贝先后两个对象互不影响

10、跨域
同源策略(协议+端口号+域名要相同)
一、jsonp跨域(只能解决get)
原理:动态建立一个script标签。利用script标签的src属性不受同源策略限制,由于全部的src属性和href属性都不受同源策略的限制,能够请求第三方服务器资源内容
步骤:1.去建立一个script标签
2.script的src属性设置接口地址
3.接口参数,必需要带一个自定义函数名,要否则后台没法返回数据
4.经过定义函数名去接受返回的数据

二、document.domain 基础域名相同 子域名不一样
三、window.name 利用在一个浏览器窗口内,载入全部的域名都是共享一个window.name
四、服务器设置对CORS的支持
原理:服务器设置Access-Control-Allow-Origin HTTP响应头以后,浏览器将会容许跨域请求
五、利用h5新特性window.postMessage()

iframe元素建立包含另一个文档的内联框架(行内框架)(setTimeout进行异步加载)
解释:浏览器中的浏览器!用于设置文本或者图形的浮动图文框或容器
它和跨域
一、document.domain 实现主域名相同,子域名不一样的网页通讯
都设置为超域:document.domain = 'demo.com'
二、window.postMessageht(data, url),h5的API,启动跨域通讯


11、图片的懒加载和预加载
预加载:提早加载图片,当用户须要查看是能够直接从本地缓存中渲染
为何要使用预加载:在网页加载以前,对一些主要内容进行加载,以提供用户更好的体验,减小等待时间。
不然,若是一个页面的内容过于庞大,会出现留白。
解决页面留白的方案:1.预加载 2.使用svg站位图片,将一些结构快速搭建起来,等待请求的数据来了以后,替换当前的占位符
实现预加载的方法:
1.使用html标签
2.使用Image对象
3.使用XMLHTTPRequest对像,但会精细控制预加载过程

 

懒加载(lazyload):客户端优化,减小请求数和延迟请求数
提高用户体验,
减小无效资源的加载
防止并发加载的资源过多会阻塞js的加载,影响网站的正常使用
原理:首先将页面上的图片的src属性设置为空字符串,而图片的真是路经则设置带data-original属性中,
当页面滚动的时候须要去监听scroll事件,在scroll事件的回调中,判断咱们的懒加载的图片是否进入到可视区域
,若是图片在可视区域将图片的src属性设置为data-original的值,这样就能够实现延迟加载。

12、函数节流防抖
什么是防抖:短期内屡次触发同一个事件,只执行最后一次,或者在开始时执行,中间不执行。好比公交车上车,要等待最后一个乘客上车
什么是节流:节流是连续触发事件的过程当中以必定时间间隔执行函数。节流会稀释你的执行频率,好比每间隔1秒钟,只会执行一次函数,不管这1秒钟内触发了多少次事件
都为解决高频事件而来, scroll mousewhell mousemover touchmove onresize

十3、将arguments类数组转化为数组的方法
Array.apply(null, arguments)
Array.prototype.slice.apply(arguments)
Array.from(arguments)

十4、高阶函数
1、函数做为参数传递 抽离出一部分容易变化的业务逻辑,把这部分业务逻辑放在函数参数中。这样一来能够分离业务代码中变化与不变的部分
回调函数
2、函数做为返回值传递

十5、如何判断一个变量是对象仍是数组(prototype.toString.call())。
千万不要使用typeof来判断对象和数组,由于这种类型都会返回object。
typeOf()是判断基本类型的Boolean,Number,symbol, undefined, String。
对于引用类型:除function,都返回object null返回object。
installOf() 用来判断A是不是B的实例,installof检查的是原型。(arr instanceof Array)
toString() 是Object的原型方法,对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其余对象,则须要经过 call / apply 来调用才能返回正确的类型信息。

hasOwnProperty()方法返回一个布尔值,指示对象自身属性中是否具备指定的属性,该方法会忽略掉那些从原型链上继承到的属性。

isProperty()方法测试一个对象是否存在另外一个对象的原型链上。


十6、setTimeout 和 setInterval的机制
由于js是单线程的。浏览器遇到etTimeout 和 setInterval会先执行完当前的代码块,在此以前会把定时器推入浏览器的
待执行时间队列里面,等到浏览器执行完当前代码以后会看下事件队列里有没有任务,有的话才执行定时器里的代码

十7、var let const
const:定义的变量不可修改,必须初始化 ,
var:定义的变量能够修改,若是不初始化输出undefined,不会报错
let:块级做用域,函数内部使用let定义后,会函数外部无影响
let const 不会形成变量的提高

十8、js垃圾回收机制
1.JS具备自动垃圾收集的机制
2.JS的内存生命周期(变量的生命)
1.分配你所须要的空间 var a = 20
2.使用分配带的内存(读写) alert(a + 10)
3.不适用的时候,释放内存空间 a = null
3.JS的垃圾收集器每隔固定的时间就执行一次释放操做,通用的是经过标记清除的算法
4.在局部做用域中,垃圾回收器很容易作出判断并回收,全局比较难,所以应避免全局变量

标记清除算法:js最多见的垃圾回收方式,当变量进入执行环境的时候,好比函数中声明一个变量,垃圾回收器将他标记为'进入环境',
当变量离开(函数执行完后),就其标记为'离开环境'。垃圾回收器会在运行的时候给存储在内存中的全部变量加上标记,
而后去掉环境中的变量以及被环境中该变量所引用的变量(闭包)。在这些完成以后仍存在标记的就是要删除的变量了

十9、渐进加强和优雅降级
1.渐进加强就是针对低版本浏览器进行构建页面,保证最基本的功能,而后对高级浏览器进行效果、交互等改进和最佳功能达到更好的用户体验
2.优雅降级:一开始构建完整的功能,而后对低版本的进行兼容

二10、undefined 和 null
1.undefined类型只要一个,即undefined,当声明变量还未被初始化时就是undefined
2.null类型也只有一个值,即null。null用来表示还没有存在的对象,经常使用来表示函数企图返回一个不存在的对象
3.NaN 与任何值都是相比较的结果都是false

二11、valueof和tostring
valueof:全部对象都有valueof,若是存在任意原始值,他就默认将对象转化为表示它的原始值。
若是对象是复合值,而却大部分对象没法真正表示一个原始值,所以默认的valueof()方法简单的返回对象自己,而不是返回原始值。
数组、函数和正则表达式简单的继承了这个more方法,返回对象自己

二12、输入框的change和input事件
onchange事件:要在input失去焦点的时候才触发
oninput事件:要在用户输入的时触发,他是元素值发生变化时当即触发

二十3、同步和异步
同步:因为js单线程,同步任务都在主线程上排队执行,前面任务没有执行完成,后面的任务会一直等待
异步:不进入主线程,进入任务队列,等待主线程任务执行完成,开始执行。最基本的异步操做SetTimemot和SetInterval,等待主线程任务执行完,在开始执行里面的函数


二十4、函数的柯里化
概念:一个函数接受函数A做为参数,运行后返回return function一个新的函数,而且能够处理A中的参数(只接受单一参数的函数)
意义:将函数彻底变成了接受一个参数,返回一个参数的固定形式,便于讨论和优化

二十5、while
while循环会在指定条件为真时循环执行代码

二十6、TypeScript的优势:
一、编译时的强类型,变成了强类型语言,仍是编译成js 编译的时候就能够检验
二、更好的模块化
三、更好的是实现面向对象的编程,类、接口、模块

二十7、js的阻塞特性:全部浏览器在下载JS的时候,会阻止一切其余活动,好比其余资源的下载,内容的呈现等等。
直到JS下载、解析、执行完毕后才开始继续并行下载其余资源并呈现内容。
为了提升用户体验,新一代浏览器都支持并行下载JS,可是JS下载仍然会阻塞其它资源的下载(例如.图片,css文件等)。
css阻塞:由于浏览器会维持html中css和js的顺序,样式表必须在嵌入的JS执行前先加载、解析完。
而嵌入的JS会阻塞后面的资源加载,因此就会出现上面CSS阻塞下载的状况。

二十8、meta元素可提供有关页面的元信息,好比针对搜索引擎和更新频度的描述和关键词

 

二十九: POST提交数据时四种常见格式

服务端一般是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。

         setRequestHeader(“Content-type” , ”application/x-www-form-urlencoded”);

1)1. application/x-www-form-urlencoded 原生表单

2)2. multipart/form-data 表单上传文件

3)3. application/json

4)4. text/xml

三十:   HTTP请求方法

GET:获取资源      POST:传输文本

PUT:传输文件      DELETE:删除文件

HEAD:得到报文首部

OPTIONS:访问服务器端能够提交哪些请求方法

三十一: js实现图片上传到服务器和回显

<input type="file" value="" name="file" id = "input_file"

      accept="image/gif,image/jpeg,image/jpg,image/png,image/svg"    onchange="imgPreview(this,0)">

function imgPreview(fileDom,i) {

var file = fileDom.files[0];  //获取文件

reader.onload = function(e) {

document.getElementsByClassName('file-box')[i].style.background="url("+e.target.result+")no-repeat";//回显图片

          document.getElementsByClassName('file-box')[i].style.backgroundSize='200px 160px';

}

reader.readAsDataURL(file); //转码保存

}

//ajax请求

var formData = new FormData();

formData.append('photo', $('#input_file')[0].files[0]); 

$.ajax({})

三十二: 简述浏览器渲染过程

解析html以构建dom树 -> 构建render树(加上css) -> 布局render树 -> 绘制render树

三十三:  jQuery工做原理

1)jQuery采用的是构造函数模式进行开发的,jQuery是一个类

2)经常使用的方法(CSS、属性、筛选、事件、动画)都是定义在jQuery.prototype上的 ->只有jQuery的实例才能使用这些方法

三十四: Sessionid如何生成,由谁产生,保存在哪里?

sessionid是一个会话的key,浏览器第一次访问服务器会在服务器端生成一个session,有一个sessionid和它对应。程序调用 HttpServletRequest.getSession(true)这样的语句时才被建立。存放:服务器端的内存中

三十五: Session和Cookie的区别与联系:

一、cookie数据存放在客户的浏览器上,session数据放在服务器上。

二、cookie不是很安全,别人能够分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。

三、session会在必定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。

四、单个cookie保存的数据不能超过4K,不少浏览器都限制一个站点最多保存20个cookie。

五、能够考虑将登录信息等重要信息存放为session,其余信息若是须要保留,能够放在cookie中。

三十六: JSON.parse()与JSON.stringify()的区别

JSON.parse()从一个字符串中解析出json对象

JSON.stringify()从一个对象中解析出字符串

三十七:NaN 是什么?它的类型是什么?如何可靠地测试一个值是否等于 NaN ?

NAN:不是数字               类型:number

value!==value 为true就是nan(只有nan才会和本身不相等)

Number.isNaN()

三十八:javascript建立数组时,Array()和[]有什么区别

Array()经过调用数组构造函数生成,能够(8)直接定义数组长度,内存中开辟一个存储空间,比较耗资源

[]经过字面量定义数组,直接在内存中开辟一个存储字段,不耗资源

三十九: 定义函数时用 var foo = function () {} 和 function foo() {}有什么区别?

前者声明了一个变量,这个变量是个方法,是能够改变的

后者声明了一个方法,这个方法名字没法改变

本质变量和方法声明提早的问题

四十:写一个按照下面方式调用都能正常工做的sum方法

console.log(sum(2,3));  //输出Outputs 5

console.log(sum(2)(3)); //输出Outputs 5

function sum() {

          var num = arguments[0];

          if(arguments.length === 2) {

            return arguments[0] + arguments[1]

          } else {

            return function(sec) {

               return num + sec;

            }

          } 

        }

四十一:若是一个函数没有返回语句,此函数返回值是什么?

无返回语句返回Undefined

return; 返回null,起到中断方法执行效果

四十二: forEach()和map()的区别

Foreach:没有返回值,遍历数组对每一个值进行处理

Map():有返回值,返回值组成一个新的数组

四十二:ES6语法

箭头函数 ()=>{}

Var let const

解构

let {name,age} = {name: "lisi", age: "20"};

console.log(name); //lisi              

模板字符串

For in && for of

New promise()

四十三.如何合并对象

Object.assign(o1,o2,o3,…)

四十四.不彻底结构

Let [x,y]=[1,2,3] ; x=1,y=2

四十五.var/let/const的区别

Let/const 只在声明块级做用域内有效

Let定义变量,const定义常量,必须初始化,不可改变

Var 全局变量,会声明提早值留原地,屡次赋值,例如循环中新值会替换旧值



node面试
1、koa中间件执行机制
1.添加中间件的方式是使用Koa实例的use方法,并传入一个generator函数,这个generator函数接受一个next参数
2.use的原理:function Application () {this.middleware = [] // 这个数组就是用来装一个个中间间的}
3.每次执行use方法,就把外面传进来的generator函数push到middleware数组中
app.use = function (fn) {this.middleware.push(fn)}
4.koa中是预先经过use方法,将请求可能会通过的中间间装在一个数组中。
5.callback函数就是请求到来的时候执行的回调。把装着中间件middleware的数组做为参数传递为compose这个方法。
6.componse把毫无关系的一个个中间件给收尾串起来了,就比如咱们日常的烤面筋
7.componse将中间件从最后一个开始处理,并一直往前知道第一个中间件。其实最关键的就是将最后一个中间件获得generator
做为参数传递给前一个中间件。当最后一个中间件的参数next是空的generator函数生成对象

中间件是怎么跑起来的:https://juejin.im/post/591c8b4544d904006c90a2cb

 


vue面试
1、介绍下MVVM(数据的双向绑定)
M: model数据模型
V: view 界面
MV:做为桥梁负责沟通view跟model
只关心数据的流传,减小强耦合性。最关键的就是数据的双向绑定
关键步骤:1.实现数据监听器Observer,用object.defineProperty()重写数据的get/set。值更新就在set中通知订阅者更新数据
2.实现模板编译compile,深度遍历dom树,对每一个元素节点的指令模板替换数据以及订阅数据
3.实现watch用于链接Observer和compile,可以订阅并接受每个属性的变更的通知,执行指令绑定的相应的回调函数,从而更新数据

mvc和mvvm其实区别并不大。都是一种设计思想。主要就是mvc中Controller演变成mvvm中的viewModel。mvvm主要解决了mvc中大量的DOM 操做使页面渲染性能下降,
加载速度变慢,影响用户体验。和当 Model 频繁发生变化,开发者须要主动更新到View 。

2、 eventBus vuex
原理:eventbus 解决了兄弟组件之间事件传递问题,本质是订阅发布者模式,从而摆脱了兄弟之间须要父组件转而传递的复杂。还有一种方法是vuex数据流,单一状态树,rootState树根
名词,专车。订阅者跟发布者都引用专车,这个vue实例,来完成订阅发布者。 emit(发布) on(订阅一个组件)
npm包 vue-event-proxy

vuex 是将数据单独的抽离出来,一种状态管理工具,它借鉴的是Flux、redux的基本思想,将转态抽离到全局造成一个store

3、watch:
对属性进行监听,容许咱们执行异步操做,限制咱们执行该操做的频率(debounce),并在咱们获得结果前,设置中间转态。

4、Vue的双向数据绑定实现原理
1.核心就是数据劫持 + 发布/订阅者模式:vue使用的是Object.defineProperty()经过监听他的get/set事件,监听对数据的操做,从而触发数据同步

Object.defineProperty缺陷的:
1.只能对属性进行数据劫持,而且须要深度遍历整个对象
2.对于数组不能监听数据的变化
而proxy原生支持监听数组的变化,而且能够直接对整个对象进行拦截,全部Vue在下个版本中用proxy替换object.defineProperty


5、nextTick原理

6、生命周期函数 https://juejin.im/post/5b41bdef6fb9a04fe63765f1
new Vue(建立一个Vue对象)--> beforeCreate --> observer Data(开始监控data对象数据变化) --> init event(vue内部初始化事件)

--> created() --> compile(编译模板,把data里面的数据和模板生成html) --> beforeMount(尚未生成HTML到元素上) -->

mounted(挂载完成,也就是模板中的html渲染到了html页面中) --> beforeUpdate (Vritual Dom) --> updated --> beforeDestroy --> destroyed

1.ajax请求最好放在created里面,页面能够访问到this了
2.关于dom的操做要放在mounted里面,在mounted前面尚未生成dom
3.每次进入/离开组件都要作一些事情,用什么钩子函数:
不缓存:进入的时候能够用created和mounted钩子,离开的时候能够使用beforedDestory(能够访问this)和destoryed


缓存:缓存了组件以后,在次进入组件不会触发beforeCreate,created, beforeMount,mounted
若是你想每次进入组件都作一些事情的话,你能够放在activated进入缓存组件的钩子中
7、keep-alive
在被keep-alive包含的组件/路由,会多出两个生命周期:activated 和 deactivated
actived在组件第一次渲染时会被调用,以后再每次缓存组件被激活时调用 调用机制:第一次进入缓存路由/组件,在mounted后面,beforeRouteEnter守卫传给 next 的回调函数以前调用:

8、Vue的SPA 如何优化加载速度
1.减小入口文件体积
2.静态资源本地缓存
3.开启Gzip压缩
4.使用SSR,nuxt.js

9、模块化
基本概念: 1.在js中,一个模块就是实现特定功能的文件(js文件)
2.遵循模块的机制,想要什么就加载什么模块
3.模块化开发须要遵循规范

js实现模块化规范
1.AMD 浏览器 requirejs 模块被异步加载,模块加载不影响后面语句的运行 默认使用baseURL+ paths的路经解析方式
2.CommonJS nodejs
3.ES6的import/export
4.CMD 浏览器端

解决的问题:1.命名冲突 2.文件依赖 3.模块的复用 4.统一规范和开发方式

10、谈谈Vue和React组件化的思想
1.咱们在各个页面开发的时候,会产生不少重复的功能,好比element中的xxxx。像这种纯粹非页面的UI,便成为咱们经常使用的UI组件,最初的前端组件也就仅仅指的是UI组件
2.随着业务逻辑变得越来可能是,咱们就想要咱们的组件能够处理不少事,这就是咱们常说的组件化,这个组件就不是UI组件了,而是包具体业务的业务组件
3.这种开发思想就是分而治之。最大程度的下降开发难度和维护成本的效果。而且能够多人协做,每一个人写不一样的组件,最后像撘积木同样的把它构成一个页面

12、VUE如何自定义属性

全局自定义:

Vue.directive(‘focus’,{

         Inserted:function(el){

                   el.focus()  //聚焦函数

}       

})

组件自定义

directive{

         inserted:function(el){

                   el.focus() 

}

}

十3、.Vue和vuex 有什么区别

Vue是框架,vuex是插件,vuex是专门为vue应用程序开发的状态管理模式

十4、.Vuex中actions和mutations的区别

Mutations的更改是同步更改,用于用户执行直接数据更改,this.$store.commit(‘名’)触发

Actions的更改是异步操做,用于须要与后端交互的数据更改,this.$store.dispath(“名”)触发

注意:

1):定义actions方法建立一个更改函数时,这个函数必须携带一个context参数,用于触发mutations方法,context.commit(‘修改函数名’ , ’异步请求值’);

2):mutations第一个参数必须传入state,第二个参数是新值


React
1、react和vue的区别
=> 相同点:
1.数据驱动页面,提供响应式的试图组件
2.都有virtual DOM,组件化的开发,经过props参数进行父子之间组件传递数据,都实现了webComponents规范
3.数据流动单向,都支持服务器的渲染SSR
4.都有支持native的方法,react有React native, vue有wexx
=> 不一样点:
1.数据绑定:Vue实现了双向的数据绑定,react数据流动是单向的
2.数据渲染:大规模的数据渲染,react更快
3.使用场景:React配合Redux架构适合大规模多人协做复杂项目,Vue适合小快的项目
4.开发风格:react推荐作法jsx + inline style把html和css都写在js了
vue是采用webpack + vue-loader单文件组件格式,html, js, css同一个文件

2、redux中的reducer(纯函数)
Redux数据流里,reduces实际上是根据以前的状态(previous state)和现有的action(current action)更新state(这个state能够理解为上下累加器的结果)
每次redux reducer被执行时,state和action被传入,这个state根据action进行累加或者是'自身消减'(reduce),进而返回最新的state,这也就是典型reduce函数的用法:state -> action -> state

3、react的refs
refs就想一个逃生窗,容许咱们之间访问dom元素或者组件实例,能够向组件添加一个ref属性的值是一个回调函数,
它将接受地城dom元素或组件的已挂在实例,做为第一个参数

4、react中的keys
帮组咱们跟踪哪些项目已更改、添加、从列表中删除,key是独一无二的,可让咱们高效的去定位元素,而且操做它

5、React的生命周期
三个状态:Mounting(已插入真实的DOM)
Updating(正在被从新渲染)
Unmounting(已移除真实的DOM)
componentDIdMount 在第一次渲染后调用,只在客服端。以后组件已经生成对应的DOM结构,
componentDidUpdate 在组件完成更新后当即调用,在出初始化是不会调用

6、React子组件向父组件传值
父组件经过props 给子组件传递数据,子组件则是经过调用父组件传给它的函数给父组件传递数据。

7、React数据流

8、为何虚拟DOM会提升性能 https://www.zhihu.com/question/29504639?sort=created
虚拟DOM至关于在js和真实dom中间加了一个缓存,利用dom diff算法避免了没有必要的doom操做,从而提升性能
具体实现步骤:
·用JavaScript对象结构表示DOM树的结构;而后用这个树构建一个真正的DOM树,插到文档中
·当状态变动的时候,从新构造一棵树的对象树,而后用新的树和旧的树进行对比,记录两棵树差别
·把2所记录的差别应用到步骤1所构建的真正的DOM树上,试图就更新了。

9、diff算法
1.把树形结构按照层级分解,只比较同级元素
2.给列表结构的每一个单元添加key属性,方便比较。在实际代码中,会对新旧两棵树进行一个深度优先的遍历,这样每一个节点都会有一个标记
3.在深度优先遍历的时候,每遍历到一个节点就把该节点和新的树进行对比。若是有差别的话就记录到一个对象里面
Vritual DOM 算法主要实现上面步骤的三个函数:element, diff, patch。而后就能够实际的进行使用
react只会匹配相同的class的component(这里的class指的是组件的名字)
合并操做,条用component的setState方法的时候,React将其标记为dirty.到每个时间循环借宿,React检查全部标记dirty的component从新绘制
4.选择性子树渲染。能够重写shouldComponentUpdate提升diff的性能

10、super

11、简述下flux的思想
flux的最大特色,就是数据的‘单向流动’
1.用户访问View
2.View发出用户的Action
3.Dispatcher收到Action,要求state进行相应的更新
4.store更新后,发出一个‘change’事件后,更新页面

12、reac性能优化是哪一个周期函
shouldComponentUpdate 这个方法用来判断是否须要调用render方法从新描绘dom.由于dom的描绘很是消耗性能,
若是咱们在shouldComponentUpdate方法中可以写出更优化的dom diff算法,能够极大的提升性能

十3、react怎么划分业务组件和技术组件
根据组件的职责一般把组件分为UI组件和容器组件
UI组件负责UI的呈现,容器组件负责管理数据和逻辑
二者经过React-redux提供connect方法联系起来

十4、setState
setState经过一个队列机制实现state更新,当执行setState时,会将须要更新的state很后放入状态队列
而不会当即更新this.state,队列机制能够高效地批量更新state。若是不经过setState而直接修改this.state的值
那么该state将不会被放入状态队列中。当下次调用setState并对状态队列进行合并时,就会忽略以前修改的state,形成不可预知的错误

同时,也利用了队列机制实现了setState的异步更新,避免了频繁的重复更新state

同步更新state:
setState 函数并不会阻塞等待状态更新完毕,所以 setNetworkActivityIndicatorVisible 有可能先于数据渲染完毕就执行。第二个参数是一个回调函数,在setState的异步操做结束而且组件已经从新渲染的时候执行
也就是说,咱们能够经过这个回调来拿到更新的state的值,实现代码的同步

例子:componentDidMount() {

fetch('https://test.com')

.then((res) => res.json())

.then(
(data) => {
this.setState({ data:data });

StatusBar.setNetworkActivityIndicatorVisible(false);
}


性能优化

1、webpack打包文件体积过大?(最终打包为一个js文件)
1.异步加载模块
2.提取第三库
3.代码压缩
4.去除没必要要的插件

如何优化webpack构建的性能
1、减小代码体积 1.使用CommonsChunksPlugin 提取多个chunk之间的通用模块,减小整体代码体积
2.把部分依赖转移到CDN上,避免每次编译过程都由Webpack处理
3.对一些组件库采用按需加载,避免无用的代码
2、减小目录检索范围
·在使用loader的时候,经过制定exclude和include选项,减小loader遍历的目录范围,从而加快webpack编译速度

3、减小检索路经:resolve.alias能够配置webpack模块解析的别名,对于比较深的解析路经,能够对其配置alias


2、咱们把开发中的全部资源(图片,js、css文件)都当作模块,经过loader和plugins来对资源进行处理,打包成符合生产环节部署的前端资源。

3、移动端的性能优化
一、首屏加载和按需加载,懒加载
二、资源预加载
三、图片压缩处理,使用base64内嵌图片
四、合理缓存dom对象
五、使用touchstart代替click(click 300毫秒的延迟)
六、利用transform:translateZ(0),开启硬件GUP加速
七、不滥用web字体,不滥用float(布局计算消耗性能),减小font-size声明
八、使用viewport固定屏幕渲染,加速页面渲染内容
九、尽可能使用事件代理,避免直接事件绑定

4、Vue的SPA 如何优化加载速度
1.减小入口文件体积
2.静态资源本地缓存
3.开启Gzip压缩
4.使用SSR,nuxt.js

5、移动端300ms延迟
由来:300毫米延迟解决的是双击缩放。双击缩放,手指在屏幕快速点击两次。safari浏览器就会将网页缩放值原始比例。
因为用户能够双击缩放或者是滚动的操做,当用户点击屏幕一次以后,浏览器并不会判断用户确实要打开至这个连接,仍是想要进行双击操做
因次,safair浏览器就会等待300ms,用来判断用户是否在次点击了屏幕
解决方案:1.禁用缩放,设置meta标签 user-scalable=no
2.fastclick.js
原理:FastClick的实现原理是在检查到touchend事件的时候,会经过dom自定义事件当即
发出click事件,并把浏览器在300ms以后真正的click事件阻止掉
fastclick.js还能够解决穿透问题

6、页面的重构;在不改变外部行为的前提下,简化结构、添加可读性

服务器端
1、状态码:

2XX(成功处理了请求状态)
200 服务器已经成功处理请求,并提供了请求的网页
201 用户新建或修改数据成功
202 一个请求已经进入后台
204 用户删除成功
3XX(每次请求使用的重定向不要超过5次)
304 网页上次请求没有更新,节省带宽和开销
4XX(表示请求可能出错,妨碍了服务器的处理)
400 服务器不理解请求的语法
401 用户没有权限(用户名,密码输入错误)
403 用户获得受权(401相反),可是访问被禁止
404 服务器找不到请求的网页,
5XX(表示服务器在处理请求的时候发生内部错误)
500 服务器遇到错误,没法完成请求
503 服务器目前没法使用(超载或停机维护)

2、304的缓存原理(添加Etag标签.last-modified) 304 网页上次请求没有更新,节省带宽和开销
1.服务器首先产生Etag,服务器可在稍后使用它来判断页面是否被修改。本质上,客户端经过该记号传回服务器要求服务器验证(客户端)缓存)
2.304是 HTTP的状态码,服务器用来标识这个文件没有被修改,不返回内容,浏览器接受到这个状态码会去去找浏览器缓存的文件
3.流程:客户端请求一个页面A。服务器返回页面A,并在A上加一个Tage客服端渲染该页面,并把Tage也存储在缓存中。客户端再次请求页面A
并将上次请求的资源和ETage一块儿传递给服务器。服务器检查Tage.而且判断出该页面自上次客户端请求以后未被修改。直接返回304

last-modified: 客服端请求资源,同时有一个last-modified的属性标记此文件在服务器最后修改的时间
客服端第二次请求此url时,根据http协议。浏览器会向服务器发送一个If-Modified-Since报头,
询问该事件以后文件是否被修改,没修改返回304

有了Last-Modified,为何还要用ETag?
一、由于若是在一秒钟以内对一个文件进行两次更改,Last-Modified就会不正确(Last—Modified不能识别秒单位的修改)
二、某些服务器不能精确的获得文件的最后修改时间
三、一些文件也行会周期新的更改,可是他的内容并不改变(仅仅改变修改的事件),这个时候咱们并不但愿客户端认为文件被修改,而从新Get

ETag,为何还要用Last-Modified?
一、二者互补,ETag的判断的缺陷,好比一些图片等静态文件的修改
二、若是每次扫描内容都生成ETag比较,显然要比直接比较修改时间慢的多。


ETag是被请求变量的实体值(文件的索引节,大小和最后修改的时间的Hash值)
一、ETag的值服务器端对文件的索引节,大小和最后的修改的事件进行Hash后获得的。

3、get/post的区别
1.get数据是存放在url以后,以?分割url和传输数据,参数之间以&相连; post方法是把提交的数据放在http包的Body中
2.get提交的数据大小有限制,(由于浏览器对url的长度有限制),post的方法提交的数据没有限制
3.get须要request.queryString来获取变量的值,而post方式经过request.from来获取变量的值
4.get的方法提交数据,会带来安全问题,好比登陆一个页面,经过get的方式提交数据,用户名和密码就会出如今url上

4、http协议的理解
1.超文本的传输协议,是用于从万维网服务器超文本传输到本地资源的传输协议
2.基于TCP/IP通讯协议来传递数据(HTML,图片资源)
3.基于运用层的面向对象的协议,因为其简洁、快速的方法、适用于分布式超媒体信息系统
4.http请求信息request:
请求行(request line)、请求头部(header),空行和请求数据四部分构成

请求行,用来讲明请求类型,要访问的资源以及所使用的HTTP版本.
请求头部,用来讲明服务器要使用的附加信息
空行,请求头部后面的空行是必须的
请求数据也叫主体,能够添加任意的其余数据。
5.http相应信息Response
状态行、消息报头、空行和响应正文

状态行,由HTTP协议版本号, 状态码, 状态消息 三部分组成
消息报头,用来讲明客户端要使用的一些附加信息
空行,消息报头后面的空行是必须的
响应正文,服务器返回给客户端的文本信息。


5、http和https
https:是以安全为目标的HTTP通道,简单讲是HTTP的安全版本,经过SSL加密
http:超文本传输协议。是一个客服端和服务器端请求和应答的标准(tcp),使浏览器更加高效,使网络传输减小

5、http1.0 1.1 2.0的区别
长链接:HTTP1.0须要使用keep-alive参数来告知服务器创建一个长链接,而HTP1.1默认支持长链接
节约宽带:HTTP1.1支持只发送一个header信息(不带任何body信息)
host域(设置虚拟站点,也就是说,web server上的多个虚拟站点能够共享同一个ip端口):HTTP1.0没有host域

1.http2采用的二进制文本传输数据,而非http1文本格式,二进制在协议的解析和扩展更好
2.数据压缩:对信息头采用了HPACK进行压缩传输,节省了信息头带来的网络流量
3.多路复用:一个链接能够并发处理多个请求
4.服务器推送:咱们对支持HTTP2.0的web server请求数据的时候,服务器会顺便把一些客户端须要的资源一块儿推送到客户端,省得客户端再次建立链接发送请求到服务器端获取。这种方式很是合适加载静态资源

6、koa和express的区别
1.异步流程的控制。express采用callback来处理异步,koa2采用的是async/await
2.错误处理。express采用callback捕获异常,对深层次的异常捕获不了。koa采用try/catch

7、web缓存
1.web缓存就是存在于客户端与服务器之间的一个副本、当你第一个发出请求后,缓存根据请求保存输出内容的副本
2.缓存的好处
(1)减小没必要要的请求
(2)下降服务器的压力,减小服务器的消耗
(3)下降网络延迟,加快页面打开速度(直接读取浏览器的数据)

8、常见的web安全及防御原理
1.sql注入原理:通郭sql命令插入到web表单递交或者输入活命,达到欺骗服务器执行的恶意sql命令
防范:1.对用户输入进行校验
2.不适用动态拼接sql
2.XSS(跨站脚本攻击):往web页面插入恶意的html标签或者js代码。
举例子:在论坛放置一个看是安全的连接,窃取cookie中的用户信息
防范:1.尽可能采用post而不使用get提交表单
2.避免cookie中泄漏用户的隐式
3.CSRF(跨站请求假装):经过假装来自受信任用户的请求
举例子:黄轶老师的webapp音乐请求数据就是利用CSRF跨站请求假装来获取QQ音乐的数据
防范:在客服端页面增长伪随机数,经过验证码
XSS和CSRF的区别:
1.XSS是获取信息,不须要提早知道其余用户页面的代码和数据包
2.CSRF代替用户完成指定的动做,须要知道其余页面的代码和数据包

9、CDN(内容分发网络)
1.尽量的避开互联网有可能影响数据传输速度和稳定性的瓶颈和环节。使内容传输的更快更稳定。
2.关键技术:内容存储和分发技术中
3.基本原理:普遍采用各类缓存服务器,将这些缓存服务器分布到用户访问相对的地区或者网络中。当用户访问网络时利用全局负载技术
将用户的访问指向距离最近的缓存服务器,由缓存服务器直接相应用户的请求(全局负载技术)


10、TCP三次握手 (客服端和服务器端都须要确认各自可收发)
客服端发c起请求链接服务器端s确认,服务器端也发起链接确认客服端确认。
第一次握手:客服端发送一个请求链接,服务器端只能确认本身能够接受客服端发送的报文段
第二次握手: 服务端向客服端发送一个连接,确认客服端收到本身发送的报文段
第三次握手: 服务器端确认客服端收到了本身发送的报文段

11、从输入url到获取页面的完整过程 https://blog.csdn.net/samjustin1/article/details/52650520
1.查询NDS(域名解析),获取域名对应的IP地址
查询浏览器缓存
2.浏览器与服务器创建tcp连接(三次握手)
3.浏览器向服务器发送http请求(请求和传输数据)
4.服务器接受到这个请求后,根据路经参数,通过后端的一些处理生成html代码返回给浏览器
5.浏览器拿到完整的html页面代码开始解析和渲染,若是遇到外部的css或者js,图片同样的步骤
6.浏览器根据拿到的资源对页面进行渲染,把一个完整的页面呈现出来

12、浏览器渲染原理及流程 DOM -> CSSOM -> render -> layout -> print
流程:解析html以及构建dom树 -> 构建render树 -> 布局render树 -> 绘制render树
概念:1.构建DOM树: 渲染引擎解析HTML文档,首先将标签转换成DOM树中的DOM node(包括js生成的标签)生成内容树
2.构建渲染树: 解析对应的css样式文件信息(包括js生成的样式和外部的css)
3.布局渲染树:从根节点递归调用,计算每个元素的大小,位置等。给出每一个节点所在的屏幕的精准位置
4.绘制渲染树:遍历渲染树,使用UI后端层来绘制每个节点

重绘:当盒子的位置、大小以及其余属性,例如颜色、字体大小等到肯定下来以后,浏览器便把这些颜色都按照各自的特性绘制一遍,将内容呈如今页面上
触发重绘的条件:改变元素外观属性。如:color,background-color等
重绘是指一个元素外观的改变所触发的浏览器行为,浏览器会根据元素的新属性从新绘制,使元素呈现新的外观
注意:table及其内部元素须要屡次计算才能肯定好其在渲染树中节点的属性值,比同等元素要多发时间,要尽可能避免使用table布局

重排(重构/回流/reflow): 当渲染书中的一部分(或所有)由于元素的规模尺寸,布局,隐藏等改变而须要从新构建,这就是回流。
每一个页面都须要一次回流,就是页面第一次渲染的时候

重排必定会影响重绘,可是重绘不必定会影响重排


十3、为何css放在顶部而js写在后面
1.浏览器预先加载css后,能够没必要等待HTML加载完毕就能够渲染页面了
2.其实HTML渲染并不会等到彻底加载完在渲染页面,而是一边解析DOM一边渲染。
3.js写在尾部,主要是由于js主要扮演事件处理的功能,一方面不少操做是在页面渲染后才执行的。另外一方面能够节省加载时间,使页面可以更加的加载,提升用户的良好体验

可是随着JS技术的发展,JS也开始承担页面渲染的工做。好比咱们的UI其实能够分被对待,把渲染页面的js放在前面,时间处理的js放在后面

 

设计模式

1、观察者模式:https://juejin.im/post/5a14e9edf265da4312808d86 https://juejin.im/post/5af05d406fb9a07a9e4d2799
在软件开发设计中是一个对象(subject),维护一系列依赖他的对象(observer),当任何状态发生改变自动通知他们。强依赖关系
简单理解:数据发生改变时,对应的处理函数就会自动执行。一个Subjet,用来维护Observers,为某些event来通知(notify)观察者

2、发布-订阅者 有一个信息中介,过滤 耦合性低
它定义了一种一对多的关系,能够使多个观察者对象对一个主题对象进行监听,当这个主题对象发生改变时,依赖的全部对象都会被通知到。

二者的区别:
1.观察者模式中,观察者知道Subject ,二者是相关联的,而发发布订阅者只有经过信息代理进行通讯
2.在发布订阅模式中,组件式松散耦合的。正好和观察者模式相反。
3.观察者大部分是同步的,好比事件的触发。Subject就会调用观察者的方法。而发布订阅者大多数是异步的()
4.观察者模式须要在单个应用程序地址空间中实现,而发布订阅者更像交叉应用模式。

1004001111
数据结构和算法

1、两个栈实现一个队列,两个队列实现一个栈 https://www.cnblogs.com/MrListening/p/5697459.html

2、红黑树(解决二叉树依次插入多个节点时的线型排列) https://juejin.im/post/5a27c6946fb9a04509096248

3、最小栈的实现(查找最小元素,用两个栈配合栈内元素的下标)https://juejin.im/post/5a2ff8c651882533d0230a85

4、十大排序
1.冒泡排序:重复走访过要排序的数列,一次比较两个元素,若是他们的顺序错误就把它们交换过来。
实现过程:1.比较相邻的元素。若是第一个比第二个大,就交换他们两个
2.对每一对相邻元素做一样的工做,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数
3.针对全部的元素重复以上的步骤,除了最后一个
4.重复步骤1-3,直到排序完成。
2.选择排序:首先在未排序序列中找到最小值,放在排序序列的起始位置,而后,在从剩下未排序元素中继续寻找最小值,而后放在与排序序列的末尾
实现过程:

3.插入排序:构建有序序列,对于未排序数据,在已排序序列中冲后向前扫描,找到相应位置并插入
实现过程:1.从第一个元素开始,该元素能够认为已经被排序
2.取出下一个元素,在已排序的元素序列中冲后向前扫描
3.若是该元素(以排序)大于新元素,将元素向后移一位

4.桶排序:将数据分布到有限数量的桶里,每一个桶在分别排序

1.快速排序:快速排序使用分治法把一个串(list)分为两个子串(sub-lists).具体算法实现
实现过程:1.从数组中挑出一个元素,成为一个基准
2.从新排列数组,全部元素比基准小的摆在基准前面,全部元素比基准大的摆在基准后面(相同的能够摆在一边)
这个分区退出以后,该基准就处于数列的中间位置。成为分区操做。
3.递归的把小于基准值的子数列和大于基准值元素的子数列排序
算法实现: function quickSort (arr) {
if (arr.length <= 1) {return arr}
var destIndex = Math.floor(arr.length/2)
var left = [], right = [];
var dest = arr.splice(destIndex,1)[0];
for (var i =0;i<arr.length;i++){
if (arr[i]<dest) {
left.push(arr[i])
} else {
right.push(arr[i]) }
return quickSort(left).concat([dest],quickSort(right)

2.堆排序:利用对这种数据结构所涉及的一种排序算法,堆积是一个近乎彻底二叉树的结构,并同时知足堆积的性质:即子节点的键值或索引老是小于(或大于)它的父节点。
实现过程:1.

5、数组去重 https://juejin.im/post/5aed6110518825671b026bed#heading-6
1.双重循环
var arr=[1,3,6,1,3,5];
var newArr=[];
for(var i=0;i<arr.length;i++){
var flag=true;
for(var j=0;j<newArr.length;j++){
if(newArr[j]===arr[i]){
flag=false;
break
}
}
if(flag){
newArr.push(arr[i])
}
}
console.log(newArr)
2.indexOf
var arr=[1,3,6,1,3,5];
var newArr=[];
for(var i=0;i<arr.length;i++){
if(newArr.indexOf(arr[i])==-1){
newArr.push(arr[i]);
}
}
console.log(newArr)
3.数组排序去重 最快你Olong
var arr=[1,3,6,1,3,5];
var newArr=[];
arr=arr.sort();
for(var i=0;i<arr.length;i++){
if(arr[i]!=arr[i-1]){
newArr.push(arr[i]);
}
}
console.log(newArr);
4.ES6语法Set去重
var arr=[1,3,6,1,3,5];
console.log([...new Set(arr)]);
或者
console.log(Array.from(new Set(arr)));

6、字符串
判断回文字符串:(递归的思想)
1.字符串分隔,倒转,聚合[...obj].reverse().join('')
2.字符串头部和尾部,逐次向中间检测
实现:function isPalindrome(line) {
line += '';
for (var i=0,j=line.length-1;i<j;i++,j--) {
if (line.chartAt(i) !== line.chartAt(j) {
return false
}

3.递归

7、二分查找(有序数组的查找)
// 二分查找能够解决已排序数组的查找问题,即只要数组中包含T(要查找的值),那么经过不断的缩小包含T的数据范围,就能够最终要找到的数
// (1) 一开始,数据范围覆盖整个数组。
// (2) 将数组的中间项与T进行比较,若是T比数组的中间项小,则到数组的前半部分继续查找,反之,则到数组的后半部分继续查找。
// (3) 就这样,每次查找均可以排除一半元素,至关于范围缩小一半。这样反复比较,反复缩小范围,最终会在数组中找到T
代码实现:function binarySearch (data, dest, start, end){
var end = end || data.length-1;
var start = start || 0;
var m = Math.floor((start+end)/2);
if (dest<data[m]){
return binarySearch(data, dest,0, m-1)
} else {
return binarySearch(data, dest, m+1, end)
}}
return false

 

手写代码

1、动手实现一个bind(原理经过apply,call)
一句话归纳:1.bind()返回一个新函数,并不会当即执行。
2.bind的第一个参数将做为他运行时的this,以后的一系列参数将会在传递的实参前传入做为他的参数
3.bind返回函数做为构造函数,就是能够new的,bind时指定的this值就会消失,但传入的参数依然生效
Function.prototype.bind = function (obj, arg) {
var arg = Array.prototype.slice.call(arguments, 1);
var context = this;
var bound = function (newArg) {
arg = arg.concat(Array.prototype.slice.call(newArg);
return context.apply(obj, arg)
}
var F = function () {} // 在new一个bind会生成新函数,必须的条件就是要继承原函数的原型,所以用到寄生继承来完成咱们的过程
F.prototype = context.prototype;00.......................
bound.prototype = new F();
return bound;
}

2、 AJAX (异步的javascript和xml)
ajax的原理:至关于在用户和服务器之间加一个中间层(ajax引擎),使用户操做与服务器响应异步化。
优势:在不刷新整个页面的前提下与服务器通讯维护数据。不会致使页面的重载
能够把前端服务器的任务转嫁到客服端来处理,减轻服务器负担,节省宽带
劣势:不支持back。对搜索引擎的支持比较弱;不容易调试
怎么解决呢?经过location.hash值来解决Ajax过程当中致使的浏览器前进后退按键失效,
解决之前被人常遇到的重复加载的问题。主要比较先后的hash值,看其是否相等,在判断是否触发ajax
function getData(url) {
var xhr = new XMLHttpRequest(); // 建立一个对象,建立一个异步调用的对象
xhr.open('get', url, true) // 设置一个http请求,设置请求的方式,url以及验证身份
xhr.send() //发送一个http请求
xhr.onreadystatechange = function () { //设置一个http请求状态的函数
if (xhr.readyState == 4 && xhr.status ==200) {
console.log(xhr.responseText) // 获取异步调用返回的数据
}
}
}
Promise(getData(url)).resolve(data => data)

AJAX状态码:0 - (未初始化)尚未调用send()方法
1 - (载入)已调用send方法,正在发送请求
2 - (载入完成呢)send()方法执行完成
3 - (交互)正在解析相应内容
4 - (完成)响应内容解析完成,能够在客户端调用了


3、函数节流(throttle)
function throttle (func, wait) {
var timeout;
var previous = 0;
return function () {
context = this;
args = arguments;
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context,args)
}, wait);
}
}
}

}

4、函数防抖(dobounce)
function debounce (func, wait) {
var timeout;
return function() {
var context = this;
var args = arguments;
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context,args)
}, wait);
}
}

5、实现一个函数clone,能够对JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制

Object.prototype.clone = function() {
var newObject = this.constructor === Array ? [] : {} //对象的深拷贝 获取对应的构造函数 [] 或者 {}
for (let e in this) { //遍历对象的属性 in this[e]
newObject[e] = typeof this[e] === 'object' ? this[e].clone() : this[e] //对象中的属性若是仍是对象 那就继续递归 不然就返回基本的数据类型
}
return newObject
}

6、实现一个简单的Promise https://juejin.im/post/5b2f02cd5188252b937548ab
class Promise {
constructor (executor) { // executor里面有两个参数,一个叫resolve(成功),一个叫reject(失败)。
this.status = 'pending',
this.value = undefined;
this.reason = undefined;
// 成功存放的数组
this.onResolvedCallbacks = [];
// 失败存放法数组
this.onRejectedCallbacks = [];
let resolve = (value) => {
if (this.status == 'pending') {
this.status = 'resolve';
this.value = value;
this.onResolvedCallbacks.forEach(fn => fn())
}
}

let reject = (reason) => {
if (this.status == 'pending') {
this.status = 'reject';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn())
}
}
try{
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then (onFullFilled,onRejected) {
if (this.status == 'resolved') {
onFullFilled(this.value)
}
if (this.status == 'rejectd') {
onRejected(this.reason);
}
if (this.status == 'pending') {
this.onResolvedCallbacks.push(()=>{
onFullFilled(this.value);
})
this.onRejectedCallbacks.push(()=> {
onRejected(this.reason);
})
}

}
}

const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hello world')
}, 1000);
})
p.then((data) =>{
console.log(data)
},(err) =>{
console.log(err);
})

7、发布订阅者模式(观察者模式)

var event = {}; // 发布者
event.clientList = [] //发布者的缓存列表

event.listen = function (fn) { // 增长订阅者函数
this.clientList.push(fn)
}

event.trigger = function () { // 发布信息
for (var i =0;i<this.clientList.length;i++) {
var fn = this.clientList[i];
fn.apply(this, arguments);
}
}

event.listen (function(time) {
console.log('正式上班时间为:' +time)
})
event.trigger ('2018/7')

8、手动写一个node服务器const http = require('http');const fs = require('fs');const server = http.createServer((req,res) => { if (reu.url == '/') { const indexFile = fs.createReadStream('./index.html') req.writeHead(200,{'context-Type':'text/html;charset = utf8}) indexFile.pipe(res)}server.listen(8080)

相关文章
相关标签/搜索