// 头部
// 导航条
// 主要内容
区块
// 主要内容、文章、帖子、博客等
// 侧边栏
// 页脚
语义化的理解:
正确的标签干正确的事
让页面结构化,结构更清晰,便于对浏览器、搜索引擎解析
有利于SEO
方便其他设备解析执行,例如盲人阅读器
便于团队开发与维护
块级元素:
div、h1~h6、p、ol、ul、li、dl、dt、dd、table、tr、td、form、footer、nav、header、aside、section、article等
行内元素:
span、a、img、b、i、u、del、sup、em、strong、video、input、button、textarea、
内联块状元素: 、
空元素:
常见的有:br hr img input link meta 鲜见的有:area base col colgroup param
1、块级元素:块级元素独占一行,默认宽度为100%
2、行内元素:行内元素在同一行显示,默认宽度由内容撑开
3、块级元素可以设置宽高,行内元素设置宽高不生效
4、行内元素width 和 height 属性将不起作用.
5、块级元素可以设置margin和padding的四周,行内元素只能设置margin和padding的左右 6、块级元素默认display为block,行内元素默认display为inline
7、布局时,块级元素可以包含块级元素和行内元素,行内元素一般不要包含块级元素
行内框架,在网页中可以嵌入另外一个网页
优点:
解决加载缓慢的第三方内容如图标和广告等的加载问题 Security sandbox 并行加载脚本
缺点:阻塞onload加载事件,不利seo(你的网站在百度可以被人更快搜索到);即时内容为空,加载也需要时间;没有语意
解决方法:使用js动态添加iframe 设置src
alt 是给搜索引擎识别,在图像无法显示时的替代文本;
title 是关于元素的注释信息,主要是给用户解读。
当鼠标放到文字或是图片上时有 title 文字显示。(因为 IE 不标准)在 IE 浏览器中 alt 起到了 title 的作用,变成文字提示。 在定义 img 对象时,将 alt 和 title 属性写全,可以保证在各种浏览器中都能正常使用。
href (Hypertext Reference)指定网络资源的位置,从而在当前元素或者当前文档和由当前属性定义的需要的锚点或资源之间定义一个链接或者关系。(目的不是为了引用资源,而是为了建立联系,让当前标签能够链接到目标地址。)
src source(缩写),指向外部资源的位置,指向的内容将会应用到文档中当前标签所在位置。
1、请求资源类型不同:href 指向网络资源所在位置,建立和当前元素(锚点)或当前文档(链接)之间的联系。在请求 src 资源时会将其指向的资源下载并应用到文档中,比如 JavaScript 脚本,img 图片;
2、作用结果不同:href 用于在当前文档和引用资源之间确立联系;src 用于替换当前内容; 3、浏览器解析方式不同:当浏览器解析到src ,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,图片和框架等也如此,类似于将所指向资源应用到当前内容。这也是为什么建议把 js 脚本放在底部而不是头部的原因。
1、如何让谷歌浏览器支持小字体
通过缩放的方式 transform:scale(0.8); --webkit-transform:scale(0.8);
通过加入css属性 --webkit-text-size-adjust:none;解决。2、浏览器默认的margin和padding不同。解决方案是加一个全局的*{margin:0;padding:0;} 来统一。
方案一:
给容器设置
position:relative;
给子元素设置
position:absolute;
left:0;
right:0;
top:0;
bottom:0;
margin:auto;
方案二:已知高度
给容器设置
position:relative;
给子元素设置
position:absolute;
left:50%;
top:50%;
margin-left: -元素自身一半;
margin-top: -元素自身一半;
方案三:未知高度(一个宽高未知的盒子设置水平垂直居中显示(两种方法)
给容器设置
position:relative;
给子元素设置
position:absolute;
left:50%;
top:50%;
transform:translate(-50%, -50%);
方案四:弹性布局(一个宽高未知的盒子设置水平垂直居中显示(两种方法)
给容器设置
display:flex;
justify-content:center;
align-items:center;
父元素设置 flex
子元素设置 margin:auto;
块级元素默认宽度为100%,块级元素可以设置宽高
行内元素默认宽度由内容撑开,行内元素设置宽高不生效
%有继承关系
vw只和设备的宽度有关系
作用域对象不同,padding针对于自身对象,margin针对于外部对象
浮动元素碰到包含它的边框或者浮动元素的边框停留。由于浮动元素不在文档流中,所以文档流的块框表现得就像浮动框不存在一样。浮动元素会漂浮在文档流的块框上。
什么时候需要清除浮动?浮动带来的问题
父元素的高度无法被撑开,影响与父元素同级的元素 与浮动元素同级的非浮动元素(内联元素)会跟随其后 若非第一个元素浮动,则该元素之前的元素也需要浮动,否则会影响页面显示的结构。
1)受影响的加clear:left|right|both;
2)浮动元素的父元素加高
3)浮动元素的父元素加overflow:hidden|auto;原理是给包裹浮动元素的父元素运用了BFC布局规则
4)空div法:浮动元素后面加一个div,给div加clear:both;
5)伪对象法:浮动元素的父元素上加 :after{
Content:“ ”;
display:block
clear:both
}
BFC - Block Formatting Context 块级格式化上下文, BFC是一块独立的渲染区域,可以将BFC看成是元素的一种属性,拥有了这种属性的元素就会使他的子元素与世隔绝,不会影响到外部其他元素。
特点:
1,每一个BFC区域只包括其子元素,不包括其子元素的子元素。
2,每一个BFC区域都是独立隔绝的,互不影响
怎样使一个元素变成BFC区域
1、body根元素
2、float属性不为none
3、position为absolute或fixed4、行内块显示模式,inline-block
4、 display为inline-block, table-cell, table-caption, flex, inline-flex
5、设置overflow,即hidden,auto,scroll
6、表格单元格,table-cell
7、弹性布局,flex8、overflow不为visible在布局中BFC的应用场景
解决问题
1、解决外边距的塌陷问题(垂直塌陷)
2、利用BFC解决包含塌陷
3、清除浮动:overflow:hidden,现在知道了BFC区域内的子元素任何边动都不会影响到外部元素的。所以BFC区域同样可以清除浮动带来的影响。
4、BFC可以阻止标准流元素被浮动元素覆盖
总结:BFC就是块级格式化上下文,让元素成为一个独立的空间 不受外界影响也不影响外面布局
BFC概念 也叫【块级格式化上下文】,简单来说,BFC 是一个完全独立的空间(布局环境),让空间里的子元素不会影响到外面的布局。
BFC是CSS布局的一个概念,是一个环境,里面的元素不会影响外面的元素。
BFC的布局规则
内部的Box会在垂直方向,一个接一个地放置。
Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠。
每个盒子(块盒与行盒)的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
BFC的区域不会与float box重叠。
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
计算BFC的高度时,浮动元素也参与计算
如何创建BFC
1、float的值不是none。
2、position的值不是static或者relative。
3、display的值是inline-block、table-cell、flex、table-caption或者inline-flex
4、overflow的值不是visible
BFC作用 (解决了什么问题)
阻止margin重叠 可以包含浮动元素 —— 清除内部浮动 自适应两栏布局 可以阻止元素被浮动元素覆盖
块格式化上下文, 特性:
使 BFC 内部浮动元素不会到处乱跑;
和浮动元素产生边界。
!important > 行内样式(比重1000)> ID 选择器(比重100) > 类选择器(比重10) > 标签(比重1) > 通配符 > 继承 > 浏览器默认属性
行内样式>ID选择器>类选择器>元素选择器>全局选择器
10000> 1000> 100> 10> 1
行内>内嵌>外链(离元素节点越近权限越高)
1)基础选择器
全局选择器 *
元素选择器 div,a
类选择器 .
ID选择器 #
2)关系选择器
后代选择器 空格
子代选择器 >
相邻兄弟选择器 + (范围:相邻后面兄弟)
通用兄弟选择器 ~ (范围:后面所有的兄弟)
3)伪类选择器
:link 点击之前
:visited 点击之后
:hover 鼠标悬停
:active 鼠标按下
:first-child 第一个子元素
:last-child 最后一个子元素
:nth-child () 第几个子元素
:only-child 唯一一个子元素
:empty 空的子元素
:not()
4)伪对象选择器
::before{
Content" ";
} 在元素之前插入内容
::after{
Content" ";
} 在元素之后插入内容
5)属性选择器
元素[属性=属性值]
作用:圣杯布局和双飞翼布局解决的问题是相同的,都是让三列浮动,然后通过负外边距形成三列布局。就是
两边定宽,中间自适应的三栏布局
,中间栏要放在文档流前面以优先渲染。两种布局方式的不同之处:
圣杯布局:利用父容器左、右内边距+两个列的相对定位;
双飞翼布局:把主列嵌套在一个新的父级块中并利用主列的左、右外边距进行布局调整。
圣杯布局:
双飞翼布局
(1)css浮动
第一个float:left; 第二个float:reght; 第三个设置margin-left和margin-right
(2)绝对定位法
第一个定位到left; 第二个定位到rigth; 第三个设置margin-left和margin-right
(3)flex布局
.left{
width:200px;或者flex:0 0 200px;
}
.right{
width:200px;或者flex:0 0 200px;
}
.center{
flex:1;
}
两者的区别在于content不同
w3c的盒模型方式被称为“content-box”(标准盒模型)的范围包括margin、border、padding、content,并且content不包含其他部分;
IE的被称为“border-box”(怪异盒模型),它的content包含border、padding,使用box-sizing:border-box;就是为了在设置有padding值和border值的时候不把宽度撑开。
1)组成部分: content+padding+border+margin
2)标准盒模型的width和heigth决定content的宽和高
计算盒子宽:width(content)+padding+border
计算盒子高:heigth(content)+padding+border
样式设置:box-sizing:content-box;
怪异盒模型的width和height等于content+padding+border的宽和高
计算盒子宽:width(content+padding+border)
计算盒子高:heigth(content+padding+border)
样式设置:box-sizing;border-box
3)content 内容区域{
块级元素默认宽度为100%、块级元素可以设置宽高
行内元素默认宽度由内容撑开、行内元素设置宽高不生效
}
4)padding 内边距:设置内容与边框的距离
5)border 边框
6)margin 外边距:设置元素之间的距离
display:none 隐藏对应的元素,在文档布局中不再给它分配空间,它各边的元素会合拢,就当他从来不存在。
visibility:hidden 隐藏对应的元素,但是在文档布局中仍保留原来的空间。
什么是flex布局?
fle是flexible box的缩写,就是弹性布局。
任何一个元素(块元素、行内块元素、行内元素),都可以设置为弹性盒子属性。
语法:
块元素:display:flex;
行内元素:display:inline-flex;
1)display:flex; 开启弹性盒子模型,子元素默认水平排列
2)flex-direction:; 设置项目的排列方向{
row:默认值,子元素水平排列
column:子元素垂直排列
}
3)justify-content:;设置项目主轴对齐方式{
flex-start:弹性盒开始
flex-end : 弹性盒结束
center:居中
space-around:在子元素四周分配父元素剩余的距离
space-between:在子元素之间平均分配父元素剩余的距离
}
4)align-items:;设置项目侧轴对齐方式{
flex-start:弹性盒的开始
flex-end:弹性盒的结束
center:居中
}
5)flex-grow:;设置子元素分配父元素剩余的距离
px 像素
pt ios单位 通常 2倍屏(iphone 5,6,7,8) 1pt = 2px 3倍屏1pt = 3px(iphonex,iphone6 plus)
em 一个字符宽
rem 根节点一个字符宽
rpx 是小程序uni-app的宽 750= 一阁屏幕
vh 100vh = 1个屏幕的高
vw 100vw = 1个屏幕的宽
rem是全部的长度都相对于根元素元素。通常做法是给html元素设置一个字体大小,然后其他元素的长度单位就为rem。
em是相对于父元素字体大小,元素的width/height/padding/margin用em的话是相对于该元素的font-size vw/vh 全称是 Viewport Width 和 Viewport Height,视窗的宽度和高度,相当于 屏幕宽度和高度的 1%,不过,处理宽度的时候%单位更合适,处理高度的 话 vh 单位更好。
px像素(Pixel)相对长度单位,像素px是相对于显示器屏幕分辨率而言的。 一般电脑的分辨率有{1920 1024}等不同的分辨率 1920 1024 前者是屏幕宽度总共有1920个像素,后者则是高度为1024个像素
共同点:
1.改变行内元素的呈现方式,display 被置为 block;
2.让元素脱离普通流,不占据空间;
3.默认会覆盖到非定位元素上
不同点:
absolute 的”根元素“是可以设置的,
而 fixed 的”根元素“固定为浏览器窗口,当你滚动网页,fixed 元素与浏览器窗口之间的距离是不变的。
relative 相对定位,正常文档流,相对于自身的位置
absolute 绝对定位,脱离文档流,相对于开启了position非static最近的父辈元素
fixed 固定定位,脱离文档流,相对于浏览器可视窗口(不随滚动条滚动)
行内 :文字一行,高等于行高
行内块:一行,高等于行高,veticle-aligin:middle
块: flex 弹性布局 aligin-items:center; display:table-cell
定位的方式
内联首屏关键css
异步加载css
资源压缩
合理使用选择器
减少使用昂贵的属性
不要使用@import
css sprites 雪碧图是一项图片整合技术,把许多小的背景图片整合到一张图片上
原理:将一个页面涉及到的所有图片都包含到一张大图中去,然后利用 CSS 的 background-image,background- repeat,background-position 的组合进行背景定位。
优点:
1)利用 CSS Sprites 减少了页面的http请求
2)减少图片的字节数
3)减少命名的困扰
缺点:
1)需要通过background-position精确定位
2)整合图片比较麻烦
1)static 静态定位 默认值
2)Relative 相对定位,相对于自己原位置定位,定位后原位置保留,配合left、right、top、bottom移动
3)Absolute 绝对定位,相对于已经定位的父元素定位,如果父元素没有定位,逐级往上找,最后相对于body定位,定位后的原位置不保留,配合left、right、top、bottom移动
4)Fixed 固定定位,相对于浏览器窗口定位,定位后原位置不保留,配合left、right、top、bottom移动
opacity 会继承父元素的 opacity 属性,而 RGBA 设置的元素的后代元素不会继承不透明属性。
考查的是css3的transform
height: 1px;
transform: scale(0.5);
这属于简单的css考查,平时在用组件库的同时,也别忘了原生的css
.a {
width: 0;
height: 0;
border-width: 100px;
border-style: solid;
border-color: transparent #0099CC transparent transparent;
transform: rotate(90deg); /*顺时针旋转90°*/
}
1、利用了边框,块级元素在默认没有宽和高的情况下,设置四个边框,会以三角的形式呈现出来;
2、由于块级元素默认情况下是独占一行的,即使不设置宽度的情况下,默认也会跟随容器的宽度,所以需要给width:0;
3、transparent 属性表示的是透明,无论背景颜色是什么样,它都不会显示
宽高为0 三边透明,一边显示
.san{
width:0;
hegiht:0;
display:block;
border:10px solid transparent;"
border-left-color:red;
}
本质区别:
1)link是html标记提供的一种方式,import是css提供的一种方式 加载顺序
2)link的方式可以让结构和样式同时加载,import是先加载结构后加载样式 兼容问题
3)link是 XHTML 标签,无兼容问题,@import 是在 CSS2.1 提出的,低版本的浏览器不支持。
4)控制DOM区别:link支持使用 Javascript 控制 DOM 去改变样式,而import不能被控制
1、获取屏幕的高度和宽度(屏幕分辨率): window.screen.height/width
2、获取屏幕工作区域的高度和宽度(去掉状态栏): window.screen.availHeight/availWidth 3、网页全文的高度和宽度: document.body.scrollHeight/Width
4、滚动条卷上去的高度和向右卷的宽度: document.body.scrollTop/scrollLeft
5、网页可见区域的高度和宽度(不加边线): document.body.clientHeight/clientWidth 网页可见
6、区域的高度和宽度(加边线): document.body.offsetHeight/offsetWidth
1、选择器的拓展,最常用的css3选择器就是:root 选择器,对所有元素都生效,还有:first-child 选择器、:last-child 选择器、:nth-child(n) 选择器,这些比较常用,不常用的有:子代选择器就是一个 > ,比如div>span就是div标签下的span标签被选中、还有兄弟选择器,div+span选中的是同级下的往后选择靠近div的span标签。
2、可变更的盒模型,box-sizing属性,如果选择border-box的话元素的总高度和宽度就包含padding和margin
3、多列布局方式,flex布局
4、css的动画 transition,过渡 transform,变换 animation,动画
display:none; 隐藏,理解为消失,没有位置。
visibility:hidden; 占位隐藏,元素消失,但位置还在。理解为隐身,且元素的功能不存在。
opacity:0; 隐藏,占位置的,实际上就是透明为0,让你眼睛看不见它了,但元素的功能存在。
溢出隐藏方式: overflow:hidden;
单冒号(:) CSS3 伪类,双冒号(::) CSS3 伪元素。
::before 就是以一个子元素的存在,定义在元素主体内容之前的一个伪元素。并不存在于 dom 之中,只存在在页面之中。
:before 和 :after 这两个伪元素,是在 CSS2.1 里新出现的。起初,伪元素的前缀使用的是单冒号语法,但随着 Web 的进化,在 CSS3 的规范里,伪元素的语法被修改成使用双冒号,成为::before ::after
第一种真正的品字: 1.三块高宽是确定的; 2.上面那块用 margin: 0 auto;居中; 3.下面两块用 float 或者 inline-block 不换行; 4.用 margin 调整位置使他们居中。
第二种全屏的品字布局: 上面的 div 设置成 100%,下面的 div 分别宽 50%,然后使用 float 或者 inline 使其不换行。
因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对 CSS 初始化往往会出现浏览器之间的页面显示差异。
css 性能好,css 代码逻辑简单
js 动画控制好,js 兼容性好,js 可实现的动画多,js 可以添加事件
文字 :text-shadow:5px 5px 5px #FF0000;(水平阴影,垂直阴影,模糊距离,阴影颜色)
盒子 : box-shadow
canvas 标签的 width 和 height 是画布实际宽度和高度,绘制的图形都是在这个上面。
style 的 width 和 height 是 canvas 在浏览器中被渲染的高度和宽度。如果 canvas 的 width 和 height 没指定或值不正确,就被设置成默认值。
基础数据类型String、Number、Boolean、Undefined、Null
引用数据类型: Object、Array、Function、Date等
Symbol、BigInt是ES6之后新增的 属于基本数据类型 Symbol 指的是独一无二的值
BigInt 是一种数字类型的数据,它可以表示任意精度格式的整数
首先 Undefined 和 Null 都是基本数据类型,这两个基本数据类型分别都只有一个值,就是 undefined 和 null。 undefined 代表的含义是 未定义,一般变量声明了但还没有定义的时候会返回 undefined
null 代表的含义是 空对象。null主要用于赋值给一些可能会返回对象的变量,作为初始化。
1、变量被声明了,但没有赋值时,就等于undefined。
2、调用函数时,应该提供的参数没有提供,该参数等于undefined。
3、对象没有赋值的属性,该属性的值为undefined。
4、函数没有返回值时,默认返回undefined。
js变量存储有栈存储和堆存储,基本数据类型的变量存储在栈中,引⽤数据类型的变量存储在堆中,引⽤类型数据的地址也存在栈中
当访问基础类型变量时,直接从栈中取值。当访问引⽤类型变量时,先从栈中读取地址,在根据地址到堆中取出数据
栈:先进后出,自动分配释放 堆:先进先出,手动释放,容易内存泄漏
instanceof:返回值为布尔值; 用于判断一个变量是否属于某个对象的实例。
typeof:返回值是为字符串, 用来说明变量的数据类型。 一般只能返回如下几个结果: number, boolean, string, function, object, undefined。
注意:
1、null 和 undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断。
2、函数的 constructor 是不稳定的,这个主要体现在自定义对象上,当开发者重写 prototype 后,原有的 constructor 引用会丢失,constructor 会默认为 Object6、
const 定义常量, 不可以重复赋值 块级作用域 不存在变量提升
var 定义变量,可以重复声明 var 全局作用域或函数作用域 有变量提升
let 定义变量,不可以重复声明 , 块级作用域 不存在变量提升
超过16位整数就无法精确地表示了 超过这个最大值,所有的奇数都会+1或者-1变成偶数,无法准确赋值
...扩展函数、箭头函数、promise、async/await、let和const、set集合、导入improt 导出export default、smybol新的基本类型、解构赋值
原理:减少对DOM 修改带来的的回流操作。
其实这样就可以了,我们在循环的最后添加元素是添加到文档碎片当中去的,然后才一次性的从文档碎片中把元素添加到页面中
(1) 意外的全局变量:由于使用未声明的变量,而意外的创建了一个全局变量,而使这个变量一直留在内存中无法被回收
(2) 被遗忘的计时器或回调函数:设置了 setInterval 定时器,而忘记取消它,如果循环函数有对外部变量的引用的话,那么这个变量会被一直留在内存中,而无法被回收。
(3) 脱离 DOM 的引用:获取一个 DOM 元素的引用,而后面这个元素被删除,由于一直保留了对这个元素的引用,所以它也无法被回收。
(4) 闭包:不合理的使用闭包,从而导致某些变量一直被留在内存当中。
(5)事件监听: 没有正确销毁 (低版本浏览器可能出现)
可用 chrome 中的 timeline 进行内存标记,可视化查看内存的变化情况,找出异常点。
1、如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式,而不是对象的形式
2、如果obj里有RegExp(正则表达式的缩写)、Error对象,则序列化的结果将只得到空对象; 3、如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失;
4、如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null
5、JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor; 6、如果对象中存在循环引用的情况也无法正确实现深拷贝;
shift() 删除数组的第一个元素,返回删除的值。
unshift(3,4) 把一个或多个参数加载数组的前面,返回数组的长度
pop() 删除数组的最后一个元素,返回删除的值。
push(3) 将参数加载到数组的最后,返回数组的长度
slice(start,end) 返回从原数组中指定开始下标到结束下标之间的项组成的新数组
splice(start,deleteCount,val1,val2,…):从start位置开始删除deleteCount项,并从该位置起插入val1,val2,…,如果deleteCount为0,就表示从start位置开始添加元素。
reverse() 将数组反序 sort(orderfunction):按指定的参数对数组进行排序
join() 数组的每个元素以指定的字符连接 形成新字符串返回;
concat([6,7,8],9,10) 把两个数组拼接起来。
//通过call调用数组的slice方法来实现转换
Array.prototype.slice.call(arrayLike)
//通过call调用数组的splice方法来实现转换
Array.prototype.splice.call(arrayLike,0)
//通过apply调用数组的concat方法来实现转换
Array.prototype.concat.apply([],arrayLike)
//通过Array.from方法来实现转换
Array.from(arrayLike)
把接收多参的函数转化成可以逐个调用单个参数并返回接收剩下参数的函数
函数柯里化就是我们给一个函数传入一部分参数,此时就会返回一个函数来接收剩余的参数。
柯里化,用一句话解释就是,把一个多参数的函数转化为单参数函数的方法。
至于用法嘛,在实际开发中没有使用过,不过学习vue源码时知道,vue在将DOM转化为抽象语法树时就使用了函数柯里化来优化性能
函数柯里化的好处: 我们希望处理函数时,希望函数功能尽可能单一。如下面代码所示,我们希望第一个参数+2
,第二个参数*2
,第三个参数** 2
,最后再相加,此时我们可以使用函数的柯里化。
Loader:直译为“加载器”。Webpack将一切文件视为模块,但是webpack原生是只能解析js文件,如果想将其他文件也打包的话,就会用到‘loader’。所以Loader的作用是让webpack拥有了加载和解析非JavaScript文件的能力。
Plugin:直译为“插件”。Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。在Webpack运行的生命周期中会传播出许多事件,Plugin可以 监听这些事件,在合适的时机通过Webpack提供的API改变输出结果。
1、for…in遍历的是对象的键,for…of遍历获取的是对象的值;
2、for…in会遍历对象的整个原型链, 性能非常差不推荐使用,而for…of只遍历当前对象不会遍历原型链;
3、对于数组的遍历,for…in会返回数组中所有可枚举的属性(包括原型链上可枚举的属性),for…of只返回数组的下标对应的属性值;
总结:
for…in循环主要是为了遍历对象而生,不适用遍历数组,慎用; for…of循环可以用来遍历数组、类数组、对象、字符串、Set、Map以及Generator对象
(1) Map是键值对,Set是值的合集,当然键和值可以是任何的值;
(2) Map可以通过get方法获取,而set不能因为它只有值;
(3) 都能通过迭代器进行for…of遍历;
(4) Set的值是唯一的可以做数组去重,而Map由于没有格式限制,可以做数据存储;
forEach():
遍历数组,调用数组的每个元素,利用回调函数对数组进行操作,本质上等同于 for 循环。 forEach 会改变原数组。
没有返回值,不支持continue 和 break
return只能跳出当前循环
map()
遍历数组,调用数组的每个元素,利用回调函数对数组进行操作,与 forEach 类似。 不过map是返回一个新数组,原数组不变,新数组的索引结构和原数组一致 map需要return返回值
filter()
遍历数组,返回一个新数组(原数组的子集),回调函数用于逻辑判断,
回调函数为 true 则将当前元素添加到新数组中,false 则跳过,不会改变原数组
forEach()方法会针对每一个元素执行提供的函数,对数据的操作会改变原数组,该方法没有返回值;
map()方法不会改变原数组的值,返回一个新数组,新数组中的值为原数组调用函数处理之后的值;
注意:
forEach() 会改变原数组的方法 参数:item数组中的当前项,index当前项的索引,array原始数组; 数组中有几项,那么传递进去的匿名回调函数就需要执行几次
使用场景:当我们对数组的元素进行处理时(例如:增加元素,元素值改变),可以使用这个函数
注意:
map() 方法不会改变原数组的值
item数组中的当前项,index当前项的索引,array原始数组
map的回调函数中支持return返回值,return的是啥,相当于把数组中的这一项变为啥(并不影响原来的数组,只是相当于把原数组克隆了一份,把克隆这一份的数组中的对应项改变了 );
map会改变原数组的方法,map的执行速度更快,比forEach的执行速度快了70%;
使用场景:
map适用于你要改变数据值的时候,不仅在于它更快,而且返回一个新的数组,这样可以提高复用性(map(),filter(),reduce())等组合使用。
总结:
能用forEach()做到的,map()同样可以。反之亦成立
map()会分配内存空间存储新数组并返回,forEach()不会返回数组
forEach()允许callback更改原始数组的元素。而map()返回新的数组
(1) DOM操作:例如:document.getElementById 就是dom操作
DOM事件模型和事件流:
DOM事件模型分为捕获和冒泡。
一个事件发生后,会在子元素和父元素之间传播(propagation)。
这种传播分成三个阶段。
(1)捕获阶段:事件从window对象自上而下向目标节点传播;
(2)目标阶段:真正的目标节点正在处理事件;
(3)冒泡阶段:事件从目标节点自下而上向window对象传播。
阻止事件传播(冒泡): e.stopPropagation()
阻止默认行为: e.preventDefault()
(2) BOM操作
BOM(浏览器对象模型)是浏览器本身的一些信息的设置和获取,例如获取浏览器的宽度、高度,设置让浏览器跳转到哪个地址。
例如:
window.screen对象:包含有关用户屏幕的信息
window.location对象:用于获得当前页面的地址(URL),并把浏览器重定向到新的页面 window.history对象:浏览历史的前进后退等
window.navigator对象:常用来获取浏览器信息、是否移动端访问等等
scrolleft offsetLeft
scrollLeft 滚动条滚动的距离
offsetLeft 当前元素与父元素(position非static)距离
clientWidth offsetWidth, scrollWidth区别
clientWidth内容+padding宽
offsetWith 内容+padding+边框宽
scrollwidth 内容+滚动区域的宽
获取浏览器宽高
window.innerWidth 、wondow.innerHeight
document.documentElement.clientWidth
HTTP协议从未规定GET/POST的请求长度限制是多少。对get请求参数的限制是来源于浏览器或web服务器限制了url的长度。
(1) HTTP协议未规定GET和POST的长度限制
(2) GET的最大长度显示是因为浏览器和web服务器限制了URL的长度
(3) 不同的浏览器和WEB服务器,限制的最大长度不一样
(4) 要支持IE,则最大长度为2083byte,若只支持Chrome,则最大长度为8182byte
get请求类似于查找的过程,用户获取数据,可以不用每次都与数据库连接,所以可以使用缓存。因此get请求适用于请求缓存。
post不同,post一般做的是修改和删除的工作,所以必须与数据库交互,所以不能使用缓存。
本质上是优化高频率执行代码的一种手段
节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时
函数防抖:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。就像英雄联盟或王者荣耀的回城,要读条,一旦被打断就要重新读条,要完整读完条才能回去。
函数节流:每隔一段时间,只执行一次函数。
防抖应用场景
搜索框搜索输入。只需用户最后一次输入完,再发送请求 手机号、邮箱验证输入检测 onchange / oninput事件 窗口大小计算。只需窗口调整完成后,计算窗口大小。防止重复渲染。
节流应用场景
懒加载、滚动加载、加载更多或监听滚动条位置; 百度搜索框,搜索联想功能; 防止高频点击提交,防止表单重复提交;
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大,它是一个 ECMAScript 6 提供的类,目的是更加优雅地书写复杂的异步任务。
其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。解决回调函数层级过多形成的回调地狱问题
Promise对象有以下两个特点:
1、对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
2、一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
Promise.all()
方法用于将多个 Promise 实例,包装成一个新的 Promise 实例
。
Promise.all()
方法接受一个数组
作为参数,p1、p2、p3都是 Promise 实例
,如果不是,就会调用Promise.reslove() [该方法可自行了解]
自动将参数转为 Promise 实例,再进一步处理
实现思路:通过Promise.all()
方法,等多个接口全部接收到数据后,再统一进行处理,然后渲染页面。
定义api请求接口、自定义jsonp用到、 弹框插件 等待用户确定则resolve、 封装actions 用sync装饰 await实现异步 等待,网络,等待用户确定的,异步操作都会用到promise
ajax核心是通过XMLHttpRequest(xhr) 与服务器异步交换数据,实现前端刷新更新视图
var xhr = new XMLHttpRequest(); // 创建一个xhr对象
xhr.open("get","url地址") //打开连接get方式
xhr.send(data) // 发送数据到服务器
xhr.onreadystatechange = function(){ // 监听xhr的变化
if(xhr.reaystate===4){ //状态4成功
if(xhr.status===200){ //响应码200
// xhr.responseText 获取的数据
}
}
}
JavaScript是单线程语言,在执行任务的时候,会先执行第一个任务再执行第二个任务,假如第一个任务是个耗时的任务那么第二个任务就一直阻塞不能执行,那么这个时候就需要异步来处理这个操作;
同步是按顺序执行,单线程,会阻塞代码;
异步多线程执行,非阻塞式执行代码
同步:主线程上排队执行的任务,只有前一个任务执行完毕,才能继续执行下一个任务;
异步:不进入主线程,而进入任务队列的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程;
异步方法:回调函数,Promise,订阅发布模式,事件响应,aync和awiat
最常用的异步操作就是将 回调函数作为异步回调的参数来使用,而promise是通过then来做的; new promise 的时候就会被立即执行,因而为了实现用的时候调用所以将promise写在函数里面;
冒泡流:事件由最具体的元素响应 然后组件冒泡到最不具体的元素(html)
捕获流:从最不具体的元素捕获事件
开启捕获 addEventListenter第三个参数 true
阻止事件冒泡:e.stopPropagation()
无new操作怎么实现
var vm = new Vue() //通过new关键字实现实例化 $("div")
jquery的工厂函数与原型链重新指向
function jQuery (selector){ return new JQuery.prototype.init(selector) } JQuery.fn = jQuery.prototype; JQuery.fn.init = function(selector){ return xxxx; } jQuery.fn.init.prototype = JQuery.prototype; window.$=JQuery;
js对象转jquery:用$函数包裹 $(js对象)
jquery转js:
下标获取,get方法获取
$(selector)[0]
$(selector).get(0)
页面渲染过程:
下载html -> 生成dom树 下载css -> 生成css树 css树与dom树合并为渲染树 开始渲染页面 -> 遇到js会有阻塞,
JQuery.常用方法:
显示与隐藏:show hide fadeIn fadeOut toggle slideIn slideDown
val 属性和值:css() html() attr() props()text()
类:addClass toggleClass hasClass removeClass
动画、停止动画:animation() stop()
ajax方式查找节点:$ajax,$.get $,post() .load()
查找节点:find chilren parent parents next sibings
clientX:距离可视窗口左面的距离,可视区域不包括工具栏和滚动条。
clientY:距离可视窗口顶端的距离
pageX:距离整个页面(超出可视窗口的页面)左面的距离
pageY:距离整个页面(超出可视窗口的页面)顶端的距离
offsetX:距离容器左面的距离,鼠标相对于事件源元素(srcElement)的X,Y坐标,只有IE事件有这2个属性,标准事件没有对应的属性。
offsetY:距离容器顶部的距离
event.screenX、event.screenY:鼠标相对于用户显示器屏幕左上角的X,Y坐标。
我们都知道,当一个函数被调用的时候,当前的this 指向的是被调用的这个函数(ES6 的箭头函数除外), 当一个对象或者实例下有多个方法,通过对象或者实例去调用他自己的方法时,当前的this 指向的是 当前的这个对象或者实例,如果在这个方法执行完成以后,返回 this 其实也就等于返回的是当前的对象或者实例,在返回的这个对象或者实例 的基础上再去调用这个对象或者实例下的其他方法,就可以省去重新拿当前对象或者实例的步骤,就可以再上一个方法后边继续调用其他方法。链式调用就可以形成。
链式调用就是调用完一个方法以后,不用另起一行,重新再当前this 对象上再去调用方法。
如果采用类的思想,那么它的子类就会继承类的所有方法,同时如果每次调用方法后都返回的是这个子类本身,那么就实现了链式调用。
1、职责分离,高内聚,低耦合
2、分层,结构清晰合理
3、算法性能较优
4、复用性,维护性优
1.`职责分离,高内聚,低耦合`: 举例:创建不同的js,每个js满足自己角色职责的事情 ,比如页面跳转js , 数据处理js(增删改查) , 数据验证js(效验) , 封装js(相似相同的不断复用的js封装) , 计算结果js ,上传资源 js.......
2.`分层,结构清晰合理`:举例: 首先是学会分包 ,以js 包举例, 在最外层可分为locajs 和 js , localjs 里面是每个对象的js包, 可能有user / news / report / system / honor ,还有工具包 ,如tools ,共有使用的js , 对于js包中一般放组件, 何为组件, jquery.js , bootstrap.js ,mui.js 等第三方js 内容
3.`算法性能较优`: 减少使用多内嵌for 循环和负责递归,不同数据量情况选择不同的排序方法等
4.`复用性,维护性优`: 做到不第二次写 “ 相同或者相似 ” 的 js 代码, 对于多次编写的相似或者相同的代码进行封装, 构建函数和多个传入参数,实现复用,其他js 使用只要通过函数调用即可, 方便日后维护和调优
(1) 创建了一个新对象;
(2) 将对象与构造函数的原型链连接起来;
(3) 将构造函数中的this绑定到新建的对象上;
(4) 判断返回值类型,如果是值类型,返回创建的对象;如果是引用类型,返回这个引用类型的对象;
let obj = new Object();
obj._proto_ = Person.prototype;
let result = Person.call(obj)
if(typeof (result) == "object"){
person1 = result
}else{
person1 = obj;
}
1.有对象就指向调用对象:在对象myObject上绑定方法,在方法中this就指向对象myObject。 2.没调用对象就指向全局对象:这里嵌套函数foo并没有直接绑定的对象,所以函数内的this指向全局对象global。
3、箭头函数的this指向上一层作用域的this
4、构造函数 new 函数名() this 指向 new出来对象的实例
5、对象中的this指向对象
6、事件响应函数的this指向调用者
7、setTimout setInterval 里面 this指向window
8、call,apply,bind 响应的函数 this指向第一个参数
1、 箭头函数更加简洁;
2、 箭头函数不会创建自己的this,所以它没有自己的this,它只会在自己作用域的上一层继承this,所以箭头函数中的this指向在它定义时就确认了,之后不会再改变,所以箭头函数的this值永远不会改变;
3、call()、apply()、bind()等方法不能改变箭头函数this的指向;
4、箭头函数不能作为构造函数使用,没有constructor ;
5、箭头函数没有自己的arguments,但是可以访问外围函数的 arguments对象;
6、箭头函数没有prototype(原型),原型是undefined;
7、箭头函数this指向函数的上一层作用域的this;
8、不能通过 new 关键字调用,同样也没有 new.target 值和原型;
意义:懒加载的主要目的就是作为服务器前端的优化,减少请求次数或者延迟请求数。 实现原理:先加载一部分数据,当触发某个条件时利用异步(async)加载剩余的数据,新得到的数据不会影响原有数据的显示,同时最大幅度的减少服务器端资源耗用。
实现方式:
1.第一种是纯粹的
延迟加载
,使用setTimeOut和setInterval进行加载延迟。2.第二种是
条件加载
,符合某种条件,或是出发某些事件才开始异步加载。3.第三种是
可视区加载
,仅记载用户的可视区域,这个主要监控滚动条来实现,一般会距用户看到某些图片前的一段距离时开始进行记载,这样就可保证用户下拉时正好可以看到加载完毕后的图片或是内容。
图片懒加载的原理具体实现
1、存储图片的真实路径,把图片的真实路径绑定给一个以data开头的自定义属性data-url即可,页面中的img元素,如果没有src属性,浏览器就不会发出请求去下载图片(没有请求就提高了性能)
2、初始化img的时候,src不能是真实的图片地址(会一次性发送请求),也不可以是空地址或者坏地址
3、设置img的默认src为一张1px*1px,很小很小的gif透明图片(所有的img都用这一张,只会发送一次请求),之所以需要是透明的,是需要通过background设置的背景图(一张loading.png,就是一个转圈圈的背景效果图)
4、需要一个滚动事件,判断元素是否在浏览器窗口,一旦进入视口才进行加载,当滚动加载的时候,就把这张透明的1px.gif图片替换为真正的url地址(也就是data-url里保存的值)
5、等到图片进入视口后,利用js提取data-url的真实图片地址赋值给src属性,就会去发送请求加载图片,真正实现了按需加载
方法一:滚动监听+scrollTop+offsetTop+innerHeight
1、获取可视窗口的大小
2、获取内容滚动的距离
3、如何判断图片进入了可视区域
方法二:滚动监听+getBoundingClientRect() 方法三:intersectionObserve()
图片懒加载:当用户不需要的时候先不加载图片 图片预加载:当网络有空闲先提前把可能需要的图片缓存到内存中
可以分为微任务(micro task)队列和宏任务(macro task)队列。
微任务一般比宏任务先执行,并且微任务队列只有一个,宏任务队列可能有多个。另外我们常见的点击和键盘等事件也属于宏任务。
下面我们看一下常见宏任务和常见微任务。
常见宏任务:
setTimeout() setInterval() setImmediate()
常见微任务:
promise.then()、promise.catch() new MutaionObserver() process.nextTick() 微任务和宏任务的本质区别。
宏任务特征:有明确的异步任务需要执行和回调;需要其他异步线程支持。 微任务特征:没有明确的异步任务需要执行,只有回调;不需要其他异步线程支持。
setTimeout(function () {
console.log("1");
}, 0);
async function async1() {
console.log("2");
const data = await async2();
console.log("3");
return data;
}
async function async2() {
return new Promise((resolve) => {
console.log("4");
resolve("async2的结果");
}).then((data) => {
console.log("5");
return data;
});
}
async1().then((data) => {
console.log("6");
console.log(data);
});
new Promise(function (resolve) {
console.log("7");
resolve()
}).then(function () {
console.log("8");
});
// 2 4 7 5 8 3 6 async2的结果 1
每打开一个新网页就会创建一个渲染进程,渲染进程是多线程的,
负责页面渲染的 GUI 渲染线程,
负责JavaScript的执行的 JavaScript 引擎线程,
负责浏览器事件循环的事件触发线程,注意这不归 JavaScript 引擎线程管,
负责定时器的定时触发器线程,setTimeout 中低于 4ms 的时间间隔算为4ms
负责XMLHttpRequest的异步 http 请求线程,
GUI 渲染线程与 JavaScript 引擎线程是互斥的,
单线程JavaScript是因为避免 DOM 渲染的冲突,web worker 支持多线程,但是 web worker 不能访问 window 对象,document 对象等。
优点:
1、不受到同源策略的限制。
2、它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持
缺点:
1、只支持GET请求而不支持其它类型的HTTP请求,因为script只能发送get请求
2、它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
3、jsonp在调用失败的时候不会返回各种HTTP状态码。
4、安全性问题。假如提供jsonp的服务存在页面注入的漏洞,就有可能会导致所有调用这个jsonp的网站都会存在漏洞。所以在使用jsonp的时候必须要保证使用的jsonp服务必须是安全可信的。
优点:
1.相对与jsonp更安全更方便简洁
2.功能更强大,支持所有类型的请求
缺点:
1.ie10以下不支持CORS
2.由于CORS是W3C中一项较“新”的方案,以至于各大网页解析引擎还没有对其进行严格规格的实现,所以不同引擎下可能会有一些不一致。
jsonp
CORS 响应头允许(后端允许)
proxy
利用script标签自身的跨域能力,动态创建script标签,让src属性访问网上的资源,后台资源返回的数据一般是函数,前端用函数接收数据。
同源策略是客户端脚本(尤其是JavaScript)的重要的安全度量标准。它最早出自Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载。
所谓同源指的是:协议、域名、端口相同,同源策略是一种安全协议,指一段脚本只能读取来自同一来源的窗口和文档的属性。
一、http缓存
二、websql
cookie
localstorage
sessionstorage
flash缓存
渐进增强(Progressive Enhancement):一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。
优雅降级(Graceful Degradation):一开始就构建站点的完整功能,然后针对浏览器测试和修复。比如一开始使用 CSS3 的特性构建了一个应用,然后逐步针对各大浏览器进行 hack 使其可以在低版本浏览器上正常浏览。
其实渐进增强和优雅降级并非什么新概念,只是旧的概念换了一个新的说法。在传统软件开发中,经常会提到向上兼容和向下兼容的概念。渐进增强相当于向上兼容,而优雅降级相当于向下兼容
http是HTTP协议运行在TCP之上。所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。
https是HTTP运行在SSL/TLS之上,SSL/TLS运行在TCP之上。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。此外客户端可以验证服务器端的身份,如果配置了客户端验证,服务器方也可以验证客户端的身份
1、原型链继:将父类的实例作为子类的原型
2、构造继承:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类
3、实例继承:为父类实例添加新特性,作为子类实例返回 拷贝继承
4、组合继承:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现 函数复用
5、寄生组合继承:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实 例方法/属性,避免的组合继承的缺点
回调函数
使用回调函数的方式有一个缺点是,多个回调函数嵌套的时候会造成回调函数地狱,上下两层的回调函数间的代码耦合度太高,不利于代码的可维护。
Promise
使用 Promise 的方式可以将嵌套的回调函数作为链式调用。但是使用这种方法,有时会造成多个 then 的链式调用,可能会造成代码的语义不够明确。
async 函数
async 函数是 generator 和 promise 实现的一个自动执行的语法糖,它内部自带执行器,当函数内部执行到一个 await 语句的时候,如果语句返回一个 promise 对象,那么函数将会等待 promise 对象的状态变为 resolve 后再继续向下执行。因此可以将异步逻辑,转化为同步的顺序来书写,并且这个函数可以自动执行。
let const
字符串、数组、对象的方法扩展
symbol、set、map新的数据类型和数据结构
proxy
异步解决方案:promise,async、await
class类
module模块
一、加载(页面)
1、减少http请求(精灵图,文件的合并)
2、减小文件大小(资源压缩,图片、视频、代码压缩)
3、CDN(第三方库)
4、SSR服务端渲染、预渲染 5、懒加载 6、分包
二、性能(动画、操作):减少dom操作,避免回流,文档碎片
三、内存占用:内存占用过大,浏览器崩掉
四、电量消耗:游戏方面
1、使用es6 set方法
[...new Set(arr)]
let arr = [1,2,3,4,3,2,3,4,6,7,6]; let unique =(arr)=>[...newSet(arr); unique(arr);//[1,2,3,4,6,7]
2、利用新数组indexOf查找indexOf()方法可返回某个指定的元素在数组中首次出现的位置。如果没有就返回-1。
3、for双重循环通过判断第二层循环,去重的数组中是否含有该元素,如果有就退出第二层循环,如果没有j==result.length就相等,然后把对应的元素添加到最后的数组里面。
浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址
深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存,使用深拷贝的情况下,释放内存的时候不会因为出现浅拷贝时释放同一个内存的错误。
浅复制:仅仅指向被复制的内存地址,如果原地址发生改变,那么浅复制出来的对象也会相应的改变。
深复制:在计算机中开辟一块新的内存地址用于存放复制的对象。
转字符串:JSON.parse(JSON.stringify(list));将js对象转化为json数据再转回来就能得到与深拷贝的数组 深拷贝 =>80%
递归:遍历原数组赋值到新建立的数组。
Object.assign(A,B)
for in 遍历拷贝
{...A} 对象扩展
数组与对象赋值是浅拷贝;一维的数组和对象可以看做是深拷贝;二维的是浅拷贝;方法不能拷贝;
【{},[]】
浅拷贝: 以赋值的形式拷贝引用对象,仍指向同一个地址,修改时原对象也会受到影响 Object.assign 展开运算符 ...
深拷贝: 完全拷贝一个新对象,修改时原对象不再受到任何影响
JSON.parse(JSON.stringify(obj)): 性能最快
具有循环引用的对象时,报错
当值为函数、undefined、或symbol时,无法拷贝
递归进行逐一赋值
lodash工具库:cloneDeep
深拷贝:
arr=[100, [{a : 'hello'}, {b : "world"}], { c: "123456789" }];
//判断修改的是不是'object'或者null,如果不是 object 或者 null 那么直接返回
function deepClone(obj = {}) {
if (typeof obj !== 'object' || obj == null) {
return obj;
}
let result;
//判断上面下来的obj是不是数组 用instanceof来检测 因为是数组应用类型
obj instanceof Array?result=[]:result={}
for (var item in obj) {
//查找一个对象是否有某个属性
if (obj.hasOwnProperty(item)) {
// 递归调用
result[item] = deepClone(obj[item])
}
}
return result;
}
let arr1=deepClone(arr);
arr1[1][0].a='vue'
arr1[0]=99
console.log('原数组',arr)
console.log('新数组',arr1)
function add(num1, num2) {
const num = num1 + num2;
if(num2 === 100) {
return num;
} else {
return add(num, num2 + 1)
}
}
var sum = add(1, 2);
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 它是基于JavaScript的一个子集。数据格式简单, 易于读写, 占用带宽小 {‘age’:‘12’, ‘name’:‘back’}
this的指向主要有下面几种:
1、this出现在全局函数中,永远指向window
2、this出现在严格模式中 永远不会指向window
3、当某个函数为对象的一个属性时,在这个函数内部this指向这个对象
4、this出现在构造函数中,指向构造函数实例
5、当一个元素被绑定事件处理函数时,this指向被点击的这个元素
6、this出现在箭头函数中时,this和父级作用域的this指向相同
不需要function关键字来创建函数
省略return
改变this指向
==,当两个运算符相等时,它返回true,即不检查数据类型
===,当两个运算符和数据类型都相等的情况下,才返回true
async 是一个通过异步执行并隐式返回 Promise 作为结果的函数。是Generator函数的语法糖,并对Generator函数进行了改进。
async/await函数是异步代码的新方式 async/await是基于promise实现的 async/await使异步代码更像同步代码 await 只能在async函数中使用,不能再普通函数中使用,要成对出现 默认返回一个promise实例,不能被改变 await下面的代码是异步,后面的代码是同步的
Promise是异步编程的一种解决方案,它是一个对象,可以获取异步操作的消息,避免了地狱回调 Promise有三种状态: pending(等待态),fulfilled(成功态),rejected(失败态) ;状态一旦改变,就不会再变。
创造promise实例后,它会立即执行。 Promise拥有一个then方法,用以处理resolved或rejected状态下的值 then方法接收两个函数作为参数,第一个参数是Promise执行成功时的回调,第二个参数是Promise执行失败时的回调。 then方法返回一个新的Promise对象,因此可以通过链式调用then方法
function xxx(onResolved) {
// 这里叫做promise2
return new Promise((resolve,inject) => {
//计时器模拟请求
setTimeout(()=>{
if(){
resolve(res)
} else{
inject(err)
}
})
});
};
xx.then(fun,fun)
闭包的概念:
闭包就是指被定义在其他函数内部的函数,闭包函数可以享用它所有的外部函数中定义的所有变量。
闭包就是函数嵌套函数,函数作为参数被传入,作为返回值被返回。
定义在一个函数内部的函数(方法里面返回方法)。
闭包:是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部。
闭包的特性
函数内再嵌套函数
内部函数可以引用外层的参数和变量
参数和变量不会被垃圾回收机制回收
闭包的优缺点
优点:延长变量生命周期、私有化变量
缺点:过多的闭包可能会导致内存泄漏
闭包的应用场景
ajax请求的成功回调
事件绑定的回调方法
setTimeout的延时回调
函数内部返回另一个匿名函数
函数节流、防抖 封装模块(保证数据的私有性)
arr instanceof Array
arr.constructor == Array
Object.prototype.toString.call(arr) == ‘[Object Array]’
方法一:利用对象记录每个字符出现的次数
1、定义一个空的对象 -> 利用对象记录每个字符出现的此数
2、循环这串字符串,利用charAt的方法,判断 若属性i存在 属性值+1 否则-1
3、定义一个变量为 -> 出现的次数
4、定义一个变量为 -> 最多次数的字符名 5、遍历对象,对比 取大值 和 属性名key
方法二:reduce
1、利用split方法 转成数组
2、Array.reduce方法 参数一:初始值 参数二:当前值
3、如果对象中存在当前值(属性)则+1 否则-1
4、初始值为空对象 5、最后同上
1、通过设置自定义属性方式, 给每一条 li 设置自定义属性 index 为 i, 点击时就可以获取 this 的自定义属性 index。
2、通过 let (const)的块级作用域特点,获取到的是每个独立的 i。让声明的i每循环一次都能成为一个独立的块,这样每次点击的循环事件都互不影响。
3、通过 bind 改变 this 指向为每一条 li,传入第二个参数为 i,在点击时就可以获取到 i。 4、通过闭包自执行函数方式 ,传入参数 i,在函数内容返回一个函数体赋值给每一条点击的 li。
5、将li对象通过Array.from()方法转化成数组,在通过forEach()去遍历里面的每一项这样每次点击都可以找到每一项对应的下标index。
// 斐波那契数列:指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、…… 。这个数列从第3项开始,每一项都等于前两项之和。
function fn(i){
if(i == 2 || i==1){
return 1;
}else{
return fn(i-1)+fn(i-2);
}
};
for(var i=1 ;i<20; i++){
console.log(fn(i))
};
1、数组concat()方法 传递给content()方法的参数序列中如果包含数组,则会将数组的每一项添加到结果数组中,这就使数组的方法具有展开二维数组的能力。
需要注意的是,如果数组的元素还是数组则不会在展开了,也就是content()方法只能降低一维。
2、创建一个空的数组,搭配for循环方法实现
作用:是扩展函数的作用域范围
格式:函数.call(对象,参数1,参数2,参数3...);
格式: 函数.apply(对象,[参数1,参数2,参数3...])
注意:call和apply是所有函数的方法(JS中函数本身也是对象类型,也有自己的方法),在借用方法时,该方法会自动执行,不需要在手动调用 区别:两个函数区别就是传参不同
三者区别
三者都可以改变函数的this对象指向 三者第一个参数都是this要指向的对象,如果没有这个参数或参数为undefined或null,则默认指向全局window
三者都可以传参 call是参数列表,apply是数组,call和apply是一次性传入参数, bind是参数列表,但可以分为多次传入参数 bind是返回绑定this之后的函数,apply、call 则是立即执行
应用场景
call 经常做继承。 apply 经常跟数组有关系,比如借助于数学对象实现数组最大值最小值。 bind 不调用函数,但是还想改变this指向,比如改变定时器内部的this指向。
1、如果页面中同一个元素被添加了多个Load事件,那么后面添加的事件会覆盖前面添加的事件,而jQuery中的ready事件可以同时存在
2、ready事件的执行时间比load事件早,因为ready事件是在Dom树渲染完毕后执行,而load事件是在页面中的元素加载完毕后执行
1、箭头函数比普通函数更加简洁
2、箭头函数没有自己的this
3、箭头函数继承来的this指向永远不会改变
4、箭头函数不能作为构造函数使用
5、箭头函数没有自己的arguments
6、箭头函数没有prototype
7、call()、apply()、bind()等方法不能改变箭头函数中this的指向
声明一个函数,并马上调用这个匿名函数就叫做立即执行函数; 也可以说立即执行函数是一种语法,让你的函数在定义后立即执行;
立即执行函数的作用:
1.不必为函数命名,避免了污染全局变量。
2.立即执行函数内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量。
3.封装变量。
1、避免变量被污染
2、创建私有环境
3、保存变量,常驻内存
4、延长变量的生命周期
class使用extends关键字实现继承
通过js原型链实现继承
原型:
所有的构造方法中都会有一个属性__prototype属性,这个属性会指向一个对象prototype原型, 这个对象被称为原型对象,简称原型。原型中存储的是该构造方法创建出来的所有实例可以共享的内容
原型链: 当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,也就是原型链的概念。原型链的尽头一般来说都是Object.prototype所以这就是我们新建的对象为什么能够使用toString()等方法的原因
原型:
一个简单的对象,用于实现对象的属性继承。 每个JavaScript对象中都包含一个proto的属性指向该对象的原型,可obj.proto进行访问。
原型链:
原型链是由原型对象组成,每个对象都有 proto 属性,(该属性指向对象的prototype原型属性)指向了创建该对象的构造函数的原型,proto 将对象连接起来组成了原型链。是一个用来实现继承和共享属性的有限的对象链。
作用:
1、原型链实现了js继承
2、原型可以给构造函数创建的实例添加共用方法
构造函数:可以通过 new来 新建一个对象 的函数
实例: 通过构造函数和new创建出来的对象,便是实例。 实例通过proto指向原型,通过constructor指向构造函数。
就是利用事件冒泡的原理,给多个元素共有的父元素上指定一个事件处理程序,就可以管理某一类型的所有事件。
由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件。这种方法叫做事件代理。
作用:动态添加的元素也可以响应事件
优点:使代码简洁;减少浏览器的内存占用;
有两种垃圾回收策略:
标记清除: 标记阶段即为所有活动对象做上标记,清除阶段则把没有标记(也就是非活动对象)销毁。
引用计数: 它把对象是否不再需要简化定义为对象:有没有其他对象引用到它。如果没有引用指向该对象(引用计数为 0),对象将被垃圾回收机制回收。
cookie 是浏览器与服务器交互的重要手段;cookie存储在浏览器端一小段数据,http请求与响应都会携带cookie;cookie可以被后端设置;也可以被前端设置
session是存储在服务器的当前用户的唯一标识符(安全),通常以cookie形式存储sessionid 告诉前端当前用户的状态
document.write 只能重绘整个页面
innerHTML 可以重绘页面的一部分
setItem(key,value) 设置数据
getItem(key) 获取key数据
removeItem(key) 移除key数据
clear()清空
其中一个方法是给localStorage方法的原型加两个方法,一个存的时候的方法,一个取的时候的方法,存的时候的方法上记录一下当前时间,取的时候的方法用当前时间减去存的时候的时间判断一下是否过期,没过期就返回,过期就给删掉
// 存的时候的方法
Storage.prototype.setExpire=(key, value, expire) =>{
let obj={
data:value,
time:Date.now(),
expire:expire
};
localStorage.setItem(key,JSON.stringify(obj));
}
// 取的时候的方法
Storage.prototype.getExpire= key =>{
let val =localStorage.getItem(key);
if(!val){
return val;
}
val =JSON.parse(val);
if(Date.now()-val.time>val.expire){
localStorage.removeItem(key);
return null;
}
return val.data;
}
1、存储大小
cookie:一般不超过4K(因为每次http请求都会携带cookie、所以cookie只适合保存很小的数据,如会话标识)
localStorage:5M或者更大
2、数据有效期
cookie:一般由服务器生成,可以设置失效时间;若没有设置时间,关闭浏览器cookie失效,若设置了时间,cookie就会存放在硬盘里,过期才失效。
localStorage:永久有效,窗口或者浏览器关闭也会一直保存,除非手动永久清除,因此用作持久数据
应用场景
cookie:判断用户是否登录过网站,以便实现下次自动登录或记住密码;保存事件信息等
localStorage:常用于长期登录(判断用户是否已登录),适合长期保存在本地的数据
Doctype 告诉浏览器你是什么模式渲染页面;
严格按浏览器最新标准;
混杂兼容渲染
无论如何完成工作是首要的,如果我预计时间来不及了,我会主动汇报,或者给出现阶段的进度,不要等到deadline,让大家都措手不及。
浏览器缓存
操作系统缓存
本地域名服务器
根域名服务器请求解析
顶级域名服务器
SYN表示建立连接,FIN表示关闭连接,ACK表示响应
三次握手的目的是建立可靠的通信信道,通讯就是数据的发送与接收。而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。
第一次握手: 客户端---->发送带有SYN标志的数据包---->服务端
客户端什么都不用确认;
服务端确认了对方发送正常,自己接收正常
第二次握手: 服务端---->发送带有SYN/ACK标志的数据包---->客户端
客户端确认了自己发送、接收正常,对方发送、接收正常;
服务端确认了对方发送正常,自己接收正常
三次握手: 客户端---->发送带有ACK标志的数据包---->服务端
客户端确认了自己发送、接收正常,对方发送、接收正常;
服务端确认了自己发送、接收正常,对方发送、接收正常
所以三次握⼿就能确认双发收发功能都正常,缺⼀不可。
第2次握手为什么要传回SYN和ACK
服务端传回客户端所发送的SYN是为了告诉客户端,我接收到的信息确实就是你所发送的信号了。
传了 SYN,为啥还要传 ACK?
双方通信无误必须是两者互相发送信息都无误。传了 SYN,证明客户端到服务端的通道没有问题,但是服务端到客户端的通道还需要 ACK 信号来进行验证。
断开一个 TCP 连接则需要“四次挥手”:
1、客户端:
发送一个 FIN,用来关闭客户端到服务器的数据传送
2、服务端:
收到这个 FIN,它发回一个ACK。
3、服务端:
关闭与客户端的连接,发送一个FIN给客户端
4、客户端:
发回ACK报文确认
任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了TCP连接。
URI 是统一资源标识符,相当于一个人身份证号码
Web 上可用的每种资源如 HTML 文档、图像、视频片段、程序等都是一个来 URI来定位的 URI 一般由三部组成:
①访问资源的命名机制
②存放资源的主机名
③资源自身的名称,由路径表示,着重强调于资源。
URL 是统一资源定位符,相当于一个人的家庭住址
URL 是 Internet 上用来描述信息资源的字符串,主要用在各种 WWW 客户程序和服务器程序上,特别是著名的 Mosaic。采用 URL 可以用一种统一的格式来描述各种信息资源,包括文件、服务器的地址和目录等。
URL 一般由三部组成:
①协议(或称为服务方式)
②存有该资源的主机 IP 地址(有时也包括端口号)
③主机资源的具体地址。如目录和文件名等。
https://www.baidu.com/
URL:统一资源定位符,俗称网址
url 统一资源标识符,是IP的一个映射
www:服务器
https:传输协议(http和TCP之间加了一层 TSL或者SSL的安全层)
baidu.com:域名
ajax是一种创建快速动态网页
的技术,通过XMLHttpRequset对象,访问服务器进行少量的数据交换,使网页实现异步更新,这意味着可以不重载整个页面的情况下,对网页的某些部分进行更新。
全称:异步的javascript和xml 作用:无刷新更新页面的数据(视图) 原理: 客户端 通过xhr与服务器交换数据,客户端用javascript来操作dom渲染更新数据
1)通过异步模式,提高用户体验度
2)优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了客户端宽带占用,同时减轻服务器压力。
1)传统的web应用:如果需要更新内容,必须重载整个页面。浏览器直接发送请求服务器,服务器把数据返回浏览器。
2)ajax实现原理:创建XML对象,让它去访问服务器,服务器接收请求、处理请求,服务器把响应数据返回给XML对象,浏览器渲染页面。
优点:
1)最大的特点整个页面无刷新,只是
局部刷新
,用户的体验非常好2)交互的方式使用
异步请求模式
与服务器交互,更加迅速的响应数据3)
减轻服务器的压力
,利用客户端渲染数据,同时节省客户端的宽带
缺点:
1)ajax不支持浏览器的back按钮
2)安全问题,ajax会暴漏与服务器交互的细节 3)对搜索引擎支持比较弱
创建
XMLHttpRequest
(xhr)对象建立连接,调用 xhr.open()
发出 HTTP 请求,调用 xhr.send()
接收服务器传回的数据
使用javascript操作dom实现局部刷新
第一步:客户机提出域名解析请求,并将该请求发送给本地的域名服务器。
第二步:当本地的域名服务器收到请求后,就先查询本地的缓存,如果有该纪录项,则本地的域名服务器就直接把查询的结果返回。
第三步:如果本地的缓存中没有该纪录,则本地域名服务器就直接把请求发给根域名服务器,然后根域名服务器再返回给本地域名服务器一个所查询域(根的子域)的主域名服务器的地址。 第四步:本地服务器再向上一步返回的域名服务器发送请求,然后接受请求的服务器查询自己的缓存,如果没有该纪录,则返回相关的下级的域名服务器的地址。 第五步:重复第四步,直到找到正确的纪录。
一般会经历以下几个过程:
1、首先,在浏览器地址栏中输入url
2、浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,会直接在屏幕中显示页面内容。若没有,则跳到第三步操作。
3、在发送http请求前,需要域名解析(DNS解析)(DNS(域名系统,Domain Name System)是互联网的一项核心服务,它作为可以将域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网,而不用去记住IP地址。),解析获取相应的IP地址。
4、浏览器向服务器发起tcp连接,与浏览器建立tcp三次握手。(TCP即传输控制协议。TCP连接是互联网连接协议集的一种。)
5、握手成功后,浏览器向服务器发送http请求,请求数据包。
6、服务器处理收到的请求,将数据返回至浏览器
7、浏览器收到HTTP响应
8、读取页面内容,浏览器渲染,解析html源码
9、生成Dom树、解析css样式、js交互
10、客户端和服务器交互
11、ajax查询
经过DNS域名解析系统 -> 把域名解析为ip地址
把ip发送到⽹络供应商(发送HTTP请求) -> 进行TCP的三次握⼿--建⽴连接
服务器处理请求并返回HTTP报文
客户端取回需要的资源sources,浏览器解析并渲染页面
TCP四次挥手,连接结束
1、HTTPS协议需要CA证书,费用较高;而HTTP协议不需要
2、HTTP协议是超文本传输协议,信息是明文传输的,HTTPS则是具有安全性的SSL加密传输协议;
3、使用不同的连接方式,端口也不同,HTTP协议端口是80,HTTPS协议端口是443;
4、HTTP协议连接很简单,是无状态的;HTTPS协议是具有SSL和HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP更加安全
XML 用来传输和存储数据,HTML 用来显示数据;
XML 使用的标签不用预先定义
XML 标签必须成对出现
XML 对大小写敏感
XML 中空格不会被删减
XML 中所有特殊符号必须用编码表示
XML 中的图片必须有文字说明
xss攻击用户使用非法javascript与网站交互实现非法的目的
对于防范xss攻击的话前端可以做到
1.对用户提交的数据进行编码,而不是明文提交,这样可以防止代码注入
2.对提交的数据用正则进行过滤,不合法则不允许提交
3、后端:httponly 防止js访问cookie ,secure让https才发生cookie
服务端渲染:
服务器直接生产渲染好对应的HTML页面, 返回给客户端进行展示。比如:jsp页面
好处:前端耗时少,即减少了首屏时间,模板统一在后端。前端(相对)省事,不占用客户端运算资源(解析模板)
坏处:占用服务器资源。
客户端渲染:
浏览器中显示的网页中的大部分内容,都是由前端写 js 代码在浏览器中执行,最终渲染出来的网页。也可以怎么说:后端返回JSON数据,前端利用预先写的html模板,循环读取JSON数据,拼接字符串,并插入页面。
好处:网络传输数据量小。不占用服务端运算资源(解析模板),模板在前端(很有可能仅部分在前端),改结构变交互都前端自己来了,改完自己调就行。
坏处:前端耗时较多,对前端工作人员水平要求相对较高。前端代码较多,因为部分以前在后台处理的交互逻辑交给了前端处理。占用少部分客户端运算资源用于解析模板.
WebQuality就是网站开发的时候,为了方便残障人员能够通过文字语音播出的方式播放文字内容所开发的一个功能。
残障人士指的是那些带有残疾或者身体不健康的用户。 使用 alt 属性:
通过这样的设置,可以帮助残障人员用语音来浏览网页内容。
除了以上的设计,还可以通过调节字体大小来实现,在浏览器菜单选择"查看 - 文字大小"来改变字体大小。
提升访问速度;允许多路复用;二进制分帧(更快乐,同时容量更大了,可分割更小了)
浏览器的运行机制:解析html以构建dom树 -> 构建(render)渲染树 -> 布局(render)渲染树 -> 绘制render树
(1)触发重绘的条件:改变元素的外观属性,例如:color、background-color,outline等
(2)触发重排的条件:任何布局和几何属性的改变都会触发重排:
例如:
页面初始渲染
添加/删除可见DOM元素 改变元素位置 改变元素尺寸(宽、高、内外边距、边框等) 改变元素内容(文本或图片等) 改变窗口尺寸
1、集中样式改变:可以添加一个class,样式都在class中改变
2、DOM离线化:先设置元素为display:none;然后进行页面布局等操作;设置完成后将元素设置为display:block;这样的设置就只引发两次重绘和重排
3、批量添加DOM:要避免频繁的去操作DOM,可以通过创建documentFragment,完成所有所有DOM操作后,最后一次性把它添加到文档中。
4、 使用absolute脱离文档流:将需要多次重排的元素,position属性设为absolute或fixed,元素脱离了文档流,它的变化不会影响到其他元素。
5、使用 display:none ,不使用 visibility,也不要改变 它的 z-index
6、缓存布局:避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
重排:当页面元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程叫做重排也叫做回流。
重绘:当页面元素样式的改变不影响布局时,浏览器重新对元素进行更新的过程叫做重绘。
重绘是小改变,重绘不一定会发生重排。 重排就是大改变,重排一定会触发重绘,重排会产生比重绘更大的开销。
!!!