日常学习知识点总结(JS篇)
1、闭包:
闭包就是函数中的函数,里面的函数可以访问外面函数的变量,外面的变量是内部函数的一部分。
闭包的作用:使用闭包可以访问函数中的变量。
可以使变量长期保存在内存中,生命周期比较长。
缺点:闭包不能滥用,否则会导致内存泄漏,影响网页的性能。闭包使用完了,要立即释放资源,将引用变量指向null.
应用场景:函数作为参数传递
函数作为返回值
为什么使用闭包 : 全局变量和局部变量都具有不可兼得的优缺点。
全局变量: 优: 可重用。 缺: 易被污染。
局部变量: 优: 仅函数内可用,不会被污染。 缺: 不可重用!
何时使用: 即要重用一个变量,又保护变量不被污染时。
示例: 1)var name = "The window";
var object = {
name: "my object",
getNameFunc: function(){
var self = this;
return function (){
return self.name;
}
}
}
console.log(object.getNameFunc()()); //my object
2)var name = "The window";
var object = {
name: "my object",
getNameFunc: function(){
return function (){
return this.name;
}
}
}
console.log(object.getNameFunc()()); //The window
2、localStorage 、sessionStorage 和 cookie 之间的区别:
共同点:都是保存在浏览器端,且都遵循同源策略(相同的协议、相同的主机名、相同的端口)。
不同点:
localStorage的声明周期是永久的,关闭页面或浏览器之后local Storage中的数据也不会消失。localStorage除非主动删除数据,否则数据永远不会消失。
sessionStorage的生命周期是仅在当前会话下有效。sessionStorage引入了一个“浏览器窗口”的概念,sessionStorage是在同源的窗口中始终存在的数据。只要这个浏览器窗口没有关闭,即使刷新页面或者进入同源另一个页面,数据依然存在。但是sessionStorage在关闭了浏览器窗口后就会被销毁。同时独立的打开同一个窗口同一个页面,sessionStorage也是不一样的。
cookie生命期为只在设置的cookie过期时间之前一直有效,即便窗口或浏览器关闭。存放数据大小为4K左右,有个数限制(各浏览器不同),一般不能超过20个。缺点是不能存储大数据且不易读取。
用法:
1)判断浏览器是否支持localStorage/sessionStorage----if (window.localStorage) { }
2)localStorage/sessionStorage都具有相同的操作方法
存储数据:setItem(key, value)---将value存储到key字段
取出数据:getItem(key)----获取指定key本地存储的值
修改数据:setItem(key,newVal)----修改指定key本地存储的值
删除数据:removeItem(key)----删除指定key本地存储的值
清除数据:clear()----清楚所有本地存储的数据
3)cookie
存储数据:window.document.cookie = 'XXXX';
取出数据:document.cookie;
cookie的作用:
解决了认证(登录)后,下次访问还需要认证(登录)的重复认证问题。
可以记住用户名和密码,增强用户体验。
cookie的缺点:
安全性问题,cookie数据保存在客户端,有可能被篡改或盗取
Web Storage包含如下两种机制:
sessionStorage为每一个给定的源(given origin)维持一个独立的存储区域,该存储区域在页面会话期间可用(即只要浏览器处于打开状态,包括页面重新加载和回复)。
localStorage同样的功能,但在浏览器关闭,然后重新打开后数据仍然存在。
3、原型与原型链:
1)原型:在JS中原型是一个prototype对象,用于表示类型之间的关系
原型链:是针对构造函数的。指对象之间的继承关系,在JavaScript中是通过prototype对象指向父类对象,直到指向Object对象为止,这样就形成了一个原型指向的链条,专业术语称之为原型链。
当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的_proto_(即构造函数prototype)中寻找。如果一直找到最上层都没找到,就返回undefined。最上层是指------ object.prototype.__proto__===null.
2)构造函数/原型对象/实例对象三者之间的关系以及原型链的访问原理:
构造函数:是一种特殊的方法,它不同于普通的函数,普通的函数通过‘函数名()’即可进行调用,而构造函数需要使用‘new 函数名()’进行调用。主要用来创建对象时初始化对象。
原型对象:是构造函数所拥有的,在JavaScript规定,每一个构造函数都有一个prototype(原型)属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数所拥有。
实例对象:则是通过调用构造函数而产生。(例如:var er = new Person( ) )
总结: 1)任何函数都具有一个prototype属性,该属性是一个对象。
2)构造函数的prototype对象默认都有一个constructor属性,指向prototype对象所在的函数。
3)通过构造函数得到的实例对象内部会包含一个指向构造函数的prototype对象的指针__proto__。
4)所有的实例都直接或间接继承了原型对象的成员。
4、JS事件流
1)事件流:分为捕获阶段,处于目标阶段,冒泡阶段三个阶段
事件冒泡,从触发的对象开始,事件不断往上传递
事件捕获,从dom树一直向下传递事件直到捕获为止
2)事件绑定类型
dom0:通过element对象调用对应的事件属于绑定特定的事件,事件会在事件冒泡阶段被捕获。
let btn = document.getElementById("myBtn");
btn.onclick = function(){// 由于onclick是attr,所以可以通过.来获取
console.log(this.id); //"myBtn"
};
dom2:通过addEventListener来绑定事件,removeEventListener来移除事件。element.addEventListener(event,function,useCapture)中的第三个参数可以控制指定事件是否在捕获或冒泡阶段执行。true---事件句柄在捕获阶段执行。false(默认)---事件句柄在冒泡阶段执行。IE9、Firefox、Safari、Chrome 和 Opera 支持 DOM2 级事件处理程序。
let btn = document.getElementById("myBtn");
btn.addEventListener('click', function(event){
console.log(this.id); //"myBtn"
},false);
btn.addEventListener("click", function(){// 添加多个回调,触发的时候依次调用
alert("Hello world!");
}, false);
对于ie8之前的可以使用attachEvent添加事件,detachEvent解除事件
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){// 事件类型必须是onclick,跟dom2不一样
alert("Clicked");
});
三者的区别:
1)dom2,attachEvent可以为一个事件添加多个相应函数,彼此之间不会覆盖。dom0则不可以。
2)dom0的兼容性好,支持所有的浏览器。dom2不支持ie浏览器,所以对于ie浏览器事件处理使用attachEvent。由于IE只支持冒泡事件,所以attachEvent,没有第三个参数。
3)dom0在注销事件的时候,只要将对应的事件属性置为null即可。dom2调用removeEventListener函数的时候,参数要与addEventListener一样,也就是说,在addEventListener指定的函数的回调不能是一个匿名函数,不然在注销不到。因为两个函数对象是不一样的,虽然内容一样。
3)事件对象:
如果将回调函数直接绑定到目标对象上,那么this,target,currentTarget都是一样的,都是目标对象。
如果是绑定到父级元素上,那么this和currentTarget都等于父级元素,也即是回调函数被绑定的对象,target才是真正触发的对象。
4)document 加载事件回调
DOMContentLoading:在dom树加载完成之后被触发,不等待css,js,img等下载
onload:等待页面的内容都加载完毕之后被触发
5)事件集合:
鼠标事件:click(单机)、dbclick(双击)、mousedown(鼠标按下)、mouseout(鼠标移走)、mouseover(鼠标弹起)、mouseup(鼠标移动)、mousemover(鼠标移动)
键盘事件:keydown(键按下)、keydown(按键)、keyup(键起来)
HTML事件:load(加载页面)、unload(卸载离开页面)、change(改变内容)、scroll(滚动)、focus(获得焦点)、blur(失去焦点)
阻止事件冒泡的方法:
1)event.stopPropagation( ); 2)return false; 3)event.preventDefault( )
5、继承:
方法1:原型链+借用构造函数组合
// 父类
function Person(){
this.name = name;
this.sum = function (){
console.log(this.name);
}
}
Person.prototype.age = 10;
function SubType(name){
Person.call(this,name); // 借用构造函数模式
}
SubType.prototype = new Person(); // 原型链继承
var sub = new SubType("gar");
console.log(sub.name); // gar,继承了构造函数属性
console.log(sub.age); // 10,继承了父类原型的属性
优点:构造函数可以传参,不会与父类引用属性共享,可以复用父类的函数
缺点:继承了父类函数时,调用了父类构造函数,导致子类的原型上多了不需要的父类属性,存在内存上的浪费。
方法2:ES6中class的继承,class实现继承的核心在于使用extends表明继承自哪个父类,并且在子类构造函数中必须调用super。此段代码可以看成Parent.call(this,value);
6、http协议:
HTTP,即超文本传输协议,这个协议规定了浏览器和万维网服务器之间互相通信的规则。客户端发送给服务器的格式叫“请求协议”;服务器发送给客户端的格式叫“响应协议”。
特点:http叫超文本传输协议,基于请求/响应模式的;http是无状态协议(服务器不需要知道客户端是谁,只认请求,一次请求request,一次响应response),ftp(端口号为21)是有状态。
URL:统一资源定位符,就是一个网址:协议名://域名:端口/路径。
http默认的请求方法是GET:
没有请求体,数据必须在1K之内,GET请求的数据会暴露在浏览器的地址栏中
get和post的区别:
主要有以下几个方面:
1)url可见性:get,参数url可见;post,url参数不可见
2)数据传输上:get,通过拼接url进行传递参数;post,通过body体传输参数
3)缓存性:get请求是可以缓存的;post请求不可以缓存
4)后退页面的反应:get请求页面后退时,不产生影响;post请求页面后退时,会重新提交请求
5)传输数据的大小:get一般传输数据大小不超过2k-4k(根据浏览器不同,限制不一样,但相差不大);post请求传输数据的大小根据php.init配置文件设定,也可以无限大。
6)安全性:post肯定要比get安全,毕竟传输参数时url不可见,但也挡不住部分人闲的没事在那抓包玩。对传递的参数进行加密,其实都一样。
状态码:200:请求成功,浏览器会把响应体内容(通常时html)显示在浏览器中
404:请求的资源没有找到,说明客户端错误的请求了不存在的资源
500:请求的资源找到了,但服务器内部出现了错误
302:重定向,当响应码为302时,表示服务器要求浏览器重新再发一个请求,服务器会发送一个响应头Location,它指定了新请求的URL地址。
304:服务端内容未改变,将使用缓存在浏览器端的数据。
http请求报文:一个http请求报文由请求行(request line)/请求头部(header)/空行/请求数据四部分组成。
1)请求行,由请求方法字段/URL字段/http协议版本字段3部分组成,它们用空格分隔。
2)请求头,由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分割。请求头部通知服务器有关客户端请求的信息,典型的请求头有:User-Agent,产生请求的浏览器类型;Accept,客户端可识别的内容类型列表;Host,请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
3)空行,最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。
4)请求数据,请求数据不在GET方法中使用,而是在POST方法中使用。与请求数据相关的最常使用的请求头是Content-Type和Content-Length。
http报文:
http响应也由三部分组成,分别是:状态行/消息报头/响应正文
http协议1.0/1.1/2.0的区别:
1)http1.0,短链接,每一个请求建立一个TCP连接,请求完成后立马断开连接。导致连接无法复用,带宽无法被充分利用,以及后续健康请求被阻塞。
2)http1.1,长连接,多个http请求可以复用一个TCP连接,服务器按照队列的先进先出(FIFO)原则来处理不同的Request;增加connection header,该header用来说明客户端与服务器端TCP的连接方式,若connection为close则使用短链接,若connection为keep-alive则使用长连接。
3)http2.0,多路复用,允许同时通过单一的HTTP/2连接发起多重的请求-响应消息,可以很容易的去实现多流并行而不用依赖建立多个TCP连接,把http协议通信的基本单位缩小为一个一个帧,这些帧对应着逻辑流中的消息,并行的在同一个TCP连接上双向交换消息。二进制分帧,http2在应用层(http/2)和传输层(TCP/UDP)之间增加一个二进制分帧层,在不改动http1.X的情况下,解决了http1.1的性能限制,改进传输性能,实现低延迟和高吞吐量。http/2通信都在一个连接上完成,这个连接可以承载任意数量的双向数据流。
7、http与https的区别:
http,超文本传输协议;
https,超文本传输安全协议。
https经由http进行通信,但利用SSL/TLS来加密数据包。https开发的主要目的,是提供对网站服务器的身份认证,保证交换数据的隐私与完整性。
主要区别:1)传输信息安全性不同:http明文传输,数据都是未加密的,安全性较差;https数据传输过程时加密的,安全性较好
2)申请方式:http协议免费申请,https协议需要到CA(数字证书认证机构)申请证书,需要缴费
3)响应速度:http页面响应速度比https快,主要是因为http使用TCP三次握手建立连接,客户端和服务器需要交换3个包,而https除了TCP的3个包,还要加上SSL握手的9个包,一共12个包
4)端口不同:http和https使用的完全不同的连接方式,用的端口也不一样,http是80端口,https是443端口
5)耗费资源:https其实就是建构在SSL/TLS之上的http协议,所以https比http要更耗费服务器资源。
8、数组常用方法:
改变原数组的方法:
1)push( )把里面的内容添加到数组末尾,并返回修改后的长度
pop( )移除数组最后一项,返回移除的那个值,减少数组的length
2)shift( )删除原数组第一项,并返回删除元素的值;如果数组为空则返回undefined
unshift( )将参数添加到原数组开头,并返回数组的长度
3)sort( )将数组里的项从小到大排序
4)reverse( )反转数组项的顺序
5)splice( )删除、插入和替换。
6)slice( )返回从原数组中指定开始下标到结束下标之间的项组成的新数组。
7)reduce( )对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。reducer函数接收4个参数:Accumulator(acc)累计器,Current Value(cur)当前值,Current Index(idx)当前索引,Source Array(src)源数组
没有改变原数组的方法:
8)join,就是把数组转换成字符串,然后给规定个连接字符,默认是逗号(,)
9)concat( )将参数添加到原数组中
10)indexOf( )要查找的项位置的索引。 从数组的开头(位置 0)开始向后查找。
lastIndexOf( )要查找的项位置的索引。从数组的末尾开始向前查找。
11)forEach( )对数组进行遍历循环,对数组中的每一项运行给定函数。这个方法没有返回值。
12)map( )指“映射”,对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
13)filter( )“过滤”功能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组。
14)every( )判断数组中每一项都是否满足条件,只有所有项都满足条件,才会返回true。
14)some( )判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回true。
map和forEach相同点:
1)都是循环遍历数组中的每一项
2)forEach和map方法里每次执行匿名函数都支持3个参数,参数分别是item(当前每一项),index(索引值),arr(原数组)
3)匿名函数中的this都是指向window
4)只能遍历数组
5)都不会改变原数组
map和forEach区别:
map方法返回一个新的数组,数组中的元素为原始数组调用函数处理后的值。若arr为空数组,则map方法返回的也是一个空数组,forEach对于空数组是不会调用回调函数的
无论arr是不是空数组,forEach返回的都是undefined。这个方法只是将数组中的每一项作为callback的参数执行一次。
9、字符串常用方法:
1)charAt():返回在指定位置的字符
2)charCodeAt():返回咋指定位置的字符的Unicode编码
3)concat():连接字符串
4)indexOf(): 检索字符串,返回的是字符在字符串的下标
5)match():在字符串内检索指定的值或找到一个或多个正则表达式的匹配,返回的是值而不是值的位置。
6)replace():替换匹配的字符串
7)search():检索与字符串匹配的子串,返回的是地址
8)slice():提取字符串片段,并在新的字符串中返回被提取的部分
9)split():把字符分割成数组
10)toLocaleLowerCase():把字符串转换成小写
toLocaleUpperCase():把字符串准换成大写
11)ubstr():从起始索引号提取字符串中指定书目的字符,空格不占位
12)subString():提取字符串中两个指定索引号之间的字符,空格占位
10、对象常用方法:
1)创建:
Object.create():参数是一个对象,并且该对象作为新创建对象的原型。
2)属性赋值:
obj.name='lalala';当对象存在但是属性不存在的时候,给对象添加一个属性。
3)删除属性:
delete obj['name']; 在删除数组中元素的时候,删除了属性,但数组中的站位还在,长度不变。
4)检测属性
in:检测对象的自有属性和继承属性中是否有该属性。有则返回true, 否则返回false。
hasOwnProperty():测试当前属性是不是对象的自有属性。
5)枚举属性
for/in 其可以遍历对象中的所有的可枚举属性,包括当前对象的自有属性和继承属性。
Object.keys() 遍历对象的自有属性,返回的是一个数组,其中存在的是对象中的可枚举属性名称组成。
Object.getOwnPropertyNames() 其返回的是数组,但是是所有的自有属性名称的数组。
Object.entries() 返回一个包含[key, value]给定对象自己的可枚举字符串属性的所有对的数组。
6)Object.assign(target, ...resouce); 将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。target: 目标对象 resouce: 源对象
11、网页从输入网址到渲染完成经历了哪些过程?
大致分如下步骤:a).输入网址
b).发送到DNS(域名解析)服务器,并获取域名对应的web服务器对应的IP地址;
c).与web服务器建立TCP连接;
d).浏览器向web服务器发送http请求
e).web服务器响应请求,并返回指定的url的数据(或错误信息,或重定向的新的url地址)
f).浏览器下载web服务器返回的数据及解析html源文件
g).生成DOM树,解析CSS,JS,浏览器渲染
HTML parser--->DOM Tree(标记化算法,进行元素状态的标记;dom树构建)
CSS parser--->Style Tree(解析css代码,生成样式树)
attachment--->Render Tree (结合dom树与style树,生成渲染树)
layout:布局
GPU painting:像素绘制页面
12、常见的几种跨域解决方案:
1)JSONP:动态创建一个script标签。利用script标签的src属性不受同源策略限制。因为所有的src属性和href属性都不受同源策略限制。可以请求第三方服务器数据内容。
原理:首先在客户端注册一个callback,然后把callback的名字传给服务器。此时,服务器先生成json数据,然后以JavaScript语法的方式,生成function,function名字就是传递上来带参数jsonp。最后将json数据直接以入参的方式,放置function中,这样就生成js语法的文档,返回给客户端。客户端浏览器,解析script变迁,并执行返回JavaScript文档,此时数据作为参数,传入了客户端预先定义好的callback函数里。简单的说,就是利用script标签没有跨域限制的“漏洞”来达到与第三方通讯的目的。
步骤:
a. 去创建一个script标签
b. script的src属性设置接口地址
c. 接口参数,必须要带一个自定义函数名,要不然后台无法返回数据
d. 通过定义函数名去接收后台返回数据
//去创建一个script标签
var script = document.createElement('script');
//script的src属性接口地址,并带一个callback回调函数名称
script.src = 'http://127.0.0.1:8888/index.php?callback=jsonpCallback';
//插入到页面
document.head.appendChild(script);
//通过定义函数名去接收后台返回数据
function jsonpCallback(data){
//注意,jsonp返回的数据是json对象可以直接使用
//ajax 取得数据是json字符串需要转换成json对象才可以使用
}
总结一下,json是一种数据格式,jsonp是一种数据调用的方式,带callback的json就是jsonp.
2)基于iframe的跨域解决方案
window.name
document.domin
location.hash
post.message
3)CORS:跨域资源共享。
服务器设置Access-Control-Allow-OriginHTTP响应头之后,浏览器将会允许跨域请求。浏览器需要支持HTML5,可以支持POST,PUT等方法兼容ie9以上。
需要后台设置:Access-Control-Allow-Origin: * //允许所有域名访问
Access-Control-Allow-Origin: http://a.com //只允许所有域名访问
4)设置document.domain
相同主域名不同子域名下的页面,可以设置document.domain让它们同域。
同域document提供的是页面间的互操作,需要载入iframe页面。
// URL http://a.com/foo
var ifr = document.createElement('iframe');
ifr.src = 'http://b.a.com/bar';
ifr.onload = function(){
var ifrdoc = ifr.contentDocument || ifr.contentWindow.document;
ifrdoc.getElementsById("foo").innerHTML);
};
ifr.style.display = 'none';
document.body.appendChild(ifr);
5)用Apache做转发(逆向代理),让跨域变成同域
13、目前主流浏览器的内核分别是:
IE----Trident
Chrome---Blink
Firefox----Gecko
Safari----webkit
Mozilla-----Servo, 在 Firefox Quantum (火狐“量子”版本) 浏览器的57版本上使用了Servo CSS Style引擎
14、JS/jQuery/Vue分别是怎样获取标签的
javaScript:document.getElementById(“div”);//获取id
document.getElementsByClassName(“div”);//获取class类名
document.getElementsByTagName(“p”);//获取标签
document.getElementsByName(“box”);//获取input里name值
jQuery:$('#id');//获取id
$('.class');//获取class类名
$('input');//获取标签
Vue: 使用ref,给相应的元素加ref="name",然后再this.$refs.name获取到该元素
注意:在获取相应元素之前,必须在mount钩子进行挂在,否则获取到的值为空。
15、JS的数据类型分类:
基本数据类型:Undefined,Null,Boolean,String,Number,Symbol
引用数据类型:对象,数组,函数
栈,存储基本类型值和指定代码得环境
堆,存储引用类型值得空间
objA instanceof objB:objA的原型链上是否能找到objB的原型
instanceof 和 typeof区别:
typeof返回该参数数据类型,返回值为字符串
instanceof判断参数是否存在继承关系,返回值为布尔值
判断数据类型:
1)typeof---返回对应的数据类型,区分基本数据类型,如果是引用类型(如果是对象和数组),那么返回的都是Object,无法区分。
2)instanceof---只适用于对象类型,判断一个对象是否属于某个构造函数的实例。不适用于简单类型的数据类型,返回boolean值
语法:变量名 instanceof 数据类型 || 实例对象名 instanceof 构造函数
3)constructor---默认指向prototype属性所在的构造函数,用来判断数据类型(包括数组、日期、对象),返回boolean值
语法:变量名.constructor === 数据类型
4)jQuery.type( )---判断数据类型(包括日期、正则、undefined、null等)。其判断的结果显示都是小写的字符串形式
语法:jQuery.type(变量名)
5)Object.prototype.toString---toString是Object原型上的一个方法,该方法默认返回的是toString运行时this指向的对象类型,返回的格式为[object,xxx],xxx是具体的数据类型。注,所有对象的原型链最终都指向了Object。
16、作用域与作用域链
ES6 之前 JavaScript 没有块级作用域,只有全局作用域和函数作用域
作用域:就是一个独立的地盘,让变量不会外泄、暴露出去。作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。
作用域链:是针对变量的,先在自己的变量范围中查找,如果没有找到,就向父级作用域寻找,如果父级也没有,就再一层一层向上寻找,直到找到全局作用域还是没找到,就宣布放弃。这种一层一层的关系,就是作用域链 。
17、作用域与执行上下文:
JavaScript 属于解释型语言,JavaScript 的执行分为:解释和执行两个阶段,这两个阶段所做的事并不一样:
解释阶段:
词法分析
语法分析
作用域规则确定
执行阶段:
创建执行上下文
执行函数代码
垃圾回收
JavaScript 解释阶段便会确定作用域规则,因此作用域在函数定义时就已经确定了,而不是在函数调用时确定,但是执行上下文是函数执行之前创建的。执行上下文最明显的就是 this 的指向是执行时确定的。而作用域访问的变量是编写代码的结构确定的。
作用域和执行上下文之间最大的区别是:
执行上下文在运行时确定,随时可能改变;作用域在定义时就确定,并且不会改变。
18、Js宏观任务与微观任务:
宏观任务:宿主(浏览器/node)发起的任务为宏观任务,如:整体代码script/ setTimeout/ setInterval/
微观任务:JavaScript引擎发起的任务为微观任务,如:promise/ process.nextTick
执行顺序:同步>异步;微任务>宏任务
19、前端缓存:
1)Http缓存:
http缓存可以根据是否需要重新向服务器发起请求来分类,分为强制缓存和协商缓存。
强制缓存,主要是通过http请求头中的Cache-Control和Expire两个字段控制。Expire是HTTP1.0标准下的字段。一般,我们会设置Cache-Control的值为“public,max-age=XXX”,表示在XXX秒内再次访问该资源,均使用本地的缓存,不再向服务器发起请求。
如果缓存期过了,就使用协商缓存解决问题。协商缓存需要请求,如果缓存有效会返回304。
协商缓存需要客户端和服务端共同实现,和强缓存一样,也有两种实现方式:
Last-Modified 和 If-Modified-Since,Last-Modified表示本地文件最后修改日期,If-Modified-Since会将Last-Modified的值发送给服务器,询问服务器在该日期后资源是否由更新,有更新的话就会将新的资源发送回来。 但是如果在本地打开缓存文件,就会造成Last-Modified被修改,所以在HTTP/1.1出现了ETag。
ETag和If-None-Match,ETag类似于文件指纹,If-None-Match会将当前ETag 发送给服务器,询问该资源ETag是否变动,有变动的话就将新的资源发送回来。并且ETag优先级比Last-Modified高。
一个较为合理的缓存方案:HTML:使用协商缓存;CSS & JS & 图片:使用强缓存,文件命名带上hash值。
2)浏览器缓存
Cookie主要用于用户信息的存储,Cookie的内容可以自动在请求的时候被传递给服务器。
LocalStorage的数据将一直保存在浏览器内,直到用户清除浏览器缓存数据为止。
SessionStorage的其他属性同LocalStorage,只不过它的生命周期同标签页的生命周期,当标签页被关闭时,SessionStorage也会被清楚。
WebSql和IndexDB主要用在前端有大容量存储需求的页面上,例如,在线编辑浏览器或者网页邮箱。
往返缓存,又称为BFCache,是浏览器在前进后退按钮上为了提升历史页面的渲染速度的一种策略。该策略具体表现为,当用户前往新页面时,将当前页面的浏览器DOM状态保存到BFCache中;当用户点击后退按钮的时候,将页面直接从BFCache中加载,节省了网络请求的时间。
20、浅拷贝与深拷贝:
浅拷贝:以赋值的形式拷贝引用对象,仍指向同一个地址,修改时原对象也受到影响(寻址操作,例如:访问数据类型为数组)
浅拷贝的实现方式:
Object.assign():只复制源对象中可枚举的属性和对象自身的属性
Array.prototype.concat()
Array.prototype.slice()
深拷贝:完全拷贝一个新对象,修改时原对象不再受到任何影响(寻值操作,例如:访问数据类型为字符串)
深拷贝的实现方式:
jquery 提供一个$.extend可以用来做深拷贝
JSON.parse(JSON.stringify())
手写递归方法,递归实现深拷贝的原理:要拷贝一个数据,我们肯定要去遍历它的属性,如果这个对象的属性仍是对象,继续使用这个方法,如此往复。
21、new关键字的理解:
在JavaScript中,new关键字用来创建一个类(模拟类)的实例对象。实例化对象之后,也就继承了类的属性和方法。
使用new关键字后,意味做了几件事情:
1)创建一个新的空对象{ }
2)设置这个对象原型指向构造函数,即obj._proto_ = Person.prototype
3)执行构造函数,当this关键字被提及的时候,使用新创建的对象的属性
4)返回新创建的对象(如果构造函数有自己return时,则返回该值)
22、this的全面解析
this的值是在执行的时候才能确认,定义的时候不能确认!-----因为this是执行上下文环境的一部分,而执行上下文需要在代码执行之前确定,而不是定义的时候。
主要几种情况:
1)普通函数:this 指向调用其所在函数的对象,谁调的函数指向谁
2)构造函数:this指向被创建的新对象--实例对象
3)DOM事件:this指向触发事件的dom元素
4)call, apply和bind:this是第一个参数
xx.call(this, arg1, arg2)
xx.apply(this, [arg1,arg2])
xx.bind(this)(arg1)
5)setTimeout 和 setInterval:this指向全局
6)箭头函数this指向:箭头函数定义的位置,就是this的指向,一般情况会是window
23、JS的设计模型:
1)单例模式
定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。实现的方法为先判断实例存在与否,如果存在则直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。
使用场景,一个单一对象。比如:弹窗,无论点击多少次,弹窗只应该被创建一次。
2)策略模式
定义:定义一系列的算法,把他们一个个封装起来,并且使它们可以相互替换。
目的:将算法的使用算法的实现分离开来。
一个基于策略模式的程序至少由两部分组成。第一部分是一组策略类(可变),策略类封装了具体的算法,并负责具体的计算过程。第二个部分是环境类Context(不变),Context接收客户的请求,随后将请求委托给某一个策略类。要做到这一点,说明Context中要维持对某个策略对象的引用。
3)代理模式
定义:为一个对象提供一个代用品或占位符,以便控制对它的访问。
常用的虚拟代理形式:某一个花销很大的操作,可以通过虚拟代理的方式延迟到这种需要它的时候才去创建(例,使用虚拟代理实现图片懒加载)
图片懒加载的方式:先通过一张loading图占位,然后通过异步的方式加载图片,等图片加载好了再把完成的图片加载到img标签里面。
使用代理模式实现图片懒加载的优点还有符合单一职责原则。减少一个类或方法的粒度和耦合度。
4)中介者模式
定义:通过一个中介者对象,其他所有的相关对象都通过该中介者对象来通信,而不是相互引用,当其中的一个对象发生改变时,只需要通知中介者对象即可。通过中介者模式可以解除对象与对象之间的紧耦合关系。
适用场景:例如,购物车需求,存在商品选择表单,颜色选择表单,购买数量表单等等,都会触发change事件,那么可以通过中介者来转发处理这些事件,实现各个事件间的解耦,仅仅维护中介者对象即可。
5)装饰着模式
定义:在不改变对象自身的基础上,在程序运行期间给对象动态的添加方法。
适用场景:原有方法维持不变,在原有的方法上再挂载其他方法来满足现有需求;函数的解耦,将函数拆分成多个可复用的函数,再将拆分出来的函数挂载到某个函数上,实现相同的效果但增强了复用性。
24、JavaScript的运行机制
JavaScript在执行的过程中会产生执行环境,这些执行环境会被顺利的加入到执行栈中。如果遇到异步的代码,会被挂起并加入到Task(有多种task)队列中。一旦执行栈为空,Event Loop就会从Task队列中拿出需要执行的代码并放入执行栈中执行。
不同的任务源会被分到不同的Task队列中,任务源可以分为微任务和宏任务。
正确的一次Event Loop顺序是这样的:
1)执行同步代码,这属于宏任务
2)执行栈为空,查询是否有微任务需要执行
3)执行所有的微任务
4)渲染UI
5)开始下一轮Event Loop,执行宏任务中的异步代码
由此Event Loop顺序可知,如果宏任务中的异步代码由大量的计算并且需要操作Dom的话,为了更快的界面响应,我们可以把操作Dom放入微任务中。
25、Node.js的Event Loop
Node.js也是单线程的Event Loop,但是它的运行机制不同于浏览器环境。
Node.js运行机制如下:
1)V8引擎解析JavaScript脚本
2)解析后的代码,调用Node API
3)libuv库负责Node API的执行。它将不同的任务分配给不同的线程,形成一个Even Loop(事件循环),以异步的方式将任务的执行结果返回给V8引擎
4)V8引擎再将结果返回给用户
Node.js提供的与”任务队列“有关的方法:
setTimeout与setInterval
process.nextTick方法可以在当前”执行栈“的尾部---下一次Event Loop(主线程读取”任务队列“)之前---触发回调函数。即,它指定的任务总是发生在所有异步任务之前。
setImmediate方法则是在当前”任务队列“的尾部添加事件。即,它指定的任务是在下一次Even Loop时执行。
26、什么是ajax?作用是什么?工作原理?原生js的ajax请求有几个步骤?分别是什么?
ajax是异步的JavaScript和xml。
ajax是一种用于创建快速动态网页的技术。ajax用来与后台交互。
ajax的工作原理相当于在用户和服务器之间加了一个中间层(ajax引擎),使用户操作与服务器响应异步化。并不是所有的用户请求都提交给服务器,像一些数据验证和数据处理等都交给Ajax引擎自己来做,只有确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求。
ajax,实现了客户端与服务器进行数据交流过程。使用技术的好处是:不用页面刷新,并且在等待页面传输数据的同时可以进行其他操作。
步骤:
1)//创建XMLHttpRequest对象
var xhr = new XMLHttpRequest( );
2)//规定请求的类型,URL以及是否异步处理请求
xhr.open ('GET', url, true),第三个参数为true,表示不等待,直接返回异步获取;为false,表示等待有返回数据的时候继续往下走,还没有得到数据的时候就会卡在那里,直到获取数据为止。
3)//发送信息至服务器时内容编码类型
xhr.setRequestHeader('Content-type', 'appliaction/x-www-form-urlencode');
4)//发送请求
xhr.send(null);
5)// 接收服务器响应数据
xhr.onreadystatechange = function( ){
if (obj.readyState == 4 && (obj.status == 200 || obj.status == 304)) { }
}
1)当readystate值从一个值变成另一个值,都会触发readystatechange事件
2)当readystate==4时,表示已经接收到全部响应数据
3)当status==200时,表示服务器成功返回页面和数据
4)如果2),3)内容同时满足,则可以以通过xhr.responsetext,获得服务器返回的内容
ajax运行步骤与状态值说明:
在ajax实际运行当中,对于访问XMLHttpRequest(XHR)时并不是一次完成的,而是分别经历了多种状态后取得的结果,对于这种状态在Ajax中共有5种,分别是:
0---(未初始化)还没有调用send( )方法
1---(载入)已调用send( )方法,正在发送请求
2---(载入完成)send( )方法执行完成
3---(交互)正在解析响应内容
4---(完成)响应内容解析完成,可以在客户端调用了
对于上面的状态,其中”0“状态是在定义后自动具有的状态值,而对于成功访问的状态(得到信息)我们大多数采用”4“进行判断。
响应状态码:
200---请求成功,正常返回数据
301---删除请求数据,重定向
304---该资源在上次请求之后没有任何修改(通常用于浏览器的缓存机制)
401---请求要求身份验证
403---服务器拒绝请求
404---服务器找不到请求的网页
408---服务器等候请求时发生请求超时
500---服务器内部错误,无法完成请求
27、跨标签页通讯
1)本地存储:localStorage
// 页面A发送事件
function sendMsg(text) {
window.localStorage.setItem('msg',text);
}
// 页面B接收事件
window.addEventListener('storage', function (evt) {
if(evt.key==='msg')
console.log(evt.newValue);
});
注意:重复设置相同的键值不会再次触发事件
2)使用cookie+setInterval,将要传递的信息存储在cookie里面,然后每隔一定时间读取cookie信息来实现。
<input type="button" id="butOk" value="信息">
// a页面
var mess=document.getElementById("butOk").value();
document.cookie="mess="+mess;
// b页面
// 获取Cookie天的内容
function getKey(key) {
return JSON.parse("{\""+ document.cookie.replace(/;\s+/gim,"\",\"").replace(/=/gim, "\":\"") +"\"}")[key];
}
//每隔1秒获取Cookie的内容
setInterval(function(){
console.log(getKey("mess"));
},1000);
Cookie cookie = new Cookie("time","20080808"); // 新建Cookie
cookie.setDomain(".helloweenvsfei.com"); // 设置域名
cookie.setPath("/"); // 设置路径
cookie.setMaxAge(Integer.MAX_VALUE); // 设置有效期
cookie.setSecure(true); // 设置安全属性
response.addCookie(cookie); // 输出到客户端
28、防抖动与节流的区别:
1)防抖动是将多次执行变为最后一次执行。
应用场景:使用在用户输入停止一段时间过去后再去获取数据,而不是每次输入都去获取。
// 实现一个防抖函数,在规定时间内未触发第二次则执行
function debounce(fn, delay){
// 利用闭包保存定时器
let timer = null
return function (){
let context = this
let arg = arguments
// 在规定时间内再次触发会先清除定时器后再重设定时器
clearTimeout(timer)
timer = setTimeout(function(){
fn.apply(context,arg)
}, delay)
}
}
function fn(){
console.log('防抖')
}
addEventListener('scroll', debounce(fn, 1000))
2)节流是将多次执行变成每隔一段时间执行。
应用场景:懒加载时要监听计算滚动条的位置,但不必每次滑动都触发,可以降低计算的频率,而不必去浪费资源;
另外还有做商品预览图的放大镜效果时,不必每次鼠标移动都计算位置。
// 实现一个节流函数,在规定时间内只触发一次
function throttle(fn,delay){
// 利用闭包保存时间
let prev = Date.now()
return function(){
let context = this
let arg = arguments
let now = Date.now()
if(now - prev >= delay){
fn.apply(context, arg)
prev = Date.now()
}
}
}
function fn(){
console.log('节流')
}
addEventListener('scroll', throttle(fn, 1000))
29、浏览器渲染过程:
1)浏览器将获取的HTML文档并解析成DOM树
2)处理CSS标记,构成层叠样式表模型CSSDOM(css Object Model)
3)将DOM和CSSDOM合并为渲染树(rending tree)将会被创建,代表一系列将被渲染的对象
4)渲染树的每个元素包含的内容都是计算过的,它被称为布局layout。浏览器使用一种流式处理的方法,只需要一次pass绘制操作就可以布局所有的元素
5)将渲染树的各个节点绘制到屏幕上,这一步被称为绘制painting
30、计算机网络TCP和UDP的区别:
1)TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
2)TCP提供可靠的服务。即,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付。TCP通过校验,重传控制,序号标识,滑动窗口,确认应答实现可靠传输。如,丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。
3)UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
4)每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
5)TCP系统资源要求较多,UDP对系统资源要求较少
31、进程和线程的区别:
1)一个程序至少有一个进程,一个进程至少有一个线程
2)线程的划分尺度小于进程,使得多线程程序的并发性高
3)进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大的提高了程序的运行效率。
4)线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口,顺序执行序列和程序的出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
5)从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程调度和管理以及资源分配。
32、如何让事件先冒泡后捕获:
在Dom标准事件模型中,是先捕获后冒泡。但是如果要实现先冒泡后捕获的效果,对于同一个事件,监听捕获和冒泡,分别对应相应的处理函数,监听到捕获事件,先暂缓执行,直到冒泡事件被捕获后再执行捕获之间。
33、事件委托:
简介:事件委托指的是,不在事件的发生地(直接dom)上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判断事件发生元素Dom的类型,来做出不同的响应。
举例:最经典的就是ul和li标签的事件监听,比如我们在添加事件时候,采用事件委托机制,不会再li标签上直接添加,而是再ul父元素上添加。
好处:比较合适动态元素的绑定,新添加的子元素也会有监听函数,也可以有事件触发机制。
34、图片的懒加载和预加载
预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染‘
懒加载:懒加载的主要目的时作为服务器前端的优化,减少请求数或延迟请求数
两种技术的本质:两者的行为时相反的,一个时提前加载,一个是迟缓甚至不加载
懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力
35、函数柯里化:
属于高阶函数应用,传递给函数部分参数来调用柯里化函数,让它返回一个函数去处理剩下的参数。
把接收多个参数的函数转换成接收一个单一参数的函数。
var foo = fucntion(x){
return function(y){
return x+y;
}
}
foo(3)(4) // 输出为7
36、requestAnimationFrame是怎么使用的?
requestAnimationFrame( )方法告诉浏览器,希望执行动画并请求浏览器在下一次重绘之前调用指定的函数来更新动画。该方法使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用
37、PWA全称是Progressive Web App,即渐进式WEB应用。一个PWA应用首先是一个网页,可以通过Web技术编写出一个网页应用。随后添加上App Manifest和Service Worker来实现PWA的安装和离线等功能。
38、数据属性与访问器属性的区别:
在JS中对象的属性分为两种类型:数据属性和访问器属性。
1)数据属性:它包含的是一个数据值的位置,在这可以对数据值进行读写。
包含四个特性:
configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或能否把属性修改为访问器属性,默认为true
enumerable:表示能否通过for-in循环返回属性
writable:表示能否修改属性的值
value:包含该属性的数据值。默认为undefined
修改数据属性的默认特性: 使用Object.defineProperty( )方法,这个方法有三个参数:属性所在的对象,属性名,一个描述符对象。
2)访问器属性:这个属性不包含数据值,包含的是一对get和set方法,在读写访问器属性时,就是通过这两个方法来进行操作处理的。
包含的四个特性:
configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或能否把属性修改为访问器属性,默认为false
enumerable:表示能否通过for-in循环返回属性,默认为false
Get:在读取属性时调用的函数,默认值为undefined
Set:在写入属性时调用的函数,默认值为undefined
注意:访问器属性不能直接定义,要通过Object.defineProperty( )这个方法来定义。
后续需要对该属性进行delete操作等,就需要定义访问器属性时,将这个特性设置为true。
39、Proxy 对象用于定义基本操作的自定义行为(如,属性查找、赋值、枚举、函数调用等)。
const p = new Proxy(target, handler);
target,要使用Proxy包装的目标对象(可以时任何类型的对象,包括原生数组,函数,甚至另一个代理)。
handle,一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理的行为。
Proxy.revocable( )---创建一个可撤销的proxy对象。
40、Echarts的应用:
1)常见配置:
title:{...}-----标题
legend:{...}-----图标
grid:{...}-----布局,坐标面板位置
xAxis:{...}-----X轴
yAxis:{...}-----Y轴
tooltip:{...}-----图标悬停的提示内容
toolBox:{...}-----工具栏组件,内置有导出图片,数据视图,动态类型切换,数据区域缩放,重置5个工具
series:[...]-----系列,它是一个数组,里面的元素是一个对象,每个对象就是一组数据的所有信息
2)echarts的API交互
echarts:{...}----主要时获取或设置全局属性对象API相关的
echartsInstance:{...}-----主要是获取或设置图标echart.init对象相关的API属性
action:{...}-----主要是包含一些event事件和一些数据可视化的行为设置例如高亮,tooltip位置设置等
events:{...}----主要是图表的一些触发事件
3)echarts常见问题解决
a、当X轴上面要渲染的数据太多的时候就会出现只渲染出来一部分,但是图标中的数据显示(比如说柱状图中的每个柱子)又会自动的进行宽度的缩放,所以会导致X轴与图中的信息不相匹配的问题,解决的方法是在X轴设置axisLable:{interval:0}这个属性问题就可以解决了,Y轴的使用相同的方法。
b、为了使echart图标随着浏览器的大小发生响应式变化,所以需要在设置配置之前添加window.onresize = echart.resize;
4)调用实例myChart的setOption( )方法,将option这个对象搞定到自己身上。
41、Echarts与D3的区别:
Echarts:1)封装好的方法直接调用
2)兼容到IE6以及以上的所有主流浏览器
3)echarts通过canvas来绘制图形
4)封装好的,直接用,不能修改
D3:1)太底层,学习成本大
2)兼容到IE9以上以及所有的主浏览器
3)D3通过svg来绘制图形
4)可以自定义事件
42、Svg与Canvas的区别:
Svg:1)不依赖分辨率
2)基于xml绘制图形,可以操作dom
3)支持事件处理
4)复杂度高,会减慢页面的渲染速度
Canvas:1)依赖分辨率
2)基于js绘制图形
3)不支持事件处理器
4)能以png/jpg的格式保存图片
43、网络协议:
1)IP协议(寻址)47.95.70.218
2)IP协议之上,使用Tcp来确保数据的完整有序
三次握手,滑动窗口,慢启动,挥手,分包,重发
3)Tcp协议之上,使用http协议来作为网页传输的协议(应用层)
44、XSS防御总结:
原理:XSS攻击涉及到三方,攻击者、用户、web serve。用户是通过浏览器来访问web server上的网页,XSS攻击就是攻击者通过各种办法,在用户访问的网页中插入自己的脚本,让其在用户访问网页时在其浏览器中进行执行。攻击者通过插入的脚本的执行,来获取用户的信息,如cookie,发送到攻击者自己的网站(跨站了)。所以称为跨站脚本攻击。
分类:XSS可以分为反射型XSS和持久型XSS,还有DOM Based XSS。
(XSS,就是在用户的浏览器中执行攻击者自己定制的脚本。)
1)反射型XSS,也就是非持久性XSS。用户点击攻击连接,服务器解析后响应,在返回的响应内容中出现攻击者的XSS代码,被浏览器执行。一来一去,XSS攻击脚本被web server反射回来给浏览器,所以称为反射型XSS。
特点:XSS攻击代码非持久性,也就是没有保存在web server中,而是出现在URL地址中;一般时攻击者通过邮件,聊天软件等等方式发送攻击URL,然后用户点击来达到攻击目的。
XSS 攻击的防御:对输入(和URL参数)进行过滤,对输出进行编码。
45、webSocket:
http协议有一个缺陷,通信只能由客户端发起。做不到服务器主动向客户端推送信息。这种单向请求,注定了如果服务器有连续的状态变化,客户端要获知,只能使用“轮询”,每隔一段时间,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。轮询的效率低,非常浪费资源。
webSocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议。webSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在webSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。它最大的特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
特点:
1)建立在TCP协议之上,服务器端的实现比较容易
2)与http有良好的兼容性,默认端口也是80与443,并且握手阶段采用http协议,因此握手时不容易屏蔽,能通过各种http代理服务器
3)数据格式比较轻量,性能开销小,通信高效
4)可以发送文本,也可以发送二进制数据
5)没有同源限制,客户端可以与任意服务器通信
6)协议标识符是WS(如果加密,则为wss),服务器网站就是URL
用法:
// webSocket对象作为一个构造函数,用于新建webSocket实例,实行下面语句后,客户端就会与服务器进行连接。
var ws = new WebSocket("ws://localhost:8080");
ws.onopen = function(evt) { // 指定连接成功后的回调函数
console.log("Connection open ...");
ws.send("Hello WebSockets!"); //// send( )方法用于向服务器发送数据
};
// 用于指定收到服务器数据后的回调函数,除了动态判断收到的数据类型,也可以用binaryType属性,显示指定收到的二进制数据类型
ws.onmessage = function(evt) {
console.log( "Received Message: " + evt.data);
ws.close();
};
ws.onclose = function(evt) { // 用于指定连接关闭后的回调函数
console.log("Connection closed.");
};
46、web前端性能优化常见方法:
内容优化:
1)减少HTTP请求数,因为一个完整的请求要经过DNS寻址,与服务器建立连接,发送数据,等待服务器响应,接收数据这样一个消耗时间成本和资源成本的复杂的过程。 常见方法:合并多个CSS文件和JS文件,利用雪碧图整合图像,Inline Image(使用data:URL scheme在实际的页面嵌入图像数据),合理设置HTTP缓存等。
2)减少DNS查找
3)避免重定向
4)使用Ajax缓存
5)延迟加载组件,预加载组件
6)减少DOM元素数量:页面中存在大量DOM 元素,会导致JavaScript遍历DOM的效率变慢
7)最小化iframe的数量:iframes提供了一个简单的方式把一个网站的内容嵌入到另一个网站中。但其创建速度比其他包括JavaScript和CSS的DOM元素的创建慢了1-2个数量级。
8)避免404:HTTP请求时间消耗是很大的,因此使用HTTP请求来获得一个没有用处的响应(例如404没有找到页面)是完全没有必要的,它只会降低用户体验而不会有一点好处。
服务器优化:
1)使用内容分发网络(CDN):把网站内容分散到多个,处于不同地域位置的服务器上可以加快下载速度。
2)gzip压缩
3)设置Etag:Etags(Entity tags,实体标签)是web服务器和浏览器用于判断浏览器缓存中的内容和服务器中的原始内容是否匹配的一种机制
4)提前刷新缓冲区
5)对Ajax请求使用GET方法
6)避免空的图像src
Cookie优化:
1)减少Cookie大小
2)针对web组件使用域名无关的Cookie
CSS优化:
1)将css代码放在HTML页面的顶部
2)避免使用css表达式
3)使用<link>来代替@import
4)避免使用Filters
JavaScript优化:
1)将JavaScript脚本放在页面的底部
2)将JavaScript和CSS作为外部文件来引用,在实际应用中使用外部文件可以提高页面速度,因为JavaScript和CSS文件都能在浏览器中产生缓存
3)缩小JavaScript和CSS
4)删除重复的脚本
5)最小化DOM的访问:使用JavaScript访问DOM元素比较慢
6)JavaScript代码注意:谨慎使用with,避免使用eval Function函数,减少作用域链查找(eval将对应的字符串解析成js并执行,应该避免使用js,因为非常耗性能(2次,一次解析成js,一次执行))
图像优化:
1)优化图片大小
2)通过CSS Sprites优化图片
3)不要在HTML中使用缩放图片
4)favicon.ico要小而且可缓存
移动客户端:
1)保持单个内容小于25KB
2)打包组建成符合文档
47、JS里的垃圾回收机制是什么,常用的是哪种,怎么处理的?
JS的垃圾回收机制是为了以防内存泄漏。内存泄漏的含义就是当已经不需要某块内存时这块内存还存在着,垃圾回收机制就是间歇的不定期的寻找到不再使用的变量,并释放掉它们所指向的内存。
JS中最常见的垃圾回收方式是标记清除。
工作原理:是当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。
工作流程:
1)垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记。
2)去掉环境中的变量以及被环境中的变量引用的变量的标记。
3)再被加上标记的会被视为准备删除的变量。
4)垃圾回收器完成内存清除工作,销毁那些带标记的值并回收他们所占用的内存空间。
JS中的内存泄漏:
程序不需要的内存,由于某些原因其不会返回到操作系统或者可用内存中。内存泄漏会导致(运行缓慢,高延迟,崩溃)的问题。
常见的导致内存泄漏的原因有:
1)意外的全局变量
2)被遗忘的计时器或回调函数
3)脱离文档的DOM的引用
4)闭包
48、for-in和for-of的区别:
1)循环对象属性的时候,使用for...in,遍历数组的时候使用for...of
2)for...in循环出的是key,for...of循环出的是value
3)for...of是ES6新引入的特性。修复了ES5引入的for...in的不足
4)for...of不能循环普通的对象,需要通过和Object.keys( )搭配使用
49、Math.min( )和Math.max( )大小比较:
Math.min( ) < Math.max( )
Math.min( )如果没有参数,则返回Infinity。Infinity是JavaScript中全局对象的一个属性,在浏览器环境中就是window对象的一个属性,表示无穷大。
Math.max( )没有传递参数时返回的是-Infinity。因此Math.min( ) 要比Math.max( )大。
50、前端JS加密方法:
1)base64加密
2)md5加密
3)sha1加密
网友评论