(1)javaScript的基本数据类型包括:Boolean、Number、String、Null、Undefined.
(2)Es6中添加了新的数据类型Symbol数据类型。javascript
(1)原始值包括:undefined,null,boolean,number,String,Symbl
引用数据类型:Object(除了基本数据类型以外,其余数据都是引用数据类型,包括函数,对象。
(2)二者之间的区别在于 :一、基本数据类型的值是不能改变 二、基本数据类型是不能添加属性和方法 三、基本数据类型的赋值就是简单值赋值 四、基本数据类型之间的比较就是简单的值之间的比较.
(3) 引用数据类型:一、引用数据类型的值是能够改变的,二、能够添加属性和方法 三、引用数据类型的赋值是指针的赋值,4引用数据类型之间的比较是地址之间的比较,是否相同。
1、基本数据类型是指存放栈中简单的数据段,数据大小肯定,内存空间能够分配,他们是按值存放,因此能够直接访问
2、引用类型引用类型是存放在堆内存中的对象,变量实际上是保存在栈内存中一个指针,这个指针指向堆内存,引用数据类型在栈中存的变量实际上是在堆中对象的引用地址,经过这个引用地址能够快速找到保存中的对象。css
深拷贝和浅拷贝的区别在因而否获取到了一个真实的复制对象,而不是一个引用,深拷贝会在计算机内存中开辟一个空间用来存放复制对象,而浅拷贝仅仅指被拷贝的地址,若是源地址的对象被修改了,那么浅拷出来的地址也会被修改。html
浅拷贝实现的方法:(1)使用for .... in实现第一层的浅拷贝 (2)直接赋值(3)object.assign()前端
深拷贝实现的方法:(1)使用递归来拷贝全部级的属性(2)json来拷贝json.stringify(json.parse()) 缺点在于没法实现对象中方法拷贝会显示undefined,(3)jquery中extend方法也能够实现深度拷贝(4)lodash函数实现深度拷贝(5)用concat来实现数据的深度拷贝vue
js中判断数据类型的方法html5
(1)第一种方法typeof来判断方法 typeof能够返回number 、boolean、String、null、undefined,null返回的是object是一个空对象,function会返回function,undefined会返回undefined,java
(2)constructor能够判断,可是null和undefined是没法判断的node
(3)instanceof只适合对象的检测,不适合简单数据类型的检验react
instanceof实现的原理 A instanceof B 左边是一个实例,右边是一个构造函数, instaceof会检测右边构造函数的原型对象prototype是否在左边的实例的原型链上,有则返回true,没有则返回false.jquery
(4)jQuery.type()——称之为万能能够判断全部数据类型并且是正确的
箭头函数与普通函数的区别
第一点也是最重要的一点就是this指向的问题:
(1)箭头函数this指向他所在定义的对象中;普通函数this指向谁调用它的对象.
(2)箭头函数语法比较简洁
(3)箭头函数没有原型的概念,普通函数具备原型。
(4)箭头函数没有argruments参数,只有rests剩余参数。
(1)在调用函数做用域的时候,函数执行完毕,做用域就会被销毁,在函数做用域中能够访问全局的变量;而全局访问不到函数做用域的变量;在函数做用域中能够重复声明一个变量,存在变量提高。
(2)声明的变量在块级做用域中有效,一旦离开了块级做用中,该变量就会销毁;let 不容许在相同的做用域内重复声明一个变量,不然会报错;不存在变量声明提早,若是在声明以前使用,则会报错。
for ...in 遍历可枚举的数据,object.keys()object.value()这些方法
如何判断是否是数组?
1.instanceof的方式俩来判断是否是数组
2.isArray
3.constructor
1.将json对象转化为json字符串,再判断该字符串是否为"{}"
var data = {};
var b = (JSON.stringify(data) == "{}");
alert(b);//true
2.for in 循环判断
var obj = {};
var b = function() {
for(var key in obj) {
return false;
}
return true;
}
alert(b());//true
3.jquery的isEmptyObject方法
此方法是jquery将2方法(for in)进行封装,使用时须要依赖jquery
var data = {};
var b = $.isEmptyObject(data);
alert(b);//true
4.Object.getOwnPropertyNames()方法
此方法是使用Object对象的getOwnPropertyNames方法,获取到对象中的属性名,存到一个数组中,返回数组对象,咱们能够经过判断数组的length来判断此对象是否为空
注意:此方法不兼容ie8,其他浏览器没有测试
var data = {};
var arr = Object.getOwnPropertyNames(data);
alert(arr.length == 0);//true
5.使用ES6的Object.keys()方法
与4方法相似,是ES6的新方法, 返回值也是对象中属性名组成的数组
var data = {};
var arr = Object.keys(data);
alert(arr.length == 0);//true
类数组与数组的区别与转换
区别:类数组(1)具备length属性,可是不具备数组所具备的方法,它的索引是非负数的
类数组转换为数组:
(1)第一种方法,对于类数组进行遍历,依次放入到了一个空数组中
(2)第二种方法使用扩展运算符或者是Array.from
对于数组的操做 push 入栈,pop出栈,shift删除数组的第一个,unshift,添加数组的第一个
slice不会改变原来的数组,第一参数开始截取的索引,第二个参数截取的结束索引
splice 改变原数组 第一个开始的地址,第二个删除的数的个数,第三添加的
concat 链接数组 不改变原数组
indexOf 永远返回找到第一个数组的索引,
include 包含关系
fliter 过滤器 find
map forEach循环遍历
其中有一个小的知识点:
for in 和for of forEach ,for in 用来遍历可枚举的属性 经常使用来遍历对象,遍历的是键名,forEach 不能使用return,continue,break, for of用来遍历的数组,遍历的键值。
call 、bind、apply都是用来改变this的指向
call和apply的区别在于第二个参数,apply传递的是一个数组,call传递的一个数,
他们和bind的区别在于call,apply会就当即调用,bind不会当即调用,会返回一个绑定函数,执行须要再次调用
new的原理
第一步 会在函数种建立一个空的对象
第二部 设置新对象的)_proto_指向构造函数的原型
第三步 绑定this 使函数种的this指向新实例对象
第四步 将初始化完毕的对象的地址赋给左边的变量。
如何正确判断this?
this的指向包括五种:
一、默认绑定,
不管是否在严格模式下,在全局执行环境中,普通函数还有定时器的this都指向window
node 环境:
不管是否在严格模式下,在全局执行环境中(在任何函数体外部),this 都是空对象 {}
二、隐式绑定
当函数引用有上下文对象时,隐式绑定规则会把函数中的this绑定到这个上下文对象
隐式绑定某些状况下的this会指向window或者undefined
三、显示绑定
call,apply,bind 绑定中,this指向的就是绑定的对象【称为硬绑定】
四、new绑定
五、箭头函数this
箭头函数有两个方面的做用:更简短的函数而且不绑定this。
箭头函数没有本身的this,继承外层上下文绑定的this。
闭包:可以读取其余函数内部变量的函数,咱们称为闭包
做用:能够间接调用函数内部的局部变量,可让这些变量的值始终存储在内存中,能够暂存数据,给变量开辟私密空间,避免外部污染
1、原型是function对象的一个属性,它定义构造函数制造出的对象的公共对象,能够继承修改原型的属性。原型也是对象。更加通俗的理解就是每个javascript对象在建立的时候,都会与其余对象相关联。每一个对象都会继承原型的属性_proto_ :每个对象除了null以外都有了这个属性,这个属性都会指向原型
2、原型链:每个构造函数都有一个原型对象,原型对象都有包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么假设咱们冉安哥原型对象等于另外一个类型的实例,此时原型对象将包含另外一个原型的指针,相应的,另外一个原型中也包含着一个指向另外一个构造函数。加入另外一个原型又是另外一个原型的实例,那么上述关系依然成立。如此层层递进,就构成了实例域原型的链条。
第一种继承方式
原型链继承
很常见的继承方式:
function Animal(name)
{
this.name=name
}
function Cat()
{
console.log(this.name)
}
Cat.prototype=new Animal('动物')
let cat=new Cat();
console.log(cat.name)
特色:
一、很是纯粹的继承关系,实例是子类的实例,也是父类的实例
二、父类新增长的方法/属性,子类咱们均可以访问到
三、简单,易于实现
缺点:
一、要想为子类新增长和方法,必需要在new Animal()这样语句以后执行,不能放到构造器中
二、没法实现多继承
三、来自原型对象的全部属性被全部实例共享
四、子类建立实例的时候,没法向构造函数传递参数
构造继承
核心:使用父类的构造函数来加强子类实例,等于复制父类的实例属性给子类
function Cat()
{
Animal.call(this)
}
特色:
一、解决了1中,子类实例共享父类引用的问题
二、建立子类实例时,能够向父类传递参数
三、能够实现多继承
缺点:
一、实例并非父类的实例,只是子类的实例。
二、只能继承父类的实例属性和方法,不能继承原型的属性/方法
三、没法实现函数复用,每一个子类都有父类的实例函数的副本,影响性能
实例继承
核心:为父类实例添加新特性,做为子类返回
function Cat(name)
{
var instance =new Animal();
instance.name=name
return instance
}
特色:
一、不限致调用方式,无论是new 子类()仍是子类(),返回对象具备相同的效果
缺点:
一、实例是父类的实例,不是子类的实例
二、不支持多继承
拷贝继承
function Cat(){
var animal=new Animal();
for(var p in animal)
{
Cat.prototype[p]=animal[p];
}
Cat.prototype.name=name
}
特色:
一、支持多继承
缺点:
一、效率低,内存占用高
二、没法获取父类不可枚举的方法
组合继承
核心:经过调用父类构造,继承父类的属性而且保留传参的优势,而后经过父类实例做为子类原型,实现函数复用。
特色:
一、弥补了方式2的缺陷,能够继承实例属性/方法,也能够继承
第一种方法,经过双方统一约定—_name这样的形式,可是不可靠。
第二种方法,就是经过闭包实现的。
使用闭包和特权函数实现私有属性的定义和访问是不少开发者采用的方种方式。可是这种方式存在一些缺陷:
私有变量和特权函数只能在构造函数中建立。一般来说,构造函数的功能只负责建立新对象,方法应该共享于prototype上。特权函数本质上是存在于每一个实例中的,而不是prototype上,增长了资源占用。
第三种方法,weakMap实现。
第四种方法是经过Symbol
节流和防抖
函数防抖:
当持续触发事件时,必定时间内没有再触发事件,事件处理才会执行一次,若是设定时间到来以前,又触发事件,就从新开始延时。也就是说当一个用户一直触发这个函数,且每一次出发函数小于既定事件,那么防抖的请跨国下指挥执行一次。
当持续触发事件,保证在必定时间内只调用一次时间处理函数,假设一个用户一直触发这个函数,且每次胡出发小于即定值,
应用场景:
执行上下文环境:
通俗的来讲就是在代码执行以前,把要用到的全部变量,都事先拿出来,有的直接复制,有的先用undefined先占着
执行上下文能够理解为做用域,可是二者之间又有区别:
一、全局做用以外,每个函数都会建立本身的做用域,做用域在函数定义时已经确认了,而不是函数在带哦用时。
全局执行上下文是在全局做用肯定以后,js代码立刻执行以前建立。
做用域是静态的,只要定义好了以后就一直存在,而且不在发生改变,而且不在发生变化。
执行上下文时动态的,调用函数建立,调用极少数后就自动释放了
做用域:就是变量和函数访问的范围。
上下文:主要是关键字this的值,这个是由函数运行时决定的,简单来讲就是谁调用此函数,this就指向谁。
做用域链:做用域链本质上是一个指向当前环境与上层环境的一系列变量对象的指针列表(它只引用但不实际包含变量对象),做用域链保证了当前执行环境对符合访问权限的变量和函数的有序访问。也就是咱们所指[[scope]]中执行上下文的集合,。
dom的增删改查:
dom的查找:
getELementById()//返回匹配指定id属性的元素节点。
getElementsByTagname//返回匹配指定html标签的元素
getElementsByClassname//返回匹配指定class属性的元素节点
document.getElementsByName(name) //用于选择拥有name属性的HTML元素(好比<form>、<radio>、<img>、<frame>、<embed>和
<object>等)
ocument.querySelector(selectors) //接受一个CSS选择器做为参数,返回第一个匹配该选择器的元素节点。
document.querySelectorAll(selectors) //接受一个CSS选择器做为参数,返回全部匹配该选择器的元素节点。
https://www.cnblogs.com/huan0317/p/9225707.html详情请打开此链接
Ajax的请求过程
ajax是客户端与服务器异步通讯的技术
第一步 建立xmlhttprequest对象,IE浏览器存在兼容性问题 xmlhttp=new xmlhttprequest
第二步 向服务器发送请求
“GET,POST”
xmlhttp.open("post",url,true);
第三步 执行回调函数
xmlhttp,onreadystatechanfe=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200) { //就能够执行相应的操做 document.getElementById("myDiv").innerHTML=xmlhttp.responseText; }
}
readystate值
0--------------请求未初始化
1---------------服务器已创建
2--------------发送请求‘
3--------------请求处理中
4--------------请求已完成,且响应就绪
状态码就绪:
200 服务器成功返回
301 临时定向
304 缓存
404 资源找不到
ajax的优势
1、无刷新更新数据
2、异步与服务端通讯
3、先后端负载均衡。(减轻服务器的负担,AJAX的原则是“按需取数据”, 能够最大程度的减小冗余请求和响应对服务器形成的负担)
4、基于标准被普遍支持
5、界面与应用分离
ajax的缺点:一、干掉back和history,破坏了浏览器机制
二、ajax自己有安全问题
三、违背了url和统一资源定位的初衷
四、客户端过肥,太多客户端代码形成了开发成本的问题
一、js的垃圾回收机制有两种形式一种是标记清楚发和引用计数法。
标记清除法,简单的来讲就是给各个变量名打上YES or NO的标签。在和执行上下文相似的环境中当变量名进入环境的时候,那么变量会被打上YES.通常来讲是绝对不会释放被打上yes的标签,一旦变量出了环境就会被打上NO的标签,js引擎会在必定时间或者设置必定时间来进行扫描,对NO标签进行剔除以及释放其内存。
二、引用计数法:引用技术的含义是跟踪纪律每个值被引用的次数。当声明一个变量并将一个引用类型值赋给变量时,则这个值的引用次数即是1,若是同一个值又被赋给另外一个之,则该值的引用次数加一,相反,若是包含对这个值引用的变量又取得另外一个值,则这个值引用次数减一,当这个值的引用次数为0时,说明没有办法访问它,于是能够将其占据的内存空间收回
addEventListener和onClick()的区别
js事件绑定有三种方法:
一、行内绑定
二、动态绑定
三、事件监听
1、行内绑定
<标签 属性列表 事件=“事件的处理程序”/>
2、动态绑定
基本语法:
dom对象.事件=事件的处理程序
dom绑定和行内绑定的区别在于dom绑定的对象是dom对象this--->dom,行内绑定指定的是window
addEventlistener 来绑定的,有三个参数,第一个监听的时间名,第二个回调函数,第三个true事件捕获,false事件冒泡
new和Object.create的区别
咱们建立对象的方法 有两种Object.create和new两种方式
new的全过程是用构造函数,先建立一个空对象,而后将对象的_pro_to指向构造函数的原型,绑定this,是构造函数中this指向该实例。
Object.create = function (Base) {
var F = function () {};
F.prototype = Base;
return new F();
};
以下图所示,首先建立一个空函数F,函数的prototype指向Base函数。new一个函数的实例,即让该实例的_proto_指向函数F的prototype,也就是Base函数,最后将该实例返回。即经过Object.create建立的对象o2,实际上完成了o2._proto_ = Base的操做。注意传入的参数Base2是一个对象。若是传入的是一个构造函数的话,该实例是没法继承的。
DOM的location对象
navigator的做用
-navigator对象的做用包含有官浏览器的信息,经常使用于获取客户端和浏览器,经常使用属性
-location对象包含有关当前URL的信息,经常使用于获取和改变当前浏览器的网址
window.location.href='';
history对象包含用户(在浏览器窗口中)访问过url的历史记录
length 返回浏览器历史列表中url数量
back()加载history列表中的前一个URL。
forward () 加载列表中的下一个url
go() 加载history列表中的某一个列表
csrf攻击者在用户登陆目标网站以后,诱使用户点击攻击界面,以用户信息在攻击界面向目标网站发起请求的时候,达到攻击目标。CSRF攻击是源于web的隐式身份验证机制!web的身份验证虽然能够保证一个请求是来源于某一个用户的浏览器,可是却没法保证该请求是用户批准发送的。csrf攻击的通常是服务器来解决。
scrf的危害:盗取或者修改帐号,我的身份信息泄露以及财产安全,对于用户的帐号进行操做
CSRF工具的防护手段
(1)尽可能使用post请求,少用get请求?
(2)验证referer(HTTP Refere是header的一部分,当浏览器向web服务器发送请求的时候,会带上Refere,经过验证Referrer,能够判断请求的合法性,若是Referer是其余网站的话,就有多是CSRF,则拒绝该请求)
(3)验证码(验证码,强制用户必需要与用户进行交互,才能完成最终请求)
四、使用token(这个Token的值必需要是随机,不可预测的。因为Token的存在,攻击者没法再构造一个带有合法Token的请求)
在浏览器输入一个地址回车以后,该请求会被转发到DNS服务器,DNS服务器解析域名
DNS域名解析
根DNS服务器 >顶级域名服务器> 权威DNS服务器>二级域名服务器
在浏览器中输入url按下回车的整个过程
一、把输入的url域名dns解析称为ip地址
二、浏览器向IP法案送请求信息(包括请求头Request Headers和请i去Request Body)
三、服务器向浏览器回应一个响应头()
1.先向本地dns缓存查看有没有该域名对应的ip地址,有直接跳出,没有接着往下
2.向根dns服务器询问域名对应的ip地址(根dns服务器会让他去查询顶级dns服务器)
3.向顶级dns服务器询问域名对应的ip地址(顶级dns服务器会让他去查询权威dns服务器)
4.向权威dns服务器询问域名对应的ip地址(权威dns服务器会让他去查询二级dns服务器)
5.向二级dns服务器询问域名对应的ip地址(二级dns服务器会返回对应的ip地址)
6.接收到ip地址后,会先把ip和域名对应关系保存到本地dns缓存,以便下次方便访问
在服务的短由web Server来接受请求,=并进行相应的处理,而后响应结果给客户端浏览器
浏览器接收到响应的结果,并进行相应的语法检查,若是由错误,可能会提示错误,若是没有错误,就进行渲染
渲染的时候生成DOM树,而后更具css和js生成渲染树(渲染树中的结构每每比DOM树要少,由于有些dom树中元素若是隐藏的话,不会出如今渲染树中)最后再渲染出来
都能实现异步加载,延迟加载js
defer下载完成以后等着,dom结构渲染完成(也就是页面解析完成),才执行,理论上能够保证文件执行顺序
async 下载完成以后当即执行,不能保证文件加载顺序
<!DOCTYPE>对于大小并不铭感,它须要声明在HTML文档的第一行,位于html标签以前,
<!DOCTYPE>声明的并非HTML标签,它是指示web浏览器关于页面使用那个HTML版本进行编写.
在HTML 4.01中,<DOCTYPE> 声明引用 DTD,由于 HTML 4.01 基于 SGML。DTD 规定了标记语言的规则,这样浏览器才能正确地呈现内容。 HTML5 不基于 SGML,因此不须要引用 DTD。 DOCTYPE都是标准的文档类型,不管使用哪一种模式完整定义DOCTYPE,都会 触发标准模式,而若是DOCTYPE缺失则在ie6,ie7,ie8下将会触发怪异 模式(quirks 模式)
一、双倍浮动bug
描述:块状元素在设置float属性以后,有设置横向的margin值,在IE6下显示的margin值比设置的值大;
解决方案:给float的元素添加一个display:inline;将其转换为内联元素
二、表单元素行高不一致
解决方案:
一、给表单元素添加vertical-align:middle
二、给表单元素添加float:left;
三、IE6默认16px为最小不识别较小高度的标签 (通常为10px)
解决方案
一、给标签添加overflow:hidden;
二、给标签添加font-size:0
四、图片添加超连接时,在IE浏览器中会有蓝色的边框
解决方案:border:0或者border:none
五、最小高度不兼容IE6
解决方案:
一、min-height:100px;_height:100px;
二、min-height:100px,height:auto !importang;height:100px
六、图片有间隙:
解决方案:
一、给img添加float属性;
二、img添加display:block;
### 2八、H5的新特性总结
1.新增长的选择器document.queryselect和document.queryselectall这二者的区别在于,第一个获得一个dom元素,另外一个获得一个类数组。
2.本地存储localstorage和sessionStorage
3.语义化标签例如header、footer、section等标签
4.全双工通讯webscket
5.跨域资源共享CORS Access-Control-Allow-Origin
6.跨窗口通讯postmessage
7.回话canvas
8.加强表单控件calendar、date、time、email、url
(1)display属性规定元素生成框的类型。较为常见的有none-缺省值(用于隐藏元素,元素会消失于视界和文档流中),block-块级元素,inline-block-行内块级元素,list-item列表样式块级元素……….
(2)position属性规定元素的定位类型,经常使用于布局。static-默认值,元素出如今正常文档流中(此时不受top、left、right、bottom、z-index等属性影响);absolute-绝对定位,脱离文档流,相对于它第一个非static父元素进行定;fixed-固定定位,相对于浏览器窗口进行定位;relative生成相对定位的元素,相对于其正常文档流中的位置进行定位。
(3)float属性,定义一个元素浮动方向,最初用于图像使文本环绕,如今是一种布局方式。不论浮动元素自己是何种框类型,浮动后会生成一个块级框。
1.display值为none
当元素display值为none时,元素不产生框,float和position都不起做用。
2.position是absolute或fixed
当元素display值不为none,而position是absolute或者fixed时,此时float不起做用,计算值也为none(原文中有计算方法,这里略去),display值会按上表设置。元素框的位置由top、left、right、bottom值和其父元素决定。
3.float值不为none
当元素有了浮动属性(float不为none,是left或right)后,该框浮动且display值会按上表转换。例如,span是行内元素,设置浮动后会变为块级元素。
4.元素为根元素
若是元素是根元素,设置的display也会按上表进行转换。不然,元素的display值为指定值或默认值。
一:css3选择器
1 .基本选择器
2.属性选择器
3.伪类选择器
二:css3边框和圆角
1.css3圆角border-radius
2.盒阴影box-shadow
三:css3背景和渐变
background-image
四:css变化
定义:让一个元素在一个坐标中变形,这个属性包含着一系列的函数变化,能够移动,旋转,缩放元素。
五:css3过分
定义:容许你css的属性值在必定时间区内平滑的过分,在鼠标滑过或者元素任何改变中触发。
六:css3动画
定义:使元素从一种样式逐渐变化成另外一种样式。
变量:能够将属性的值赋值给一个变量,变量为彻底的常量,因此只能定义一次
混合:将一些通用的属性放在一个class中,而后在例外一个class中去调用这些属性。任何的class和id或是元素均可以用这样的方式进行引入。 嵌套规则:
运算:(1)任何数字、颜色均可以参与运算(2)less运算可以分辨颜色和单位
函数:(1)less自己提供了一系列的颜色运算函数。颜色会被转化成为HSL色彩空间,而后在通道级别操做。
一、less
Less 是一门 CSS 预处理语言,它扩展了 CSS 语言,增长了变量、Mixin、函数等特性,使 CSS 更易维护和扩展,它能够运行在 Node 或浏览器端。
二、sass
Sass 是一款强化 CSS 的辅助工具,它在 CSS 语法的基础上增长了变量 、嵌套 、混合 、导入 等高级功能,这些拓展令 CSS 更增强大与优雅。使用 Sass 以及 Sass 的样式库(如Compass)有助于更好地组织管理样式文件,以及更高效地开发项目。
2、less和sass的相同之处
Less和Sass在语法上有些共性,好比下面这些:
一、混入(Mixins)——class中的class;
二、参数混入——能够传递参数的class,就像函数同样;
三、嵌套规则——Class中嵌套class,从而减小重复的代码;
四、运算——CSS中用上数学;
五、颜色功能——能够编辑颜色;
六、名字空间(namespace)——分组样式,从而能够被调用;
七、做用域——局部修改样式;
八、JavaScript 赋值——在CSS中使用JavaScript表达式赋值。
3、less和sass的区别
Less是基于JavaScript,是在客户端处理的。
Sass是基于Ruby的,是在服务器端处理的。
关于变量在Less和Sass中的惟一区别就是Less用@,Sass用$。
输出设置,Less没有输出设置,Sass提供4中输出选项:nested, compact, compressed 和 expanded。
Sass支持条件语句,能够使用if{}else{},for{}循环等等,而Less不支持。
1.display:none 让元素渲染树种中消失,可是不占具任何空间。visibility:hidden不会让元素从渲染树种消失,消失仍然占据空间,只是内容不可见
2.display:none;是非继承属性,子孙节点消失是由于元素在渲染树中消失了,经过修改子孙元素的属性没法将他们显示出来;visibility:hidden;是继承属性,子孙元素消失是由于继承了hidden属性,将他们设置为visible时,这些子孙元素能够显示出来。
3.读屏器不会读取display:none;的元素内容,会读取visibility:hidden;内容。
4.display:none;会引发回流和重绘,visibility:hidden;会引发重绘。
css具备继承的特性,例如父元素设置了字体颜色,子元素的字体颜色和父元素是同样的;
css具备层叠性:
、CSS 的规则是全局的,任何一个组件的样式规则,都对整个页面有效。相信写css的人都会遇到样式冲突(污染)的问题。
二、为了解决全局污染的问题,那就把class命名写长一点吧、加一层父级选择器、下降冲突的概率,那么CSS命名混乱了
三、组件依赖管理不完全,组件应该相互独立,引入一个组件时,应该只引入它所须要的 CSS 样式。
四、代码难以复用,出现了sass less 之类的工具
et 定义变量,const(定义常量)块级做用域之对于let,const有用 ,arrow箭头函数,class,promise,map,set,结构赋值,
(1)let,const ,若是区块中存在let,const命令,则这个区块对这些命令的变量声明的变量,从一开始造成封闭做用域。只要在声明以前使用这些就会报错,就造成了暂时性死区。
(2)const 实际上保证的并非变量值的值不得改动,而是保证变量指向的那个的内存地址不得改动。对基本数据类型来讲,值就保存在内存地址空间中,因同等于常量。但对于复合类型的数据主要是对象和数组,变量指向的内存空间保存的是一个地址,const只能保证地址空间不变,而至于他所指的数据结构是没法控制的
1)git 中有工做区、缓存区、本地仓库,远程仓库
(2)git add 提交到缓存区,能够使用使用git status来查看工做区状态
(3)git commit -m '精神' 提交到本地仓库
git push -u orign master
拉去合并分支的操做:git fetch/git merge或者git pull
(4)这里有个重点:
git fetch 和git pull 的区别
一、git fetch 至关因而从远程获取最新版本到本地,不会自动merge,
二、git pull 至关于从远程获取最新版本并merge到本地,在实际使用中,git fetch更安全一些
(5)操做失误,撤销操做 git reset
(6)git stash 使用状况是
1、解决冲突问题,会先执行git stash ,而后解决冲突
2、遇到紧急开发任务但目前任务不能提交时,会先执行git stash ,r而后进行紧急任务的开发,而后经过git stash pop 取出战区的内容继续开发
3、 切换分支时,当前工做空间内容不能提交时,会先执行git stash 再进行分支切换
(7)git log 查看分支提交的历史记录
(8)能不能说一下git fetch和git pull命令之间的区别
简单的来讲就是git fetch branch 是把名为branch的远程分支拉取到本地;而git pull branch是在fetch的基础上,把branch分支与当前的分支进行merge ;所以 pull=fetch+merge
(9)使用过git merge和git rebase 吗? 他们之间有什么区别吗
git merge和git rebase都是合并分支的命令
git merge branch会把branch分支的差别内容pull到本地,而后与本地分支的内容一并造成一个committer对象提交到主分支上,合并后的分支与主分支一致;
git rebase branch会把branch分支优先合并到主分支,而后把本地分支的commit放在主分支后面,合并后就好像从合并后主分支又拉一个分支同样,本地分支自己不会保留提交历史。
一个promise可能有三种状态:等待(pending)、已完成(resolved),已拒绝(reject);
一个promise的状态只能从''等待'状态转到“完成”或者"拒绝",不能逆向转换,同时“完成”态和拒绝态不能相互转换
Promise.then(接受两个回调函数),解决函数嵌套的问题
有promises对象,就能够将异步操做以同步操做的流程表达出来,避免了层层嵌套.
Promise 的all方法提供了并行执行异步操做的能力,而且在全部异步操做执行完成才执行回调。传入的是一个数组
Promise.race,谁执行的快,以谁为准。
他是http请求方式的两种
get是请求,post是提交
get的数据较小主要是收到地址栏的限制,post的数据量很大
get是在请求头,放在地址栏不安全,post是在包体里,相对安全
http请求方式有8种请求方式
options 容许客户端查看服务器性能
1、为何会出现options请求呢?
跨域请求中,options请求是浏览器自发起的preflight request(预检请求),以检测实际请求是否能够被浏览器接受。
preflight request请求报文中有两个须要关注的首部字段:
(1)Access-Control-Request-Method:告知服务器实际请求所使用的HTTP方法;
(2)Access-Control-Request-Headers:告知服务器实际请求所携带的自定义首部字段。
同时服务器也会添加origin header,告知服务器实际请求的客户端的地址。服务器基于从预检请求得到的信息来判断,是否接受接下来的实际请求。
服务器所返回的Access-Control-Allow-Methods首部字段将全部容许的请求方法告知客户端,返回将全部Access-Control-Request-Headers首部字段将全部容许的自定义首部字段告知客户端。此外,服务器端可返回Access-Control-Max-Age首部字段,容许浏览器在指定时间内,无需再发送预检请求,直接用本次结果便可。
在咱们开发过程当中出现的浏览器自发起的options请求就是上面的第二种状况。实际上,跨域请求中的”复杂请求”发出前会进行一次方法是options的preflight request。
2、当跨域请求是简单请求时不会进行preflight request,只有复杂请求才会进行preflight request。
跨域请求分两种:简单请求、复杂请求;
符合如下任一状况的就是复杂请求:
1.使用方法put或者delete;
2.发送json格式的数据(content-type: application/json)
3.请求中带有自定义头部;
除了知足以上条件的复杂请求其余的就是简单请求喽!
3、为何跨域的复杂请求须要preflight request?
复杂请求可能对服务器数据产生反作用。例如delete或者put,都会对服务器数据进行修改,因此在请求以前都要先询问服务器,当前网页所在域名是否在服务器的许可名单中,服务器容许后,浏览器才会发出正式的请求,不然不发送正式请求。
Access-Control-Allow-Credentials", "true"跨域携带容许
get 请求指定页面,并返回实体主体
head 相似get请求,只不过返回的响应中没有具体的内容,用于获取报头
post 向指定资源提交数据进行处理(例如提交表单或者上传文件)数据被包含在请求中,post请求请求可能会致使资源的创建和已有资源的修改
put 从客户端向服务器传送的数据取代指定的文档内容
delete 请求服务器删除指定页面
connect http1.1协议中预留给可以未来凝结改造为管道方式的代理服务器
trace 回显服务器收到的请求,主要用于测试或诊断
跨域问题的存在主要是由于存在js同源协议,同源的条件:
一、协议相同
二、端口相同
三、域名相同
同源政策的目的为了保证用户信息的安全,防止恶意的网站窃取数据。
第一种解决办法:jsonp
img 的src属性,link 的src属性,还有script 的src属性不遵照同源策略。
原理就是利用script能够加载能够跨域加载别的域文件,建立一个回调函数而后在远程服务上调用这个函数而且将JSON 数据形式做为参 数传递,完成回调。
第二种方法:document.domain+iframe跨域
实现原理:两个页面都是经过js强制设置document.domain为基础主语,就实现了同域
第三种实现方法 location.hash+iframe跨域
实现原理 a欲与b跨域相互通讯,经过中间页来实现。三个页面,不一样域之间利用iframe 的location.hash传值,相同域之间直接用js访问通讯
具体实现:A域:a.html ->B域:b.html->A域:c.html,a与b不一样域之间只能经过hash值单向通讯,b与c也不一样域也只能单项通讯,但c与a同域,因此可经过parent.parent访问a页面全部对象
第四种实现方法
window.name+iframe;
window.name属性的独特之处:name值在不一样的页面(设置在不一样域名)加载以后,依旧存在,而且能够支持很是常name的值
五 h5的新特性 postMessage
postMessage 是HTML 5XMLRequest Level 的API,且是位数很少能够跨域操做的window属性之一,它能够用于解决一下问题
一、页面和其打开的新窗口的数据传递
二、多窗口之间消息传递
三、页面与嵌套的iframe消息传递
用法:postMessage(data,origin)方法接受两个参数
data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,因此传参时最好用JSON.stringify()序列化。
origin: 协议+主机+端口号,也能够设置为"*",表示能够传递给任意窗口,若是要指定和当前窗口同源的话设置为"/"
第六种方法 COMET(这是一种高级AJAX技术 常常也有人称为“服务器推送”技术)
第七种方法:CORS
它容许浏览器向跨域服务器,发出XMLHtttpRequest请求,从而克服了ajax只能够在同源中使用的限制
实现CORS通讯的关键在于服务器,只要服务器实现CORS接口,就能够跨域通讯,对于简单请求,浏览器直接发出CORS请求。具体来讲就是在头信息中增长一个Origin字段
非简单请求是那种对服务器有特殊要求的请求,好比说请求的方式是PUT或者DELETE,或者Content-Type字段的类型是application/json.
非简单请求的cors请求,会在正式通讯以前,增长一次http查询请求,称为预检,浏览器先询问服务器,当前网页所在的域名是否在服务器可许的名单之中,以及能够使用哪些HTTP信息字段。只有获得确定以后,浏览器才会发出正式XMLhttpRequest请求,
jsonp只支持GET请求,CORS支持全部类型的HTTP请求,
第八种方法 WebSocket协议跨域
websocket 是HTML5一种新协议,它实现了服务器和浏览器全双工通讯,同时容许跨域通信。
重点:
cookie和session的区别
一、存储位置不一样
cookie 的数据信息存放在客户端浏览器上
session的数据信息存放在服务器上
二、存储容量不一样
单个cookie保存的数据<=4kb,一个站点最多保存20个cookie
session 大约有5M
三、cookie能够跟随着前台请求发送到后端,session不行
四、session的运行依赖session_id ,而session_id存放在cookie,若是浏览器禁止了cookie的话,咱们session将没法运行
五、安全问题
cookie对于客户端来讲是可见的,别有用心的人,能够分析本地cookie,进行cookie欺骗,因此它是不安全的
session存储在服务器上,对于客户端来讲是透明,不存在敏感信息泄露的风险
六、cookie支持跨域访问,session不支持跨域访问
cookie 和sessionstorage localstorage的区别
一、有效期不一样:sessionStorage 当浏览器关闭以前有效,localstorage 始终有效果,不管浏览器是否关闭,
cookie 只要设置的事件不过时就一致存在,不管是否关闭浏览器
二、做用域不一样 sessionStorage 不在不一样浏览器共享,即便在同一个页面,local storage和cookie都是在全部同源窗口均可以访问。
三、大小cookie的大小为4k,sessionStorage和lcoalstorage大小为5M,cookie能够在浏览器和服务器之间来回切换,sessionStorage和cookieStorage不会把数据发送给服务器,仅在本地保存,cookie数据具备路径的概念path。
canvas
一、依赖分辨率(标量)
二、不支持事件处理器,不能被抓取
三、弱化文本能力
四、能够最终保存为图片png或者jpg
五、最适合许多对象频繁重画的图形游戏
svg
一、独立于分辨率(矢量)
二、支持事件处理器
三、最适合具备大面积渲染的应用
四、复杂图像,重画变慢
五、不适合游戏开发
基于TCP/ip协议 双向的,全双工通讯
双向的 客户端、服务端
全双工:数据的接受与发送,二者同步
<首先Websocket是ws协议,可是是基于HTTP协议的,借用了HTTP的协议来完成一部 分握手。这段相似HTTP协议的握手请求中,多了几个东西。 这个就是Websocket的核心了,告诉 Apache 、 Nginx 等服务器:注意啦,我发 起的是Websocket协议,快点帮我找到对应的助理处理~不是那个老土的HTTP。 至此,HTTP已经完成它全部工做了,接下来就是彻底按照Websocket协议进行了。 可是Websocket只须要一次HTTP握手,因此说整个通信过程是创建在一次链接/状 态中,也就避免了HTTP的非状态性,服务端会一直知道你的信息,直到你关闭请 求,这样就解决了接线员要反复解析HTTP协议,还要查看identity info的信息。 服务端就能够主动推送信息给客户端啦!> 在传统的方式上,要不断的创建,关闭HTTP协议,因为HTTP是非状态性的,每次 都要从新传输 identity info (鉴别信息),来告诉服务端你是谁。
long poll: 客户端发起链接后,若是没消息,就一直不返回Response给客户端。直到有消息 才返回,返回完以后,客户端再次创建链接,周而复始。 其实原理跟 ajax轮询 差很少,都是采用轮询的方式,不过采起的是阻塞模型 (一直打电话,没收到就不挂电话)
ajax轮询 须要服务器有很快的处理速度和资源。(速度)long poll 须要有很高 的并发 哦对了,忘记说了HTTP仍是一个状态协议。 通俗的说就是,服务器由于天天要接待太多客户了,是个健忘鬼,你一挂电话, 他就把你的东西全忘光了,把你的东西全丢掉了。你第二次还得再告诉服务器一 遍。
一、https协议须要ca证书,通常免费证书较少,须要必定费用
二、http是超文本传输协议,https是具备安全性的ssl加密传输协议
三、http和https是彻底不一样的链接方式,用的端口也不同,http是80端,https默认是443
前端缓存分为两类,一类是浏览器缓存,另外一类是http缓存
http缓存只能缓存get请求响应的资源,第二次请求时,浏览器判断这些请求参数,命中强缓存就直接200,不然就把请求参数加到request header头中传给服务器,看是否命中协商缓存,命中则返回304,不然服务器会返回新的资源。
http缓存分为强缓存和协商缓存;强缓存包括:progma和cache-control expires http状态吗200
协商缓存包括 Etag\If-not-match last-modifid/if-modified-Since 返回状态是304.
强制缓存在缓存数据未失效的状况下(即Cache-Control的max-age没有过时或者Expires的缓存时间没有过时),那么就会直接使用浏览器的缓存数据,不会再向服务器发送任何请求。强制缓存生效时,http状态码为200。
当第一次请求时服务器返回的响应头中没有Cache-Control和Expires或者Cache-Control和Expires过时还或者它的属性设置为no-cache时(即不走强缓存),那么浏览器第二次请求时就会与服务器进行协商,与服务器端对比判断资源是否进行了修改更新。若是服务器端的资源没有修改,那么就会返回304状态码,告诉浏览器能够使用缓存中的数据,这样就减小了服务器的数据传输压力。若是数据有更新就会返回200状态码,服务器就会返回更新后的资源而且将缓存信息一块儿返回。跟协商缓存相关的header头属性有(ETag/If-Not-Match 、Last-Modified/If-Modified-Since)请求头和响应头须要成对出现。
当浏览器第一次向服务器发送请求时,会在响应头中返回协商缓存的头属性:ETag和Last-Modified,其中ETag返回的是一个hash值,Last-Modified返回的是GMT格式的最后修改时间。而后浏览器在第二次发送请求的时候,会在请求头中带上与ETag对应的If-Not-Match,其值就是响应头中返回的ETag的值,Last-Modified对应的If-Modified-Since。服务器在接收到这两个参数后会作比较,若是返回的是304状态码,则说明请求的资源没有修改,浏览器能够直接在缓存中取数据,不然,服务器会直接返回数据。
不访问服务器,直接读缓存,从内存中读取缓存。此时的数据时缓存到内存中的,当kill进程后,也就是浏览器关闭之后,数据将不存在。
可是这种方式只能缓存派生资源。
不访问服务器,直接读缓存,从磁盘中读取缓存,当kill进程时,数据仍是存在。
这种方式也只能缓存派生资源
访问服务器,发现数据没有
更新,服务器返回此状态码。而后从缓存中读取数据。
MVVM,将数据模型数据双向绑定的思想做为核心,由于在view和model之间没有关联,经过viewModel进行交互,并且Model和viewModel之间交互是双向的,所以视图的数据的变化同时修改数据源,而数据源的变化会当即反映在View上。
MVC是比较直观的架构,用户操做->View(负责接受用户的输入操做)->(数据持久化)->View(将结构反馈给view)
MVP:MVP是把MVC中的Controller换成了Presenter(呈现),目的就是为了彻底切 断View跟Model之间的联系,由Presenter充当桥梁,作到View-Model之间通讯的 彻底隔离。
第一种方法:经过媒体查询的方式来完成适配
第二种方式:flex布局的方式 {高度固定死,宽度自适应,单位都采用px为单位}
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
第三种方式:rem+viewport
第四种方式:rem
如何来撰写rem;
假设咱们以320*758为手稿的话,假设咱们这是html font-size大小为16px ,那么设计稿/font-szie=20 在这里1rem=16px;
咱们能够随时的获取到屏幕宽度,而后除以这个倍数,就能够达到适配
媒体查询:经过查询设备的宽度来执行不一样的css代码,最终到达界面的配置。
一、缘由是由于双击缩放的问题,因为用户能够进行双击缩放或者是单击跳转页面,当用户一次点击屏幕以后,浏览器不能当即判断用户是肯定打开这个链接仍是想进行双击操做,因此等待300ms来判断
解决方法:
1、#### faskclickhttps://github.com/ftlabs/fastclick
原理: 在检测到touchend事件的时候,会经过DOM自定义事件当即出发模拟一个click事件,并把浏览器在300ms以后真正的click事件阻止掉
2、 禁用游览器缩放
<meta name="viewport" content="user-scalable=no"> <meta name="viewport" content="initial-scale=1, maximum-scale=1">
代表这个页面是不可缩放的,那双击缩放的功能就没有意义了,此时浏览器能够禁用默认的双击缩放行为而且去掉300ms的点击延迟。
这个方案有一个缺点,就是必须经过彻底禁用缩放来达到去掉点击延迟的目的,然而彻底禁用缩放并非咱们的初衷,咱们只是想禁掉默认的双击缩放行为,这样就不用等待300ms来判断当前操做是不是双击。可是一般状况下,咱们仍是但愿页面能经过双指缩放来进行缩放操做,好比放大一张图片,放大一段很小的文字。
3、更改默认的视口宽度
<meta name="viewport" content="width=device-width">
一开始,由于双击缩放主要是用来改善桌面站点在移动端浏览体验的。 随着发展示在都是专门为移动开发专门的站点,这个时候就不须要双击缩放了,因此移动端浏览器就能够自动禁掉默认的双击缩放行为而且去掉300ms的点击延迟。若是设置了上述meta标签,那浏览器就能够认为该网站已经对移动端作过了适配和优化,就无需双击缩放操做了。
这个方案相比方案一的好处在于,它没有彻底禁用缩放,而只是禁用了浏览器默认的双击缩放行为,但用户仍然能够经过双指缩放操做来缩放页面。
假如页面上有两个元素A和B。B元素在A元素之上。咱们在B元素的touchstart事件上注册了一个回调函数,该回调函数的做用是隐藏B元素。咱们发现,当咱们点击B元素,B元素被隐藏了,随后,A元素触发了click事件。
这是由于在移动端浏览器,事件执行的顺序是touchstart > touchend > click。而click事件有300ms的延迟,当touchstart事件把B元素隐藏以后,隔了300ms,浏览器触发了click事件,可是此时B元素不见了,因此该事件被派发到了A元素身上。若是A元素是一个连接,那此时页面就会意外地跳转。
ES6代码输入 ==》 babylon进行解析 ==》 获得AST
==》 plugin用babel-traverse对AST树进行遍历转译 ==》 获得新的AST树
==》 用babel-generator经过AST树生成ES5代码
当用户第一次经过浏览器使用用户名和密码来访问服务器,服务器验证用户数据,验证成功以后再服务端写入session数据,向客户端浏览器返回sessionid,浏览器将sessionid保存在cookie中,当用户再次访问服务器时,会携带sessionid,服务器会拿着sessionid从数据库中获取数据,而后对于用户查询信息,查询到,就会将查询到的用户信息返回,从而实现状态保持。
缺点:
一、服务器压力增大
一般session是存储在内存中,每个用户经过认证以后都会将数据保存在服务器内存中,而当用户量增大时,服务器压力增大。
二、csrf跨站点请求伪造
session是基于cookie进行用户识别的,cookie若是被截取,用户就会很容易受到跨站带你请求伪造的攻击
三、扩展性不强
若是未来搭建了多个服务器,虽然每一个服务器都执行的是一样的业务逻辑,可是session数据是保存在内存中的(不是共享的),用户第一次访问的是服务器1,当用户再次请求时可能访问的是另一台服务器2,服务器2获取不到session信息,就断定用户没有登录过。
token认证机制
token与session不一样主要在于认证成功以后,会对当前用户数据进行加密,生成一个加密字符串token返回给客户端,
浏览器会将接收到的token值存储在localstorage中,再次访问服务器的时候将加密后的token带上,服务器进行解密。解密以后对于用户数据查询,他不要服务器去保留用户的认证信息或者会话信息,这意味着token不须要考虑登陆那一台服务器。具备良好的扩展性。
HTTPS协议是由SSL+HTTP协议构建的可进行 加密传输、身份认证的网络协议,比http协议安全。
一个HTTPS请求实际上包含了两次HTTP传输,能够细分为8步。
1.客户端向服务器发起HTTPS请求,链接到服务器的443端口
2.服务器端有一个密钥对,即公钥和私钥,是用来进行非对称加密使用的,服务器端保存着私钥,不能将其泄露,公钥能够发送给任何人。
3.服务器将本身的公钥发送给客户端。
4.客户端收到服务器端的公钥以后,会对公钥进行检查,验证其合法性,若是发现发现公钥有问题,那么HTTPS传输就没法继续。严格的说,这里应该是验证服务器发送的数字证书的合法性,关于客户端如何验证数字证书的合法性,下文会进行说明。若是公钥合格,那么客户端会生成一个随机值,这个随机值就是用于进行对称加密的密钥,咱们将该密钥称之为client key,即客户端密钥,这样在概念上和服务器端的密钥容易进行区分。而后用服务器的公钥对客户端密钥进行非对称加密,这样客户端密钥就变成密文了,至此,HTTPS中的第一次HTTP请求结束。
5.客户端会发起HTTPS中的第二个HTTP请求,将加密以后的客户端密钥发送给服务器。
6.服务器接收到客户端发来的密文以后,会用本身的私钥对其进行非对称解密,解密以后的明文就是客户端密钥,而后用客户端密钥对数据进行对称加密,这样数据就变成了密文。
7.而后服务器将加密后的密文发送给客户端。
8.客户端收到服务器发送来的密文,用客户端密钥对其进行对称解密,获得服务器发送的数据。这样HTTPS中的第二个HTTP请求结束,整个HTTPS传输完成。
跨站脚本攻击分为三类
基于反射的xss
基于存储的xss
基于dom的xss
XSS就是经过在用户端注入恶意的可运行脚本,若服务端对用户的输入不进行处理,直接将用户的输入输出到浏览器,而后浏览器将会执行用户注入的脚本。 因此XSS攻击的核心就是浏览器渲染DOM的时候将文本信息解析成JS脚本从而引起JS脚本注入,那么XSS攻击的防护手段就是基于浏览器渲染这一步去作防护。只要咱们使用HTML编码将浏览器须要渲染的信息编码后,浏览器在渲染DOM元素的时候,会自动解码须要渲染的信息,将上述信息解析成字符串而不是JS脚本,这就是咱们防护XSS攻击的核心想法。
预防:
一、获取用户的输入,不用innerHtml,用innerText.
二、对用户的输入进行过滤,如对& < > " ' /等进行转义
一、+ 表示 前面的字符至少出现一次
二、* 表示 前面的字符能够不出现,也能够出现一次或者屡次
三、?表示前面的字符最多只能够出现一次
$ 匹配输入字符串的结尾位置
() 表示一个子表达式的开始和结束位置
一、TTP1.1默认使用长链接,可有效减小TCP的三次握手开销。
二、HTTP 1.1支持只发送header信息(不带任何body信息),若是服务器认为客户端有权限请求服务器,则返回100,不然返回401。客户端若是接受到100,才开始把请求body发送到服务器。这样当服务器返回401的时候,客户端就能够不用发送请求body了,节约了带宽。另外HTTP还支持传送内容的一部分。这样当客户端已经有一部分的资源后,只须要跟服务器请求另外的部分资源便可。这是支持文件断点续传的基础。
三、HTTP1.0是没有host域的,HTTP1.1才支持这个参数。
四、HTTP2.0使用多路复用技术(Multiplexing),多路复用容许同时经过单一的 HTTP/2 链接发起多重的请求-响应消息。
五、"HTTP1.1在同一时间对于同一个域名的请求数量有限制,超过限制就会阻塞请求"。多路复用底层采用"增长二进制分帧层"的方法,使得不改变原来的语义、首部字段的状况下提升传输性能,下降延迟。
二进制分帧将全部传输信息分割为更小的帧,用二进制进行编码,多个请求都在同一个TCP链接上完成,能够承载任意数量的双向数据流。HTTP/2更有效的使用TCP链接,获得性能上的提高。
前端为何要性能优化:这是由于咱们每一次向服务器发出请求的话,都会加大服务器的压力;
优化的方法:
(1)减小http请求{例如CSS sprite图片懒加载}
1、css sprite如何实现连接:其实就是把网页中一些背景图片整合到一张图片文件中,再利用 CSS 的"background-image","background-repeat","background-position" 的组合进行背景定位,background-position 能够用数字能精确的定位出背景图片的位置。这样能够减小不少图片请求的开销,由于请求耗时比较长;请求虽然能够并发,可是也有限制,通常浏览器都是6个
2、懒加载的实现
就是咱们把图片的地址放在,img自定义的属性中,当该图片出如今咱们视野中的时候,要把自定义属性的值传递给,src,就这样完成了懒加载
(2)使用CDN
若是应用程序web服务器离用户更近,那么一个HTTP请求的响应时间将缩短。另外一方面,若是组件web服务器离用户更近,则多个HTTP请求的响应时间将缩短。
CDN(内容发布网络)是一组分布在多个不一样地理位置的Web服务器,用于更加有效地向用户发布内容。在优化性能时,向特定用户发布内容的服务器的选择基于对网络慕课拥堵的测量。例如,CDN可能选择网络阶跃数最小的服务器,或者具备最短响应时间的服务器。
CDN还能够进行数据备份、扩展存储能力,进行缓存,同时有助于缓和Web流量峰值压力。
CDN的缺点:
一、响应时间可能会受到其余网站流量的影响。CDN服务提供商在其全部客户之间共享Web服务器组。
二、若是CDN服务质量降低了,那么你的工做质量也将降低
三、没法直接控制组件服务器
CDN的基本原理是普遍采用各类缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络中,在用户访问网站时,利用全局负载技术将用户的访问指向距离最近的工做正常的缓存服务器上,由缓存服务器直接响应用户请求。
(3)添加Expires头
页面的初次访问者会进行不少HTTP请求,可是经过使用一个长久的Expires头,能够使这些组件被缓存,下次访问的时候,就能够减小没必要要的HTPP请求,从而提升加载速度。
Web服务器经过Expires头告诉客户端能够使用一个组件的当前副本,直到指定的时间为止。例如:
Expires: Fri, 18 Mar 2016 07:41:53 GMT
Expires缺点: 它要求服务器和客户端时钟严格同步;过时日期须要常常检查
HTTP1.1中引入Cache-Control来克服Expires头的限制,使用max-age指定组件被缓存多久。
Cache-Control: max-age=12345600
若同时制定Cache-Control和Expires,则max-age将覆盖Expires头
(4)将样式表放在头部
首先说明一下,将样式表放在头部对于实际页面加载的时间并不能形成太大影响,可是这会减小页面首屏出现的时间,使页面内容逐步呈现,改善用户体验,防止“白屏”。
咱们老是但愿页面可以尽快显示内容,为用户提供可视化的回馈,这对网速慢的用户来讲是很重要的。
将样式表放在文档底部会阻止浏览器中的内容逐步出现。为了不当样式变化时重绘页面元素,浏览器会阻塞内容逐步呈现,形成“白屏”。这源自浏览器的行为:若是样式表仍在加载,构建呈现树就是一种浪费,由于全部样式表加载解析完毕以前务虚会之任何东西
(5)将脚本放在底部
更样式表相同,脚本放在底部对于实际页面加载的时间并不能形成太大影响,可是这会减小页面首屏出现的时间,使页面内容逐步呈现。
js的下载和执行会阻塞Dom树的构建(严谨地说是中断了Dom树的更新),因此script标签放在首屏范围内的HTML代码段里会截断首屏的内容。
下载脚本时并行下载是被禁用的——即便使用了不一样的主机名,也不会启用其余的下载。由于脚本可能修改页面内容,所以浏览器会等待;另外,也是为了保证脚本可以按照正确的顺序执行,由于后面的脚本可能与前面的脚本存在依赖关系,不按照顺序执行可能会产生错误。
(6)避免CSS表达式
(7)压缩css,js代码
把模块开发所建立的文件打包成一整份文件,以便浏览器环境中执行,
能够分析模块开发时所配置的文件依赖,使打包好的文件能够有序的执行
提供各类loader,能够处理各类非js类型的资源文件,一并构建打包。
在狗仔过程当中,能够经过插件处理一些额外的功能。
提供一个开发服务器,方便开发过程当中在服务器环境中预览页面,实现免刷新,热替换等功能
从启动构建到输出结果一系列过程:
(1)初始化参数:解析webpack配置参数,合并shell传入和webpack.config.js文件配置的参数,造成最后的配置结果。
(2)开始编译:上一步获得的参数初始化compiler对象,注册全部配置的插件,插件监听webpack构建生命周期的事件节点,作出相应的反应,执行对象的 run 方法开始执行编译。
(3)肯定入口:从配置的entry入口,开始解析文件构建AST语法树,找出依赖,递归下去。
(4)编译模块:递归中根据文件类型和loader配置,调用全部配置的loader对文件进行转换,再找出该模块依赖的模块,再递归本步骤直到全部入口依赖的文件都通过了本步骤的处理。
(5)完成模块编译并输出:递归完过后,获得每一个文件结果,包含每一个模块以及他们之间的依赖关系,根据entry配置生成代码块chunk。
(6)输出完成:输出全部的chunk到文件系统。
注意:在构建生命周期中有一系列插件在作合适的时机作合适事情,好比UglifyPlugin会在loader转换递归完对结果使用UglifyJs压缩覆盖以前的结果。
本质上, happypack 是用经过 js 的多进程来实现打包加速,须要注意的是,建立子进程和子进程和主进程之间通讯也是有开销的,当你的 loader 很慢的时候,能够加上 happypack,不然,可能会编译的更慢!
happypack 经过new HappyPack(),去实例化一个HappyPack对象,其实就是告诉Happypack核心调度器如何经过一系列loader去转换一类文件,而且能够指定如何为这类转换器做分配子进程。
核心调度器的逻辑代码在主进程里,也就是运行webpack的进程中,核心调度器会将一个个任务分配给当前空闲的子进程,子进程处理完后会将结果发送给核心调度器,它们之间的数据交换是经过进进程间的通信API实现的。
核心调度器收到来自子进程处理完毕的结果后,会通知webpack该文件已经处理完毕
此处必然会问:进程和线程的关系:进程是操做系统资源分配的基本单位;线程是操做系统执行和调度的基本单位
(1)每个进程都有独立代码和数据空间,程序切换开销比较大。(2)线程能够看做为轻量级的进程。同一类线程共享代码和数据空间,每个线程拥有独立的程序计数器和运行栈,切换开销较小。
(1)一个操做系统能够拥有多个进程 (2)一个进程能够拥有多个线程
(1)进程能够分配资源 (2)线程不分配资源,共享进程中的资源
、二者监听数据变化的实现原理不一样
vue 经过getter/setter以及一些数据劫持,可以精确制导数据变化
React默认经过比较的方式(diff)进行,若是不优化可能会致使大量没必要要的VDOM的从新渲染。Vue使用的是可变的数据,React强调的是数据的不能够变
二、数据流的不一样
React使用的单项数据流
Vue的双向数据绑定
三、组件通讯
vue中有三种通讯方式,父组件经过props传递给子组件,子组件经过$emit传递消息给父组件,跨组件通讯能够使用provide/inject来。
React也有三种通讯方式,父组件经过props传递消息给子组件,子组件经过父组件传递的函数进行通讯。context跨组件通讯
四、模板渲染方式不一样
React模板渲染更接近原生js的写法
Vue更加依赖于指令来实现的
五、渲染过程不一样
Vue能够更加快速计算虚拟DOM的擦会议,这是因为他在渲染的过程当中,会跟踪每个租金按的依赖关系,不须要从新渲染整个树
7.框架本质不一样
Vue本质是MVVM框架,由MVC发展而来;
React是前端组件化框架,由后端组件化发展而来
Redux使用的是不可变数据,而Vuex的数据是可变的,所以,Redux每次都是用新state替换旧state,而Vuex是直接修改。Redux在检测数据变化的时候,是经过diff的方式比较差别的,而Vuex其实和Vue的原理同样,是经过getter/setter来比较的,这两点的区别,也是由于React和Vue的设计理念不一样。React更偏向于构建稳定大型的应用,很是的科班化。相比之下,Vue更偏向于简单迅速的解决问题,更灵活,不那么严格遵循条条框框。所以也会给人一种大型项目用React,小型项目用Vue的感受。
mvvm:响应式,双向数据绑定,即MVVM。是指数据层-视图层-view 数据视图viewmodel的响应式框架,它包括
一、修改VIew层,Model对应数据变化
二、Model数据变化,不须要查找Dom,直接更新View
MVVM的实现方式
(1)发布者-订阅者 通常经过sub,puh的方式实现数据和视图的绑定监听,更新数据方法一般作法是vm.set('property',value)
(2)脏值检测 angular.js是经过脏值检测的方式比对数据是否有变动,来决定是否更新视图,在指定的事件触发时进入脏值检测。
(3)数据劫持:vue.js是采用数据劫持结合发布者-订阅者模式的方式,经过Object.defineProperty()来劫持各个属性。
咱们已经知道实现数据的双向绑定,首先要对数据进行劫持监听,因此咱们须要设置一个监听器Observer,用来监听全部属性。若是属性发上变化了,就须要告诉订阅者Watcher看是否须要更新。由于订阅者是有不少个,因此咱们须要有一个消息订阅器Dep来专门收集这些订阅者,而后在监听器Observer和订阅者Watcher之间进行统一管理的。接着,咱们还须要有一个指令解析器Compile,对每一个节点元素进行扫描和解析,将相关指令对应初始化成一个订阅者Watcher,并替换模板数据或者绑定相应的函数,此时当订阅者Watcher接收到相应属性的变化,就会执行对应的更新函数,从而更新视图。所以接下去咱们执行如下3个步骤,实现数据的双向绑定:
1.实现一个监听器Observer,用来劫持并监听全部属性,若是有变更的,就通知订阅者。
2.实现一个订阅者Watcher,能够收到属性的变化通知并执行相应的函数,从而更新视图。
3.实现一个解析器Compile,能够扫描和解析每一个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅器。
1、object.defineprotype没法检测到下标的变化,致使数组经过下标添加元素,没法及时响应
2、 Object.defineProperty只能劫持对象的属性,从而须要对每一个对象,每一个属性进行遍历,若是,属性值是对象,还须要深度遍历。Proxy能够劫持整个对象,并返回一个新的对象。
3、 Proxy不只能够代理对象,还能够代理数组。还能够代理动态增长的属性。
一、BeforeCreate 建立前 在数据观测和初始化事件尚未开始
二、created 建立后 完成数据监测,属性和方法,初始化事件,$el属性没有显示出来
三、boforeMount 载入前在挂在开始以前被调用,相关的render函数首次被调用。实例已经完成一下配置:编译模板,把data里面的数据和模板生成html。注意这时候尚未挂在到html中
四、Mounted 载入后 在el被建立的新的VM.$el5替换,而且挂在到实例以后调用。实例已经完成一下配置:用上面编译好的html去替换el属性所指的DOM对象,完成html模板渲染到页面上。此过程能够发生ajax。
五、beforeupdate 在数据更新以前调用,发生在虚拟DOM从新渲染和打补丁以前,可在该钩子函数中更新状态,不会触发附加的从新渲染的过程。
六、updated 更新后 因为数据更新致使虚拟DOM从新渲染和打补丁以后,。DOM组件已经更新完毕,因此能够执行依赖DOM的操做。而后大多数状况下应该避免在此期间更新状态,由于可能会致使更新无线循环。此阶段不能在服务器渲染调用
七、boforedestory 在实例销毁以前调用,实例仍然彻底可用
八、destoryed 在实例销毁以后调用后。全部时间的监听器会被一处,全部子实力也会被销毁。该钩子在服务端渲染期间不能够调用
他的生命周期中有多个钩子函数没让咱们在控制整个Vue的实例的过程时更容易造成好的逻辑。
Vue的实例从建立到销毁的过程。就是生命周期。从一开始的建立,数据初始化,模板编译、挂在DOM->渲染,更新数据->渲染,销毁等一系列等过程称为vue的生命周期
第一次加载页面会触发那些钩子函数
beforecreate, created,beforemount,mounted
Dom渲染在那个阶段
Dom渲染完成在mounted中已经完成
父子组件之间传递参数:
父组件传递给子组件:子组件经过props来接受数据
子组件传递给父组件: $emit传递参数
二、非父子组件之间传递参数,兄弟组件传值
eventBus,就是建立一个事件中心,至关于一个中转站,还能够使用发布与订阅来。
Vue的路由实现:hash模式和history模u式
hash模式:在浏览器中符号:"#",#以及#后面的字符称之为hash,用window.location.hash读取
特色:hash虽然在URL中,可是不被包括在Http请求中;u哦你过来指导浏览器动做,对于服务端安全无用,hash不会从新加载页面
hash模式下,仅hash符号以前的内容会被包含在请求中
history模式:history采用HTML5的新特性,且提供了两个新的方法;pushState(),replaceState()能够浏览器历史记录栈进行修改,以及popState事件监听到状态更新,
history模式下 前端URL必需要和后端发送请求的URL一致
做用:
vue内置组件,能在组件切换过程当中将状态保留在内存中,防止重复渲染DOM
keep-alive是用在一个直属子组件被开关的情形,同时只有一个子组件在渲染,如有v-for则不会工做
注:keep-alive是一个抽象组件,自身不会渲染一个DOM元素,也不会出如今父组件链中
第一点:使用typescript对架构进行了重写
第二点:重写了虚拟Dom,相似于react的Fiber
第三点:用Proxy代替了Object.defineProtype,
把树形结构按照层级分解,只比较同级元素。
给列表结构的每一个单元添加惟一的 key 属性,方便比较。
React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)
合并操做,调用 component 的 setState 方法的时候, React 将其标记为 dirty.到每个事件循环结束, React 检查全部标记 dirty 的 component 从新绘制.
选择性子树渲染。开发人员能够重写 shouldComponentUpdate 提升 diff 的性能。
在代码中调用 setState 函数以后,React 会将传入的参数对象与组件当前的状态合并,而后触发所谓的调和过程(Reconciliation)。通过调和过程,React 会以相对高效的方式根据新的状态构建 React 元素树而且着手从新渲染整个 UI 界面。在 React 获得元素树以后,React 会自动计算出新的树与老树的节点差别,而后根据差别对界面进行最小化重渲染。在差别计算算法中,React 可以相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是所有从新渲染。
setState 只在合成事件和钩子函数中是“异步”的,在原生事件和 setTimeout 中都是同步的。
合成事件:就是react 在组件中的onClick等都是属于它自定义的合成事件
原生事件:好比经过addeventListener添加的,dom中的原生事件
setState的“异步”并非说内部由异步代码实现,其实自己执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新以前,致使在合成事件和钩子函数中无法立马拿到更新后的值,形式了所谓的“异步”,固然能够经过第二个参数 setState(partialState, callback) 中的callback拿到更新后的结果。
setState 的批量更新优化也是创建在“异步”(合成事件、钩子函数)之上的,在原生事件和setTimeout 中不会批量更新,在“异步”中若是对同一个值进行屡次 setState , setState 的批量更新策略会对其进行覆盖,取最后一次的执行,若是是同时 setState 多个不一样的值,在更新时会对其进行合并批量更新。
efs用来获取dom,什么情境下使用refs在获取一张图片的宽高
ref是一个函数,这样容易提升性能ref={()=>{this.name=ref}}
高阶组件其实就是一个函数,输入的是一个组件,输出的也是一个组件,可是输入组件具备输入组件不具备的功能。高阶组件的意义在于重用代码
(1)重用代码。有时候不少React组件都须要公用一样一个逻辑,好比说React-Redux中容器组件的部分,没有必要让每一个组件都实现一遍shouldComponentUpdate这些生命周期函数,把这部分逻辑提取出来,利用高阶组件的方式应用出去,就能够减小不少组件的重复代码。
(2)修改现有React组件的行为。有些现成的React组件并非开发者本身开发的,来自于第三方,或者即使是咱们本身开发的,可是咱们不想去触碰这些组件的内部逻辑,这时候能够用高阶组件。经过一个独立于原有组件的函数,能够产生新的组件,对原有组件没有任何侵害。
根据返回的新组件和传入组件参数的关系,高阶组件的实现方式能够分为两大类:
受控组件:
在 HTML 中,相似 <input>, <textarea> 和 <select> 这样的表单元素会维护自身的状态,并基于用户的输入来更新。当用户提交表单时,前面提到的元素的值将随表单一块儿被发送。但在 React 中会有些不一样,包含表单元素的组件将会在 state 中追踪输入的值,而且每次调用回调函数时,如 onChange 会更新 state,从新渲染组件。一个输入表单元素,它的值经过 React 的这种方式来控制,这样的元素就被称为"受控元素"。
非受控组件由DOM自己处理,即不受setState控制,用ref获取该输入框的内容
reselect是至关于vue中computed,作了一个缓存提高代码性能
hashHistory不要后台配后,browserHistory须要和服务器的一些配置。
react中如何提升组件的性能,避免出现这样的状况:父组件更新的时候,子组件也跟着更新这样会的话,会极大的浪费性能。
我以为react性能优化有两方面:一是减小render的渲染次数,另外一方面是减小计算。对应的react提供两个API。purecompement和shuldcompementUpdate这两个方法。
经常使用use有useState(),useeffect(),useContext(),useRef,useReduce,useMeo,useCallback,自定以usehooks
useState 声明状态序列,采用结构赋值,能够得到数据,和修改数据的方法
useEffect生命周期,反作用,也就是主程序以外作的事情,代替了原生命周期中CompontDidmount,ComponentDidUpdate,自己是一个函数,内部存放一个函数,return 一个解绑函数
第二个参数能够监控哪些值的变化
useContext 能够实现跨组件通讯,须要和createContext组合在一块儿
useRef 能够获取dom元素还能够存储值
useReduce 也是一个函数,内部须要放置一个redux中reducer函数,第二个参数给state赋予初始值,在这里能够管理整个项目总体状态
useContext+useReduce 能够代替redux
useMemo和useCallback 用来提升性能,由于hooks中没有shouldComponentUpdate函数能够提升性能优化,避免没必要要渲染
useMemo存储的是变量,useCallback存储的是函数
自定义use组件须要以use开头。
、React 会在第一次渲染时将全部的hook 放入 Hooks 数组中。下次渲染时,一样的3个hooks以相同的顺序被调用,因此React能够查看它的数组,并发现已经在位置0有一个useState hook ,因此React不会建立一个新状态,而是返回现有状态。
初次渲染的时候,按照 useState,useEffect 的顺序
,把 state,deps 等按顺序塞到 memoizedState 数组
中。
更新的时候,按照顺序
,从 memoizedState 中把上次记录的值拿出来。
这是由于babel在转换jsx语法的时候,会调用createElement()这个方法,这个方法须要接收三个参数:type, config, children。第一个参数声明了这个元素的类型。
对比上面两张图,图一中,我在建立自定义组件时没有首字母大写。 而 babel 在转义时把它当成了一个字符串 传递进去了;图二中,我把首字母大写了,babel 在转义时传递了一个变量进去。
问题就在这里,若是传递的是一个字符串,那么在建立虚拟DOM对象时,React会认为这是一个简单的HTML标签,可是这显然不是一个简单的HTML标签,所以去建立一个不存在的标签确定是会报错的。
若是首字母大写,那么就会当成一个变量传递进去,这个时候React会知道这是一个自定义组件,所以他就不会报错了。
1.难以重用和共享组件中的与状态相关的逻辑
2. 逻辑复杂的组件难以开发与维护,当咱们的组件须要处理多个互不相关的 local state 时,每一个生命周期函数中可能会包含着各类互不相关的逻辑在里面。
3.类组件中的this增长学习成本,类组件在基于现有工具的优化上存在些许问题。
建立redux的Store对象,须要调用combineReducer和createStore函数,
combineReducer:将多个reducer函数看成参数传入,combineReducer函数运行,返回一个新的Combination函数。combination函数主要做用返回一个挂在所有state的对象。当combination函数被调用时,实际就是循环调用传入reducer函数,返回state对象。将combination函数做为参数传入到CreateStore函数中。
重点:
1.redux建立Store:经过combineReducers
函数合并reducer函数,返回一个新的函数combination
(这个函数负责循环遍历运行reducer函数,返回所有state)。将这个新函数做为参数传入createStore
函数,函数内部经过dispatch,初始化运行传入的combination
,state生成,返回store对象。
2.redux中间件:applyMiddleware函数中间件的主要目的就是修改dispatch函数,返回通过中间件处理的新的dispatch函数
3.redux使用:实际就是再次调用循环遍历调用reducer函数,更新state.
node的特色:单线程,非阻塞I/o,事件驱动。
分为核心模块和文件模块
1.2请介绍一下require的模块加载机制:在node中,路径分析,文件定位,编译执行。若是模块在缓存中,取出缓存(核心模块的缓存要先于文件缓存)
加载模块,输出模块的exports
1.3咱们知道exports.xxx=xxx和Module.export={}有什么区别吗
exports就是module.exports.若是要输出一个简直对象{},能够利用exports这个已经存在空对象{},并继续在上面若是要输出一个函数或者数组,必须直接对module.exports对象赋值。
2.1 Node事件循环的过程
在进程启动时,Node便会建立一个相似于while(true)的循环,每一次执行循环体的过程咱们都称之为Tick。每个Tick的过程就是检查是否有事件待处理,若是有就会取出事件以及相关的回调函数。而后执行下一个循环,若是没有事件处理,就会退出进程
2.2 在每个tick的过程当中,如何判断事件是否须要处理呢?
每个事件循环中有一个或者多个观察者,而判断是否有时间须要处理的过程就是向这些观察者询问是否要处理的事件。在Node中,事件主要来源于网路请求、文件的I/O等,这些对应的事件就有对应的观察者,网络观察者,网络I/O的观察者。事件循环就一个典型的生产者/消费者模型。异步I/O,网络等则是事件生产者,源源不断为Node提供不一样类型的事件,这些事件被传递到对应的观察者那里,事件循环则从观察者那里取出事件并处理。在windows下,这个循环基于IOCP建立,在*nix下则基于多线程建立
在Node.js中,中间件主要是指封装了全部http请求细节处理的方法。Http请求一般包括不少工做,如记录日志、ip过滤、查询字符串、请求体解析、cookie处理、权限验证、参数验证,异常处理等,服务于主要业务逻辑。
3.1 如何查看V8的内存使用状况
使用process.memoryUsage(),返回以下
1
2
3
4
5
6
{
rss:
`4935680`,
heapTotal:
`1826816`,
heapUsed:
`650472`,
external:
`49879`
}
heapTotal和heapUsed表明V8的内存使用状况。external表明V8管理的,绑定到Javascript的C++对象的内存使用状况。rss, 驻留集大小, 是给这个进程分配了多少物理内存(占总分配内存的一部分) 这些物理内存中包含堆,栈,和代码段。
3.2 V8的内存限制是多少,为何V8这样设计
64位系统下是1.4GB, 32位系统下是0.7GB。由于1.5GB的垃圾回收堆内存,V8须要花费50毫秒以上,作一次非增量式的垃圾回收甚至要1秒以上。这是垃圾回收中引发Javascript线程暂停执行的事件,在这样的花销下,应用的性能和影响力都会直线降低。
3.3 V8的内存分代和回收算法请简单讲一讲
在V8中,主要将内存分为新生代和老生代两代。新生代中的对象存活时间较短的对象,老生代中的对象存活时间较长,或常驻内存的对象。
3.3.1 新生代
新生代中的对象主要经过Scavenge算法进行垃圾回收。这是一种采用复制的方式实现的垃圾回收算法。它将堆内存一份为二,每一部分空间成为semispace。在这两个semispace空间中,只有一个处于使用中,另外一个处于闲置状态。处于使用状态的semispace空间称为From空间,处于闲置状态的空间称为To空间。
3.3.2 老生代
老生代主要采起的是标记清除的垃圾回收算法。与Scavenge复制活着的对象不一样,标记清除算法在标记阶段遍历堆中的全部对象,并标记活着的对象,只清理死亡对象。活对象在新生代中只占叫小部分,死对象在老生代中只占较小部分,这是为何采用标记清除算法的缘由。
3.3.3 标记清楚算法的问题
主要问题是每一次进行标记清除回收后,内存空间会出现不连续的状态
3.3.4 哪些状况会形成V8没法当即回收内存
闭包和全局变量
3.3.5 请谈一下内存泄漏是什么,以及常见内存泄漏的缘由,和排查的方法
什么是内存泄漏
一、进程是操做系统资源分配的基本单位 二、线程是任务调度和执行的基本单位
区别:
(1)每个进程都有独立代码和数据空间,程序切换开销比较大。(2)线程能够看做为轻量级的进程。同一类线程共享代码和数据空间,每个线程拥有独立的程序计数器和运行栈,切换开销较小。
(1)一个操做系统能够拥有多个进程 (2)一个进程能够拥有多个线程
(1)进程能够分配资源 (2)线程不分配资源,共享进程中的资源
1、管道:速度慢,容量有限,只能父子通讯
2、FIFO:任何进程均可以通讯,可是速度慢
3、消息队列:容量受系统限制,且须要考虑上次未读完内容
4、信号量:不能传递复杂消息,只能用于同步
5、共享内存:容易控制容量,速度快,可是要保持同步
1、同步 多线程经过synchronized通信
2、While轮询 线程 A不断改变条件,线程B不断查看条件是否知足需求,从而实现通信
3、管道通讯,将一个线程消息发个另外一个线程