前言
1、写给自己看,有些东西只有自己能懂
2、不定时更新(直到找到工作)
干货?
HTML
- 渲染html的过程
1、浏览器解析html源码,创建一个DOM树,并行请求其他js/css/image文件(注意并行请求仍会阻塞,想要不阻塞可以使用异步加载或者延迟加载)
- css加载不阻塞html解析,但是会阻塞dom渲染;
- css加载阻塞后面js语句执行;
- js会阻塞html的解析和渲染;
- 没有async和defer的script标签会立即加载
- 有async的js,js的加载执行和html的解析和渲染并行
- 有defer标签的js,js的加载和html的解析和渲染并行,但会在html解析完成后执行
- DOMContentLoaded和onload的区别:DOMContentLoaded在html解析完毕后执行,onload在页面完全加载完成后执行(包括样式和图片)
2、解析css,生成CSSOM——css对象模型
3、dom和css合并,构建渲染树(Render Tree)
4、布局(Layout)和绘制(Paint),重绘(repaint)和重排(reflow/回流)
1)重绘:根据元素的新属性重新绘制,使元素呈现新的外观
2)重排:当渲染树中的一部分因为元素的规模尺寸,布局,隐藏等改变而需要重新构建
3)重排必定会引发重绘,但重绘不一定会引发重排
- 盒子模型
所有HTML元素都可以看作盒子模型,用来设计和布局,CSS盒模型本质是一个盒子,它包括margin
,border
,padding
,content
- 监听资源加载的方式
- window.onload = function(){…}
- window.addEventListener(“load”,function(){…});
- document.body.onload = function(){…}
<body onload = "load()">
CSS方面
- 清除浮动:
容器中有元素浮动时(float),子元素脱离文档流不能撑开父元素
<div class="out">
<div class="n1"></div>
<div class="n2"></div>
</div>
<style>
.out{border:1px solid red}
.n1,.n2{width:100px;height:100px;float:left}
</style>
- 父元素内增加一个div,给这个div加上css属性
clear:both
<div class="out">
<div class="n1"></div>
<div class="n2"></div>
<div class="new"><div>
</div>
<style>
.out{border:1px solid red}
.n1,.n2{width:100px;height:100px;float:left}
.new{clear:both}
</style>
- 父元素添加伪元素
:after
.out:after{
display:block;
content:'';
clear:both
}
overflow
属性:父元素添加
.out{overflow:hidden}
- 水平居中和垂直居中:
- 行内元素-水平居中和垂直居中:父元素:
text-align:center;line-height:父元素高度100% //必须是具体值不能是100%
- 块级元素-只是水平居中:目标元素:
margin:auto;
- 块级元素-水平居中和垂直居中-绝对定位布局:
//目标元素
position:absolute;
left:50%;
top:50%;
transform:translate(-50%,-50%)
//这里的50%是相对于盒子元素宽度或者高度的
- 块级元素水平居中和垂直居中-flex弹性布局:
//父元素
display:flex;
justify-content:center;
align-items:center
- 画一个三角形
<div></div>
div{
width:0;height:0;
border-width:100px;
border-style:solid;
border-color:#000 transparent transparent transparent ;
}
- calc、support、media的作用和写法
- calc计算长度的:
width:calc(100% - 200px)
- support检测浏览器是否支持某个属性,支持的话写一套样式,不支持写一套样式:
//常规写法
@support(display:flex){
div{display:flex}
}
逻辑操作符:
1、not:非
@supports not (display: flex) { div { float: right; }}
2、and:且
@supports (display: flex) and (display:block) { div { float: right; }}
3、or:或
@supports (display: flex) or (display:block) { div { float: right; }}
- media是媒体查询(两种用法):定义不同媒体下显示的不同样式
逻辑操作:and、not、only
//1、在css文件中
@media screen and (max-width: 300px) {
body {
background-color:lightblue;
}
}
//2、link标签中:设置不同媒体调用的css文件
<link rel="stylesheet" media="screen and (max-width:200px)" href="mystylesheet.css">
js部分
- 遍历id为a的父节点下的所有子节点
var myparent=document.getelementById('a').parentNode.children
- 递归实现1-100之和
function add(num1,num2){
var num = num1+num2
if(num2 <= 100){
return add(num,num2+1)
}
else return num
}
add(0,1)
- 变量提升与函数提升
变量提升在函数提升之前
例子:
function foo() {
console.log(a);
var a = 1;
console.log(a);
function a() {}
console.log(a);
}
foo();
实际上在js眼中:
function foo() {
var a;
function a() {}
console.log(a); // a()
a = 1;
console.log(a); // 1
console.log(a); // 1
}
foo();
技巧:将变量声明部分提升到函数顶部,其余逻辑顺序不变
- __proto__ , prototype,constructor,原型链
-
proto是每个对象都有的,指向其构造函数的prototype,实例调用一个属性时先在本身找,没有的话会沿着proto继续往上找,直到Object.prototype,prototype的proto指向的是null,最后返回undefined
-
prototype是构造函数独有,可以向上面能添加一些属性和方法,并且已经实例化的对象能够访问到该属性
-
constructor指向该对象的构造函数
-
原型链就是沿着proto寻找prototype的这条链路称为原型链:
- 作用域和作用域链
- 作用域是指变量或者资源的可访问性,比如在函数内部定义的变量,在函数外部不能被调用,有效防止变量外泄,在其他作用域中有同名变量也不会起冲突
- 作用域链:如果在当前作用域没有找到目标变量,就会向上父级作用域寻找,直到全局作用域都没有就放弃,这一次次 的关系就称为作用域链。
- 全局作用域:创建的变量和函数都会被作为window对象的属性被保存下来,即可以通过window.a的形式调用。
- 局部作用域:函数内部的作用域,只在函数内部起作用,每次调用完函数就会销毁该作用域,每调用一次都会创建新的作用域,他们相互直接是独立的.
- 块级作用域
{}
这样的代码中包括的作用域为块级作用域,其中var
在块级作用域中声明的变量是能够跨块级作用域的,let和const只能在块级作用域中起作用。
- 闭包
function fn(){
var num =1
return function(){
var n=0;
console.log(++n)
console.log(++num)
}
}
var fun=fn()
fun() //此时输出0,1
fun() //此时输出0,2
- 定义:外部作用域无法访问函数的局部作用域,想要一个外部作用域访问一个函数内部作用域的变量,这就叫闭包。
- 实现方法:在一个函数内部创建并返回一个新的函数;
- 实现原理(以上面例子来说):可以先看一下下面写的回收机制,fn函数在被调用之后其中的num本应该被立即销毁掉,但是这里返回了一个函数,这个函数引用了num,所以num不会被垃圾回收机制所清除。
- js中的垃圾回收机制
- 什么是垃圾? 一般来说没有被引用的对象就是垃圾就要被清除,形成环但是没有根不能访问到他也是垃圾,这些对象也要被清除。
- 垃圾如何回收 用“标记-清除”算法,即标记根之后标记他们的引用以及所有子孙代的引用,在进程中如果发现不能访问到的对象将被作为垃圾清除。
- 最简单的垃圾回收例子 :
var a=666 ; a=777
,这里的666
被覆盖掉了变成不可访问的状态,垃圾回收器把666丢弃,并释放内存。
- 深拷贝与浅拷贝
- 浅拷贝:不解释
- 深拷贝:与浅拷贝相反,修改其中的值不会引起源对象变化
- 实现深拷贝方法1:for in循环+递归复制,将原对象或数组的属性元素一个个重新赋值到新对象或数组中去,直到结束。
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
// 判断ojb子元素是否为对象,如果是,递归复制
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
// 如果不是,简单复制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
- 实现深拷贝方法2 :JSON方法的stringify和parse,但是有缺点:对undefind和function是忽略的,且不能处理循环对象。
JSON.parse(JSON.stringify({a:90,b:99}))
- 实现深拷贝方法3 : jquery的extend
var a={}
$.extend(true,{},a)
- 实现深拷贝方法4:…(三个点)和Object.dessign(),缺点:只能深拷贝一级,如果对象中有嵌套的对象,那么二级对象及以上则为浅拷贝,…拷贝数组的时候输出索引和数组元素键值对的形式,用…深拷贝空数组时会输出空对象,assign用来拷贝数组时是从每个数组的索引开始拷贝的,后面的索引会覆盖i前面的索引。
//assign拷贝对象
var a={a:1}
var b={b:2}
Object.assign(a,b) //第一个时目标对象,第二个以上是要被拷贝的对象
//a={a:1,b:2}
//...拷贝对象
var a={a:1}
var b={...a}
//b={a:1}
//assign拷贝数组
var a=[1,2,3]
var b=[4]
var c=[5,6]
Object.assign(a,b,c)
//a=[5,6,3]
//...拷贝数组
var a=[1,2,3,4]
var b={...a}
//b={
// 0:1,
// 1:2,
// 2:3,
// 3:4
// }
- DOM事件流
- 捕获+冒泡
- 事件:用户或浏览器执行的某种动作,如:click,onmouseover
- 冒泡事件和捕获事件
- 冒泡事件:DOM树叶子节点到根节点方向传播。<div>—><body>—><html>—>document
- 捕获事件:DOM树根节点到叶子节点方向传播。document -> <html> -> <body> -> <div>
- 顺序:先捕获后冒泡
- DOM事件流三阶段:1、捕获;2、目标阶段(div),被看作冒泡事件的一部分;3、冒泡;
- 阻止事件冒泡
- even.stopPropagation()
- 事件流 - 事件代理
- 原理:用到的就是事件的冒泡和目标元素,将事件绑定到父元素上,并且父元素能通过
event.target
(target为事件本身)来判断是哪一个子元素,从而做出响应的处理动作
<body>
<ul id="color-list">
<li>red</li>
<li>orange</li>
<li>yellow</li>
<li>green</li>
<li>blue</li>
<li>indigo</li>
<li>purple</li>
</ul>
<script>
(function(){
var colorList=document.getElementById("color-list");
colorList.addEventListener('click',showColor,false);
function showColor(e)
{
var target=e.target
if(target.nodeName==="LI"){
alert(target.innerHTML);
}
}
})();
</script>
</body>
- 优点:不用给每个子元素添加事件了,提高性能;在内添加其他子元素时也不需要重新绑定事件直接修改这个代理事件处理函数就可以了。
target
、currentTarget
的区别?:target
是当前被点击的元素,currentTarget
是当前所绑定的元素。
- cookie - 原生js实现
- cookie获取到的样子
aaa=999;bbb=888
,key=value的形式 - 获取当前页面所有cookie:
document.cookie
- 设置cookie:document.cookie=“aaa=666;expires=213124”,expires是过期时间,值为时间戳
- 设置时间方法
var myDate = new Date()
myDate.setTime(myDate.getTime()+1*24*60*60*1000)
- 删除cookie是将目标cookie的时间设置成过期时间就可以了
- post与get的区别。
-
get传参方式是通过地址栏URL传递,是可以直接看到get传递的参数,post传参方式参数URL不可见,get把请求的数据在URL后通过?连接,通过&进行参数分割。psot将参数存放在HTTP的包体内
-
get传递数据是通过URL进行传递,对传递的数据长度是受到URL大小的限制,URL最大长度是2048个字符。post没有长度限制
-
get后退不会有影响,post后退会重新进行提交
-
get请求可以被缓存,post不可以被缓存
-
get请求只URL编码,post支持多种编码方式
-
get请求的记录会留在历史记录中,post请求不会留在历史记录
-
get只支持ASCII字符,post没有字符类型限制