-
深入理解DOM数加载过程
1.在浏览器中输入url,交给DNS域名解析,找到IP,向服务器发起请求;(里面还有缓存,http协议,TCP...)
2. 服务器返回数据,浏览器接收文件(html,css,js,img...),二进制文件
html:二进制转换为html
构建DOM树:HTML解析器
Token->Node->DOM
Token词法解析,根是"document"对象
Node:HTMLDivElement
DOM:DOM和标签基本是一一对应的关系div
解析过程中:
1.遇到link的外部css,遇到css的代码会进行css加载,并行解析
2.遇到script标签的时候,会先去执行js的内容,直至脚本完成执行,然后继续构建DOM;
底部引入Javascript代码的原因。或者说可以在头部引用,但是前提是加上async、defer,或window.onload:
解析器遇到设置了async属性的script时,开始下载脚本并继续解析文档。脚本会在它下载完成后尽快执行,但是解析器不会停下来等它下载
如果script标签设置了该属性,则浏览器会异步下载该文件并且不会影响后续DOM的渲染;
如果有多个设置了defer的script标签存在,则会按照顺序执行所有的script;
defer脚本会在文档渲染完毕后,DOMContentLoaded事件调用前执行;脚本会被延迟到整个页面都解析完毕后再运行
构建css树:css解析器
每个css文件解析为样式表对象scctyleSheet,每个对象都包含cssRule,cssRule包含选择器和声明对象,以及其他与css语法对应的对象。
Token解析:css的词法及语法文法
Node->CSSOM
构建render树:渲染树=DOM树+css树
布局layout与绘制paint:计算对象之间的大小,距离确定每个节点在屏幕上的确切坐标;映射浏览器屏幕绘制;使用UI后端层绘制每个节点
reflow(回流):当元素属性发生改变且影响布局时(宽度、高度、内外边距等),产生回流,相当于刷新页面
repaint(重绘):当元素属性发生改变且不影响布局时(背景颜色,透明度,字体样式等),产生重绘,相当于不刷新页面,动态更新内容。
查看全部 -
history
window.history 属性指向History对象,它标识当前浏览器历史 浏览器历史记录是一个栈数据结构(先进后出)
History.back() 后退、History.forward()前进、History.go() 跳转
History.pushState() 向栈里推入数据、History.replaceState()向栈里替换数据
Location 对象 window.location和document.location属性,可以拿到这个对象
Location。href:整个URL
Location.protocol:当前URL的协议,包括冒号(:)
Location.host:主机。如果端口不是协议默认的80和433,则不会包括冒号(:)和端口
Location.hostname:主机名,不包括端口。
Location.port:端口号。
Location.pathname:URL的路径部分,从根路径/开始。
Location.search:查询字符串部分,从问号?开始。
Location.hash:片段字符串部分,从#开始。
Location.username:域名前面的用户名。
Location.password:域名前面的密码。
Location.origin:URL的协议、主机名和端口。
查看全部 -
三种解码方式
查看全部 -
^qUxJg$c43abd01a5fabbba66466a22476d2957b84506584查看全部
-
深拷贝:
//方法一:循环遍历
function deepClone(tartgetObj, endObj) {
var obj = endObj || {}
for (var key in targetObj) {
if(typeof targetObj[key] === 'object') {
obj[key] = tartgetObj.construtor === Array ? [] : Object.create(null)(方法二:{})
deepClone(tartgetObj[key], obj[key])
} else {
obj[key] = targetObj[key]
}
}
return obj
}//方法二
最简单的方法最新的方法,用ES6的扩展运算符(…)进行赋值,这个应该会在以后被广泛应用,这个方法也完美解决了JSON.stringify+JSON.parse不能实现的对函数方法深拷贝:
let obj1 = { name: 'Jay', age: '22',fun:function() {console.log(1)} }
let obj2 = { ...obj1 };
obj2.name = 'xxx'
console.log(obj1.name, obj2.name, obj2)
//输出结果为(jay xxx {name: "xxx", age: "22", fun: ƒ})
//方法三
var copyObj = JSON.parse(JSON.stringify(targetObj)) //object->string->object
查看全部 -
new 的执行过程
查看全部 -
装箱:把基本数据类型转化为对应的引用数据类型的操作;
如何实现:
var num = 123 // number
var objNum = new Number(123) // object
拆箱:将引用类型对象转换为对应的值类型对象;
如何实现:
调用object.valueOf()方法实现
objNum.valueOf() //123
内部如何实现:
toPrimitive(input,type) //input:传入值,type:值类型
// input 判断是不是原始类型的值:如果是,直接返回,
如果不是调用 input.valueOf() 是原始类型,直接返回,
还不是:调用input.toString 直接返回字符串
或者报错
valueOf() 是原始类型的值,直接返回,没有,就返回对象本身
toString() input字符串转换;对象:[object,type] type:对象类型
查看全部 -
1、instanceof 检测 true或false 是由原型链来进行查找判断的,
A instanceof B A是否为B 的实力对象,检测的是原型
2、检测某一个想要的数据的数据类型
Object.prototype.toString.call('1') //string
Object.prototype.toString.call([]) //Array 也是用来检测
查看全部 -
原型链
查看全部 -
事件监听的优点:可以绑定多个事件;常规的事件绑定只执行最后绑定的事件
原因:js不支持事件重载,绑定事件相当于一个变量存储的是函数的地址,如果再绑定一个事件,相当于变量指向另
个函数的地址;事件监听相当于订阅发布者,改变了数据,触发了事件,订阅这个事件的函数被执行
查看全部 -
arr.sort
查看全部 -
两道面试题
console.log([]+[]) // ''
console.log({}+[])//[object object] 或 0
查看全部 -
深拷贝的三种方式
1,JSON.parse(JSON.stringjfy(obj))
缺点:取不到undefined的key,如果对象里有函数,函数无法被拷贝下来,无法拷贝对象原型链中的属性和方法
2,Object.assign({},obj)
缺点:不是真正的深拷贝,属性是对象的时候,对象还是浅拷贝
3,递归方式实现深拷贝
查看全部 -
数据类型
基本数据类型:Undefined、Null、Boolean、Number、String
引用数据类型:Object
typeof
检测null时会返回object,
因为null类型的机器码全是0,
而typeof检测到后三位全是0的时候,会返回object
检测到object类型之后,会再次调用内部的一个[[call]]函数,如果有则返回function,否则返回object
let str = "asdf";
typeof返回string,栈类型存储
let str = new String("asdf")
typeof 返回object,堆类型存储
instanceof
通过原型链来检测,返回boolean值,true false
A instanceof B
A是否是B的实例对象
查看全部 -
浮动数相加不准确问题在于计算机会把浮点数转成二进制 超过计算机存储长度之后 会舍掉 导致转换回来之后数字不精确
// 省略小数点2位之后数字
console.log(parseFloat(0.1+0.2).toFixed(2));
//转成整数类型
function add(m1,m2){
var m=Math.pow(10,2);
return (m1*m+m2*m)/m
}
console.log(add(0.1,0.2));
查看全部
举报