一、js放在head和body标签中的区别
head 部分中的脚本: 需调用才执行的脚本或事件触发执行的脚本放在HTML的head部分中。当你把脚本放在head部分中时,可以保证脚本在任何调用之前被加载。
body 部分中的脚本: 当页面被加载时执行的脚本放在HTML的body部分。放在body部分的脚本通常被用来生成页面的内容。
二、html5的web存储
以前我们在本地存储数据都是用document.cookie来存储的,但是由于其的存储大小只有4K左右,解析也很复杂,给开发带来了诸多的不便.不过现在html5出了web的存储,弥补了cookie的不足,而且开放起来也是相当的方便。
web存储分两类
sessionStorage
容量大小约为5M左右,该方式的生命周期为关闭浏览器窗口为止
localStorage
容量大小约为20M左右, 存储的数据不会随着用户浏览时会话过期而过期,但会应用户的请求而删除。浏览器也因为存储空间的限制或安全原因删除它们.而且类型存储的数据可以同一个浏览器的多个窗口共享
注意点:只能存储字符串,如果是json对象的话,可以将对象JSON.stringify() 编码后存储
方法详解:
setItem(key, value) 设置存储内容
getItem(key) 读取存储内容
removeItem(key) 删除键值为key的存储内容
clear() 清空所有存储内容
写法:
//更新
function update() {
window.sessionStorage.setItem(key, value);
}
//获取
function get() {
window.sessionStorage.getItem(key);
}
//删除
function remove() {
window.sessionStorage.removeItem(key);
}
//清空所有数据
function clear() {
window.sessionStorage.clear();
}
三、页面加载顺序及触发的事件
页面加载大致的几个步骤
1.开始解析HTML文档结构。
2.加载外部样式表及JavaScript脚本。
3.解析执行JavaScript脚本。
4.DOM树渲染完成。
5.加载未完成的资源(如图片)。
6.页面加载成功。
页面加载触发的事件
1.document的readystatechange事件
document.onreadystatechange = function() { // 文档加载状态改变事件处理
if (document.readyState === "loading") { // document加载中
console.log(document.readyState);
}
if (document.readyState === "interactive") { // 互动文档加载完成,文档解析完成,但是如图像,样式表和框架等子资源仍在加载中
console.log(document.readyState);
}
if (document.readyState === "complete") { // 文档和所有子资源加载完成,load事件即将被触发
console.log(document.readyState);
}
}
readyState属性描述了文档的加载状态,整个加载过程中document.readyState会不断变化,每次变化都触发readystatechange事件。
也可以用事件监听器去绑定:
document.addEventListener("readystatechange", function() {
console.log(document.readyState);
});
2.document的DOMContentLoaded事件
DOM树渲染完成时候触发DOMContentLoaded事件,此时可能外部资源还在加载。jQuery中的ready事件就是实现的这个事件。
3.window的load事件
当所有的资源全部加载完成后就会触发window的load事件。
load()和onload 效果是一样的 都是在页面所有内容加载完才执行;但是onload只能有一个,load可以有多个; ready()是DOM结构树绘制完毕后执行。
四、JS中,使用什么属性可以对Dog类添加方法eat( )
prototype
Dog.prototype.eat = function( ){}
五、用Promise封装Ajax
Promise的出现主要是解决地狱回调的问题,比如你需要结果需要请求很多个接口,这些接口的参数需要另外那个的接口返回的数据作为依赖,这样就需要我们一层嵌套一层,但是有Promise 我们就无需嵌套。Promise的本质就是分离了异步数据获取和业务逻辑。
ajax
$.ajax({
method:"post",
url:"/xxx",
data:"username=mtt&password=1",
dataType:'json',
success:()=>{}//成功后的回调函数
error:()=>{}//失败后的回调函数
}
)
用promise封装ajax
let myButton = document.getElementById('myButton');
function success(responseText){
console.log("成功")
console.log(responseText);//responseTex
}
function fail(request){
console.log("失败")
console.log(request);
}
myButton.addEventListener("click",(e)=>{
//使用ajax
$.ajax({
method:"post",
url:"/xxx",
data:"username=mtt&password=1",
dataType:'json'//预期服务器返回的数据类型,如果不写,就是响应里设置的
}
).then(success,fail)//$.ajax()返回一个promise
})
用promise封装函数的通用模板
function xxx(){
return new Promise((f1, f2) => {
doSomething()
setTimeout(()=>{
// 成功就调用 f1,失败就调用 f2
},3000)
})
}
xxx().then(success, fail)
// 链式操作
xxx().then(success, fail).then(success, fail)
六、浏览器渲染页面的过程,以及重绘和重排
回流
当render tree中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候。
重绘
当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘。
注意
回流必将引起重绘,而重绘不一定会引起回流。执行顺序:先回流后重绘。
回流何时发生:
当页面布局和几何属性改变时就需要回流。下述情况会发生浏览器回流:
1、添加或者删除可见的DOM元素;
2、元素位置改变;
3、元素尺寸改变——边距、填充、边框、宽度和高度
4、内容改变——比如文本改变或者图片大小改变而引起的计算值宽度和高度改变;
5、页面渲染初始化;
6、浏览器窗口尺寸改变——resize事件发生时;
减少回流、重绘
(1) 避免操作DOM,创建一个documentFragment或div,在它上面应用所有DOM操作,最后再把它添加到window.document。也可以在一个display:none的元素上进行操作,最终把它显示出来。因为display:none上的DOM操作不会引发回流和重绘。
(2) 让要操作的元素进行"离线处理",处理完后一起更新,这里所谓的"离线处理"即让元素不存在于render tree中。如读取offsetLeft等属性。
(3) 尽可能在DOM树的末端改变class ,尽可能在DOM树的里面改变class,可以限制回流的范围,使其影响尽可能少的节点。
(4) 避免设置多层内联样式,因为每一个都会造成回流,样式合并在一个外部类,这样当该元素的class属性被操作时,只会产生一个reflow。
(5) 将需要多次回流的元素position属性设为absolute或fixed,这样该元素就会脱离文档流,它的变化不会影响其他元素变化。比如动画效果应用到position属性为absolute或fixed的元素上。
(6) 牺牲平滑度换取速度,动画元素每次移动3像素可能在非常快的机器上看起来平滑度低了,但它不会导致CPU在较慢的机器和移动设备中抖动
(7) 避免使用table布局,在布局完全建立之前,table需要很多关口,table是可以影响之前已经进入的DOM元素的显示的元素。即使一些小的变化和会导致table中所有其他节点回流。
(8) 避免使用css的JavaScript表达式,该规则较过时,但是个好主意。因为每次都需要重新计算文档,或部分文档、回流。
七、XMLHTTPRequest和JSONP的应用场景,以及其分别如何检测请求错误的
XMLHttpRequest
用于浏览器端与服务器端异步请求数据,实现对页面的无刷新修改,支持GET/POST请求,一般用于非跨域的场景。如果需要使用XMLHttpRequest跨域请求数据,需要通过CORS头支持。
JSONP
用于跨域请求数据的场景,只支持GET请求。jsonp的核心原理就是目标页面回调本地页面的方法,并带入参数。JSONP 全称是 JSON with Padding,JSONP可能会引起CSRF(Cross-site request forgery 跨站请求伪造)攻击或XSS (Cross Site Scripting 跨站脚本攻击)漏洞。输出 JSON 时,没有严格定义好 Content-Type(Content-Type: application/json)直接导致了一个典型的 XSS 漏洞。对于支持JSONP的接口,写接口时数据可能会被篡改,读接口时数据可能会被劫持。
主要解决方案:
a.Referer 严谨过滤
b.严格定义输出的 Content-Type: application/json,浏览器不解析恶意插入的 XSS 代码(直接访问提示文件下载)
c.部署一次性 Token
d.限制callback函数名长度,严格过滤callback函数名
e.过滤JSON里数据的输出
异常判断
XMLHttpRequest:一般通过该对象的readystate和http状态码status来判断。
JSONP:一般是onerror事件和超时timer来判断。
Token的定义:Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。
使用Token的目的:Token的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。