前端技术栈
2022-02-04 15:19:09 3 举报
AI智能生成
前端思维导图 最新es特性 css flexd grid布局 DOM BOM webServer只是图谱
作者其他创作
大纲/内容
OOP
AOP
原型链/作用域链
闭包
策略
代理
装饰
观察者
责任链
单例
工厂
前端常用
生成器
原型
适配器
桥接
组合
外观
享元
命令
迭代器
中介者
备忘录
状态
模板方法
访问者
其他设计模式
常用设计模式
常用设计模式网址
设计模式
编程知识储备
持久性跨站攻击
反射型/非持久性跨站攻击
XSS
CSRF
sql注入
点击劫持
DDOS攻击
http请求劫持
安全
JSLint/JSHint/jscs
CSSLint
HTML Validators
代码质量
git
人口
string
object
array
entry
path:输出位置
filename:生成的文件名词
占位符[],name可以根绝入口文件key生成对应文件
output
development
production
mode
模块热替换
基础配置
依赖图谱
Runtime
Manifest
概念
loader 用于对模块的源代码进行转换。loader 可以使你在 import 或\"加载\"模块时预处理文件
支持链式传递。能够对资源使用流水线(pipeline)。一组链式的 loader 将按照相反的顺序执行
可以是同步的,也可以是异步的
运行在 Node.js 中,并且能够执行任何可能的操作
接收查询参数。用于对 loader 传递配置
loader 也能够使用 options 对象进行配置
除了使用 package.json 常见的 main 属性,还可以将普通的 npm 模块导出为 loader,做法是在 package.json 里定义一个 loader 字段
插件(plugin)可以为 loader 带来更多特性。
loader 能够产生额外的任意文件。
特性
less编译成css
less-loader
css序列化
css-loader
css使用style标签加载到html
style-loader
autoprefixer给样式添加前缀
package.json中配置browerslist:[]
browserslist指定目标浏览器
cssnano压缩css代码
postcss-loader
css/less样式
loaderAPI
自定义loader
常用loaders
loader
加载html模板
html-webpack-plugin
html
打包之前自动清理输出目录
clean-webpack-plugin
css文件打包成独立css文件
mini-css-extract-plugin
自定义plugin
plugins
3.x
没有配置文件时也可以打包
大部分时候不符合使用要求,不实用
0配置
4版本地址
4.x
5版本地址
5.x
默认webpack配置名为weibpack.confign.js
配置文件改名
webpack
更加纯粹
体积更小
不如webpack功能全面、强大
与web区别
rollup
冷启动,启动速度极快
即时热更新
按需编译
特点
基于浏览器原生 ES imports 的开发服务器。利用浏览器去解析 imports,在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用
原理
vite
打包工具
语义化
<
>
"
®
©
&trade
转移字符
HTML/HTML5
grid
容器:父元素
项目:多个直接子元素
主轴:子元素排列的方向,默认为row,横向
交叉轴:与主轴垂直的方向,默认column,从上到下
父元素变成弹性布局渲染区域
display:flex
从左到右
row
从右到左
row-reverse
从上到下
column
从下到上排列
column-reversse
制定主轴方向
flex-direction
父元素空间不够不换行,等比例缩小子项目
默认nowarap
内容放不开就换行
wrap
自动换行
flex-wrap
flex-direction和flex-wrap的简写形式
flex-flow:flex-direction flex-warp
flex-flow
主轴上的对齐方式
主轴起点对齐
flex-start
主轴终点对齐
flex-end
主轴上居中对齐
center
两端对齐,中间多个元素等间距分布
space-between
所有元素等间距分布
space-around
justify-content
交叉轴上的对齐方式
交叉轴起点对齐
交叉轴终点对齐
flext-end
交叉轴中线居中对齐
如果项目没有设置尺寸,项目在交叉轴上沾满空间,垂直拉伸
stretch
基线对齐
baseline
align-items
容器属性
定义项目在主轴上的排列顺序
值越小越靠近主轴起点
order
单个项目在交叉轴上的对齐方式
align-self
项目的缩小比例
本项目的shrink/所有shrink的和就是缩小占比例
flex-shrink
项目的放大比例
如果有剩余空间,值越大所占空间越多
所有项目中本项目的grow/所有grow的和就是所占比例
flex-grow
项目属性
flex
行内样式
style标签内
外部样式表
导入样式
引用方法
优先级
id
class
标签
子选择器>
后代选择器(空格)
通用选择器*
兄弟选择器~
第一个兄弟+
注意顺序
:link
:visited
:hover
:active
:after
:before
:focus
:first-child
:nth-child
伪类
选择器
none
block
不可设置宽、高、边距
inline
可设置宽、高、边距,
inline-block的默认对齐方式是vertical-align:baseline
inline-block
display
盒模型
BFC block formatting context 即块级格式化上下文,他是一个独立的渲染区域,只有块级元素参与,他规定了内部的块级元素如何布局,并且与这个区域之外毫不相干。外部元素也不能影响这个渲染区域内的元素
BFC是页面上的一个隔离的独立渲染区域,区域内的子元素不会影响外部的元素,外部的元素也不会影响里面的元素
定义
默认内部的块级元素会在垂直方向上一次放置,每个元素独占一行
块级元素垂直方向上的总距离由margin决定。属于同一个BFC的两个相邻元素在垂直方向上的margin会发生重叠/合并
BFC区域不会与float浮动定义的元素区域重叠
BFC就是页面上的一个隔离的独立渲染区域,渲染区域里面的子元素不会影响外面的元素。外面的元素也不能影响到渲染区域里面的子元素
计算父元素BFC的高度时,内部浮动元素的高度都必须计算在内
布局规则
display的值是inline-block,flex,inline-flex,table-cell,table-caption
overflow的值不是visible
float的值不是none
position的值不是static或者relative
创建BFC
问题:垂直方向上,两个元素上下margin相遇 ,两个幻速的距离不等于两个margin的和。而是等于最大的margin,较小的margin会被合并
解决方式: 使用一个外围块元素包裹下方元素,新的外层元素设置overflow:hidden
结果:下方元素的margin-top收到外层BFC渲染区域的阻隔不会影响外部上方元素的margin-bottom。同理,上方元素的margin-bottom也不能跨过BFC来影响BFC内部元素的margin-top
避免垂直方向margin的合并
问题: 子元素设置margin-top,会超出父元素上边的范围,变成父元素的margin-top实际上,父元素和子元素之间还是没有距离,这不是想要的效果
解决:设置新外层元素overflow:hidden,变成一个BFC
为父元素添加border,如果不需要border,可以设置颜色透明
为父元素设置padding替换子元素的margin
为父元素内的第一个子元素之前添加一个<table></table>,使用平级的BFC阻隔下方元素的margin
其他解决方案
结果:子元素的margin-top收到外层父元素BFC渲染区域的阻隔,不会影响父元素以外的区域了
避免垂直方向margin溢出
.left{float:right;width:固定值}
.right{overflow:hidden} 变成BFC渲染区域,就不会与float左侧重叠了
左固定,右自适应
自适应两栏布局
问题:父元素不写高度时,子元素使用了浮动,导致父元素高度不被撑起,父元素高度下降露出float的子元素,父元素的同级元素也会被float元素遮挡
造成新的浮动问题
1. 父元素也使用float,生成BFC渲染区域,强制高度包含float元素
造成子元素不能超过父元素区域
2. 父元素设置overflow,生成BFC渲染区域,强制高度包含float元素
子主题
3. 父元素内部最后的位置添加一个空的子元素,设置clear:both;清楚浮动影响
lef
解决
父元素坍塌
解决的问题
BFC
不可自由嵌套的块级元素:h1-6, caption, p, hr, dt他们之中只能放内联元素
父元素必须时块级盒子元素
父元素宽度必须已经设定
前提
不存在水平居中,因为块级元素没有宽度会充满整个父元素
场景1:子元素时块级元素且不固定宽度
给父元素设置text-align:center
场景2:子元素时行内元素,宽度由内容撑开
给子元素设置margin:auto,自动分配剩余空间
给父元素和子元素都设置box-sizing:border-box
父元素padding 的值为(父宽-子宽)/2
通过计算设置父级元素的padding-left或者padding-right
父元素相对定位
子元素left:50%;margin-left:子元素宽的一半
子元素left:50%;transform:translateX(-50%)
通过相对于父元素绝度定位
场景3: 子元素时块级元素且设置宽度
水平对齐
前提:父元素时盒子容器
单行:设置父元素的line-height为其高度来使子元素垂直居中
多行:给子元素设置diaplay:inline-block/inline/table-cell; vertical-align:middle;同时利用after为元素添加一个height:100%;vertical-align:middle的元素
场景1:子元素时行内元素,高度由内容撑开
方法1:给父元素这是display:inline/inline-block/table-cell;vertical-align:middle来解决
方法2: flexbox;父元素:display:flex;flex-direction:column;justfiy-content:center
场景2: 子元素使块级元素,但是高度没有设置
给父子元素设置box-sizing:border-box
设置子元素margin为(父高-子高)/2
方法1计算子元素的margintop或者marginbottom
设置父元素padding(父高-子高)/2
方法2 计算父元素的padding-top或padding-bottom
子元素高已知:top:50%;margin-top:-子高的一半
子元素高度未知:top:50%;transform:translateY(-50%)
方法3 子元素相对于父元素绝对定位
父元素display:flex;flex-direction:column;justify-content:center
方法4: flex布局
场景3: 子元素是块级元素,高度已经设定
垂直居中
父元素:display:flex;flex-direction:column;justify-content:center;align-items:center
弹性布局
top:50%;left:50%;margin-top:-子高的一半;margin-left:-子宽的一半
子元素宽高已知
子元素宽高未知
父相子绝
垂直和水平都居中
对齐总结
{width:0;height:0;border-lef:50px solid transparent;border-right:50px solid transparent;border-bottom: 100px solid black;}
上三角形
{width:0;height:0;border-lef:50px solid transparent;border-right:50px solid transparent;border-top: 100px solid black;}
下三角形
{width:0;height:0;border-top:50px solid transparent;border-bottom:50px solid transparent;border-right: 100px solid black;}
左三角形
{width:0;height:0;border-top:50px solid transparent;border-bottom:50px solid transparent;border-left: 100px solid black;}
右三角形
{width:0;height:0;border-top:100px solid black;border-right: 100px solid transparent;}
左上三角形
{width:0;height:0;border-bottom:100px solid black;border-right: 100px solid transparent;}
左下三角形
{width:0;height:0;border-top:100px solid black;border-left: 100px solid transparent;}
右上三角形
{width:0;height:0;border-tottom:100px solid black;border-left: 100px solid transparent;}
右下三角形
构建三角形
pt 屏幕宽/设备分辨率,其中的一份就是1pt
设备物理像素
pc机显示器,1px等于0.76个物理像素
以iphone6为标准,物理像素750,分辨率375
手机屏幕,1px = 2pt
px也是一个相对单位
但是手机屏幕大小不一,差异较大,所以不希望所有手机上显示一样大,而是希望能够等比例缩放,所以移动端不用px
px
以网页根元素html上设置的字体大小为1rem,默认1rem==16px
可以实现响应式布局,通过监听屏幕大小,改变html的字体大小,就可以改变所有元素的大小,以实现响应式布局
rem
父元素字体大小为1em
em
小程序专用的单位
无论屏幕大小都分成750份,每份就是1rpx
1px = 2pt = 2rpx
可以不同尺寸屏幕下自动适配
rpx
vh:不管视口高度多少,都将视口高均分100份,每1份时1vh
vh:不管视口宽度多少,都将视口宽均分100份,每1份时1vw
本质上是百分比,但是有一个固定的参照
vm/vh
通常任务子元素的%完全相对于父元素,但并不绝对
子元素的top、bottom设置百分比,是相对于直接非static定位的父元素的高度
子元素的left、right设置百分比,是相对于直接非static定位的父元素的宽度
子元素的padding、margin设置百分比,不论是垂直还是水平方向,都是相对于直接父元素的padding和margin而非width或height
%
css像素
rem/em/px/pt/%/vw/wh/rpx的区别
代码简单,布局方便
缺点:如果中间由内容,缩小到最小就不会再小了
兼容性有问题
设置容器的行、列数
grid-template-colums:100px 100px 100px 三列100px
固定各自大小,使用多个沾满宽度
gird-template-columbns: 1fr 2fr 3fr 分成3列分别占1/6, 2/6, 3/6
按份数分配列宽
grid-template-colums:1fr minmax(150px, 1fr)表示第二列最小150px,最大1fr
设置最大最小范围
grid-template-colums: 100px auto 100px
浏览器自己决定长度
grid-template-colums:[c1] 100px [c2] 100px [c3]100px[c4]
定义网格线
grid-template-columns、grid-template-rows
各自之间的间距
grid-auto-flow:row;先填满第一行再放入第二行
grid-autp-flow:colum 先填满第一列再放入第二列
grid-auto-flow
整个区域,所有项目的水平对齐方式
start, end, center, stretch, space-between, around-between, apace-evenly
整个区域,所有项目的垂直对齐方式
取值同上
align-content
单元格内容的水平对齐方式
值:start end center stretch
justify-items
单元格内容的垂直对齐方式
容器
制定item的具体位置在哪根网格线
表示从第一条网格线到第三个网格线
简写grid-column:1/3
grid-column-start:1;grid-column-end:3
表示跨两行两列的方形区域
简写grid-area:1/1/3/3
grid-column-start:1;grid-column-end:3;grid-row-start;1;grid-row-end:3;
grid-column-start、grid-column-end、 grid-row-start、grid-row-end
当前单元格内容的水平和垂直方向
place-self同时设置水平和垂直方向
justify-self/align-self
项目
结合media查询可以实现响应式布局
缺点:代码写法复杂,布局繁琐
首先给根元素设置一个字体大小,其他尺寸单位都用rem,监听屏幕大小按比例改变根元素字体大小
缺点:大部分浏览器都有一个字体最小值:12px,字体不会再小了
单位rem
容易被挤压换行
float
响应式布局
通过媒体查询来设置样式是响应式设计的核心
打印机
print
屏幕阅读器等发声设备
speech
屏幕设备总称,包括电脑屏幕、手机屏幕、平板
screen
媒体类型
在style标签中通过设置media来设置使用样式的媒体设备
style
在link标签上通过media设置使用样式的媒体设备
<link rel='stylesheet' href='xxx.css' media='print'/>
一个css可能同事被多个页面引用,只要用link就要加media有点繁琐
link
@import
可以使用@media做到更细的控制,一个样式可以为多个媒体设备定义样式
<style>@media screen{ h1{ font-size:13px }}@media print{ h1{ font-size:8em; }}</style>
@media
orientation:landscape 横屏
orientation: portrait;竖屏
设备方向orientation
可以使用不同条件限制使用的样式
@media screen and (orientation:landscape) and (max-width:600px){ h1{ font-size:12px }}
横屏显示宽度不能超过600px
横屏显示或宽度不能超过600px
@media not screen and (orientation:landscape) and (max-width:600px){ h1{ font-size:12px }}
not必须写在开头表示后边的条件都不满足才能使用
既不是横屏,宽度又不小于600px
永远使用最后一个
因为最小900px包含了最小1200的情况
@import url(xxx.css) screen and (min-width:1200px)@import url(xxx.css) screen and (min-width:900px)
引入顺序
小于768位嘲超小屏幕(手机)
768-992 小屏幕设备(平板)
992-1200 中等屏幕(桌面显示器)
1200以上宽屏设备 (大桌面显示器)
设备划分
超小屏幕,设置宽度位100%
小屏幕宽度设置位750
中等屏幕宽度设置为 970
大屏幕宽度设置为1170
父容器尺寸划分
rem相对于根元素字体
html{ font-size:100%; }
@media(min-width:640px){body{font-size:1rem;}}
@media(min-width:960px){body{font-size:1.2rem;}}
@media(min-width:1200px){body{font-size:1.5rem;}}
响应式字号
查询条件
媒体查询
display:inline-bliock;scale只能缩放行内块或块元素
-webkit-tranform:scal(0.5);定义缩放
-webkit-transform-origin:left top;定义缩放原点为左上角,非左上角会导致padding、margin比例不对
实现小于12px的字
.half-px{ height:0.5px; } 不同设备,不同浏览器差异较大
问题
.half-px{ height:1px; transform:scaleY(0.5); transform-origin:50% 100%;// 防止线模糊}
.half-svg{ background:none; height:1px; background:url(\
background:url
firefox不可使用?把svg转成base64
更好的解决:svg
0.5px的线
缩放
CSS/CSS3
变量
nav{ url{ margin:0} li{ display:inline-blockl} a{ padding: 12px; }}
.demo{ font:{ size:30px; color:red; }}
属性也可以嵌套
a{ font-weight:bolder; &:hover{// 设置父元素a的hover属性 text-decoration:underline; }}
#main{ color:black; &-sidebar{ border:1px solid; }}
父选择器可以连接自定义后缀,&必须放在开头
父级选择器 &
嵌套
混合mixin,用来分组那些需要在页面中服用的css生命,可以给mixin传递参数来使mixin更加灵活
用来解决浏览器前缀非常有用
@mixin border-radius($radius){ border-radius:$radius; -ms-border-radius:$radius; -moz-border-radius:$radius; -webkit-border-radius:$radius;}.box{ @include border-radius(10px)}
混合
%message-common{ border:1px solid #ccc; padding:10px; color:#333; }.message{ @extend %message-common;}.success{ @extend %message-common; border-color:green;}
继承
.container{ width:100; }article[role='main']{ float:left; width:600px/960px*100%}aside[role='complementary']{ float: right; width: 300px/960px*100%;}
算术运算符
sass
less是基于js的在客户端处理,sass是基于ruby,所以在服务器处理
变量less用@ sass使用$
less的作用域会先查找局部定义的变量,没有找到就想上查找
less中的混合(mixin)直接使用class命名,使用时直接使用,sass中的混合需要@mixin name命令,使用时需要@include mixinA()
p{ @if 1+1==2{border:1px solid;} @5<3{ border:2px dotted;}}
@if lightness(@color) >30%{ background:#000}@else{ background:#fff}
@for $i from 1 to 10{ .border-#{$i}{ border #{$i}px solid blue; }}
$i : 6@while $i>0{ item-#{$i}{ widht:2em*$i; } $i:$i-2;}
@function double($n){ @return $n*2}#sidbar{ width: double(5px);}
sass中增加了条件语句和循环语句 @if @else @while @each @for自定义函数@function @return
less和sass的不同
Sass/LESS/Stylus
样式
简单数据类型
泛型
类型全部可选
Partial
属性必选
required
属性只读
readonly
选取某些属性
pick
属性的key
keyof
Extract
exclude
record
omit
与readonly相反,改为可修改
mutable
获取函数返回值类型
ReturnType<T>
内置类型
interface
type
in
infer
关键字
TypeScript
HTML使用<script>标签引入javascript
外部引入js会忽略标签内部代码
3. 适应未来.放在外部不用考虑XHTML不兼容的问题、或不支持js脚本浏览器直接显示js代码的问题
1.需要使用实体形式的<>
推荐使用外部js
noscript
HTML引入js
标识符区分大小写
以_字母$开头
生下的字符可以是_字母$和数字
不能以保留字和关键字作为标识符
标识符
1. 有助于防止省略带来的问题
2. 有助于删除空行压缩代码
3。 解析器会帮助加分号,所以有时能有性能提升
高程中推荐每个语句都写分号
1. 现代js很少直接写脚本直接用,而是使用编译器压缩、编译之后使用,浏览器不会花时间在分号上
2. 编译器会帮助我们添加分号和压缩代码
3. 对于可能出问题的代码主要情况是以{ [ ( + -开头的代码会有问题,与其全部都加,不如记住特殊情况
4。 以{[(+-开头的代码分号可以放前面,叫做行首分号
5. 对于有些编译器不能正确添加分号的情况,是编译器的锅。因为ECMA 262 已经规定了ASI(Auto semicolon insertion)规范,即如何自动添加分号
社区有不同建议:认为这是语言风格的不同
js分号问题
声明的同时必须初始化
声明后不可修改
其他与let基本相同
const
let声明的范围是块作用域,注意和var的区别
作用域
同一个作用域中,不能使用let1重复定义同一个变量
使用let声明的全局变量不会称为window的属性,但相应的变量也会在页面的声明周期内续存,要小心重复声明
因为let作用域为块,所以在let声明之前不能以任何方式来引用未声明的变量,在let声明之前的执行瞬间被称为暂时性死区
暂时性死区
var 定义的变量会穿透到for循环块的外部,导致可以读到var内的变量
let在每一次循环时都会声明一个独立变量实例
for循环定义
let
使用var定义的变量font color=\"#ff0000\
变量提升
可以使用var重复定义同一个变量
var定义的变量会成为包含它的函数的局部变量,注意和let的区别
可以省略var操作符来声明一个全局变量,该全局变量会自动称为window对象的属性
var
解析:a.x解析为a的地址上的x属性(假设地址为0x1234.x),因为x实在a对象内部;a解析为形参a
所以执行就是把{n:1}赋值给a,a={n:1} 的返回值是{n:1}的地址,然后把这个地址赋值给原来0x1234.x,也就是0x1234.x={n;1}
注意js引擎会从左到右解析,从右向左执行
赋值操作:var a={};var b=a;a.x = a = {n:1}
以0开头,如果数值超过7按照十进制处理 严格模式下报错
严格模式下使用0o开头,超过7报错
八进制数
0x开头,超过f报错
十六进制
数值在所有数学操作中都视为十进制数,结果自动转成十进制数
所以js想方设法的把浮点数转成整数
1.0会转成整数1
1. 转成整数1
浮点数的内存空间是整数的两倍
js自动把六位小数的浮点数转换为科学计数法
大数使用科学计数法表示3.14e7 ==== 31400000
永远不要比较浮点数的相等
理论依据查看范围章节
1. 把浮点数转整数,再转回浮点数;例如:(0.1*10+0.2*10)/10
2. 计算结果的插值与Number.EPSILON比较,小于这个数表示差值没有意义,可以理解为相等,例如Math.abs(n1-n2)<Number.EPSILON 就可以理解为相等
处理办法
注意0.1+0.2 =》0.300 000 000 000 000 04
浮点数
对十进制/2取余,一直取到0,倒着看余数就是二进制
计算一下0.1的二进制形式会发现为无线循环小数0.0001100110011001100110011001100110011001100110011001101...
这个无限小数就是浮点数计算不准确的原因
十进制小数转二进制,乘以2取整,顺序排列。直到小数位为0
十进制转二进制
Number.MIN_VALUE
这种说法有问题
超过它就会是Infinity
+10000000也不是
因为按照IEEE754存储标准,大于1.7976931348623158*10**308才会被定义为Infinity
Number.MAX_VALUE只有1.7976931348623157*10**308,还差1*10**292才会超大小
Number.MAX_VALUE+1 != Infinity
理论上能表示的最大值
Number.MAX_VALUE
由于数字存储会先把十进制转二进制,再转科学计数法,之后尾数只能存储53位(存储52位,首位1省略不存,所以是53位),再多位数53位之后的会被省略,也就是不安全,最大安全数字为2**53-1 为什么-1,想想3位数最大值是10*2-1就明白了
2**53-1
Number.MAX_SAFE_INTEGER
0-2**53+1
Number.MIN_SAFE_INTEGER
2**-52
表示1与大于1的最小浮点数之间的差值
ϵ或ε 读作:厄普西隆
Number.EPSILON
分别是1个符号位+11个指数位+52个尾数位举个例子,如果是5.5这个数字的话,则计算过程是这样的:5.5 转二进制 =====> 101.1 科学计数法 =====> 1.011*2^2存入计算机:符号位:0指数位:2 加1023 =====> 1025 转二进制 =====> 10000000001尾数位:1.011 隐去小数点左边的1 =====> 011
数字存储理论
范围
表示本来应该返回数值的操作失败了
Not a Number
使用 isNaN来判断
NaN == NaN false
NaN
true=>1
false=>0
布尔值
含有非数值字符(不是进制标记,开头不是+-)返回NaN
空字符串返回0
直接返回
number
0
null
undefined
不传参数
如果是原始值,转换原始值,否则报错
如果是不是原始值,再调用toString()方法,转换返回值
先调用valueOf()方法,转换其返回值
Number()
第一个字符不是数字、+、-返回NaN
Number('') === 0
空字符串返回NaN
遇到第一个非数字字符截断,后面的被忽略
parseInt
不能指定进制,只能解析十进制
八进制、十六进制等会返回0
parseFloat()
数值转换
\
\\t
换页
\\f
\\\\
\\'
\\\"
\\`
十六进制编码nn表示的字符,nn是十六进制0~F例如\\x41等于‘A’
\\xnn
十六进制编码nnn表示的Unicode字符,其中nnn是十六进制0~F
\\unnn
转义字符
字符串一旦定义就是不可变的(immutable)
`` 反引号定义
注意字符串模板内的换行和空格都会被保存在字符串内
可以自定义插值的行为
定义一个普通函数作为标签函数
参数是一个数组,第一个参数是插值表达式两边和间隔的字符串
剩余参数是各个插值表达式的值
tagfn `xx${1}bb`
使用
标签函数
获取原始的木模板字面量内容,而不是转义后的字符
String.raw
注意只对模板字符串有效,其他字符串报错
标签函数第一个参数,默认含有原始字符串的数组
原始字符串
模板字符串
用于创建当前对象的函数
constructor
判断当前对象实例是否存在给定的属性(不是原型上),参数是字符串或符号
hasOwnProperty(name)
判断当前对象是否为另一个对象的原型
isPropertyof(object)
属性是否可以使用
propertyIsEnumerable
本地化的对象字符串表示
toLocalString
对象的字符串表示
toString
返回对象对应的字符串、数值或布尔类型
valueOf
false == 0 true
false == '0' true
false == NaN false
true == NaN false
false == undefined false
true == undefined false
false == null false
ftrue == null false
使用==会有自动类型转换
参考数据类型转换
Boolean('0') true
Boolean('') false
Boolean(NaN) false
Boolean(null) false
Boolean(undefined) false
if自动转换和Boolean()相同和==完全不同
boolean
除了typeof操作符。其他任何情况下使用未声明的变量都会报错
未定义
声明之后未初始化
未定义和未初始化是完全不同的两个概念,但他们的typeof都是undefined
null是指一个空对象指针,typeof null === ‘object’
undefine是未初始化的变量 typeof undefined === ‘undefined’
undefined == null true
undefined === null false
和null区别
空对象指针
定义将来要存储对象的变量时,建议使用null来初始化
和undefined表面相等,全等为false
符号实例是唯一、不可变的
用来保存对象属性使用唯一标识符,不会发生属性冲突的危险
let sym = Symbol('xxx')
不能使用new 操作符
创建
Symbol.for()
传入的不是字符串会转成字符串
使用一个z字符串类型的key在全局符号注册表中创建并重用符号
对每个字符串进行幂等操作,第一次使用某个字符串会在全局注册表中查询对应符号,发现没有就是用这个字符串创建一个,下一次使用同样的字符串,就返回这个符号
即使使用同样的符号描述,在全局注册表中注册的符号和Symbal()注册的符号也不等同
传入Symbol查询key
Symbol.keyFor()
全局注册表
对象字面量
Object.defineProperty
返回常规属性数组
Object.getOwnPropertyNames()
返回符号属性数组
Object.getOwnPropertySymbols()
返回同时包含常规属性和符号属性描述的对象
Object.getOwnPropertyDescriptors()
返回常规属性和符号属性的key
reflect.ownKeys()
查询对象属性
符号作为属性
由for-await-of使用的遍历方法
使用for-await-of时,会调用key为Symbol.asyncIterator的函数,这个函数会返回一个实现迭代器API的对象
很多时候这个对象是一个Generator
Symbol.asyncIterator
默认迭代器,由for-of语句调用
Symbol.iterator
由String.prototype.match方法使用
正则表达式原型上有这个函数的定义
表示用该方法匹配字符串
该方法接受一个参数,就是调用match方法的字符串实例
Symbol.match
由String.prototype.replace方法使用
表示如何替换一个字符串中匹配的字串
接受两个参数,即调用replace方法的字符串实例和替换字符串
Symbol.replace
由String.prototype.search调用
表示字符串中匹配正则表达式的索引
接受一个参数,就是调用search方法的字符串实例
Symbol.search
一个正则表达式,方法,该方法在匹配正则表达式的索引位置拆分字符串
由String.prototyope.split调用
接受一个参数,就是调用split方法的字符串实例
Symbol.split
由instanceof使用
instanceof操作符会使用Symbol.hasInstance函数来确定关系,这个函数返回一个boolean
Symbol.hasInstance默认在Function的原型上,因此所有函数和类都能调用
可以在继承的类上重写这个方法,自定义instanceof的逻辑
Symbol.hasInstance
由Array.prototype.concat函数执行时,是否能被它拍平
Symbol.isConcatSpreadable
一个函数值,该函数作为派生对象的构造函数
用Symbol.species定义静态的获取器(getter),可以覆盖新创建实例的原型定义
Symbol.species
由ToPrimative抽象操作使用
定义将对象转换成原始值的方法
Symbol.toPrimitive
该属性表示一个字符串,该字符串用于创建对象的默认字符串描述
由Object.prototype.toString()调用
toString()获取对象标识时,会检索Symbol.toStringTag指定的实例标识符,默认为“Object”
Symbol.toStringTag
一个对象,该对象所有的以及继承的属性,都会从关联对象的with环境绑定中排除
with操作符不推荐使用,所以也不推荐使用Symbol.unscopables
Symbol.unscopables
内置符号12
symbol
bigInt
数据类型
返回原始值,返回该值
不是原始值,报错
返回不是原始值,调用toString()
先调用对象的valueOf方法
'true' 'false'
Boolean
'1234'
Number
遵循转原始值
'null'
'undefined'
转字符串String()
1 0
空返回0
开头是+、-、0会忽略,带有进制标识的会转成对应十进制,有进制标志又不合法对应规则的返回NaN
遵循转原始值的流程
转数字Number()
false
包括object类型,不管valueOf和toString返回什么,都是true
font color=\"#ff0000\
其他为true
转布尔值Boolean()
隐式转换规则
null返回空字符串
undefined返回空字符串
object返回\
函数返回函数的字符串形式
返回逗号,分隔的字符串
数组
函数字符串
function
没有toString()方法,会报错
null\\undefined
toString()
全等,没有隐式转换,类型和值都要相同
===
string转成number再比较
string == number
boolean转成number再比较
boolean == 其他类型
先转原始值,再比较
其他类型是基本类型
比较地址
其他类型是object(包括array、function)
object 与其他类型比较
null == undefined
NaN不和剩余的其他类型相等(==),包括它自身,NaN == NaN false
null 和 undefined
==
类型转成number再计算
- * /
当有字符串参与时,其他类型转成字符串再参与拼接
+
算数运算符
类型转number再比较
类型转boolean再判断
if判断、while循环
先转boolean再取反
非!
需要转换的操作
数据类型转换
先++--再返回数值
先返回变量,再变量++--
后缀++11
相当于转number Number()
取负数
-
一元+、-
一元操作符
再+1
绝对值的二进制先取反码
负数使用二补数(补码存储)
即每个数二进制都取反
再计算十进制计算
补码-1,再取反得到绝对值的二进制表示
每位取反,得到一个负数再计算机中表示的补码
10进制转二进制
正数按位取反
再计算十进制
在对补码按位取反,获取整数的二进制形式
先获取负数的计算机表示形式,即绝对值的补码
负数按位取反
对十进制取相反数再-1
25按位取反=-26
~-5 == 4
计算规则复杂,简单记忆
~按位取反
即绝对值的补码
负数还是先取计算机中的表示形式
二进制对齐按位与
&按位与
负数同上
二进制对其或
|按位或
两位不同返回1
^异或
二进制左移,用0填补右侧空位
其实左移n位,就是扩大了2**n倍,参考十进制左移
<<左移
符号位不跟随移动,其他位移动后左侧补0
>>有符号右移
正数的无符号右移和有符号右移相同
负数要先找到计算机表示形式,即绝对值的补码,再右移,产生的结果变化非常大
>>>无符号右移
位操作符
操作数转布尔值再取反
!!把数据转布尔值和Boolean()作用一样
!非
短路操作符
返回不一定是布尔值
第一个操作符是true,返回第二个操作符
&&与
第一个操作符是false,返回第二个操作符
第一个操作符是true,返回第一个操作符
||或
逻辑运算符
非数字使用Number()转数字再计算
NaN*任何数==NaN
*乘
操作数由NaN返回NaN
/除
%取余
**指数
-0加-0==-0
+0加+0 == +0
-0加+0 == +0
操作数有字符串,转字符串拼接
+0减+0 == +0
+0 减-0 == -0
-0 减 -0 == +0
有非数字的先转数字
数学运算
有操作数是数字,先转数字再比较
注意大写字母都比小写字母小,相同的大小写形式比较,才能符合字母顺序
比较对应字符编码
都是字符串
有object,先转原始值
>
<
>=
<=
!=
!==
关系运算
a>b?a:b
三元运算符
=
+=
-=
*=
/=
%=
**=
<<=
>>=
>>>=
赋值
最后一个值
逗号
操作符
if
while
循环体至少执行一次
do-whiel
每一个条件语句的判断都是===全等
switch
for
枚举对象中的非符号属性
for in
for of
for await of
定义一个xxx标签,和break、contine结合使用返回代码的特定位置
xxx:statement
标签语句
break xxx
结束循环,跳出循环体
break
continue xxx
结束本次循环,进行下一轮循环
continue
代码作用域设置为特定对象
块中未定义的变量会搜索with(object)中的object
不推荐使用 ,严格模式报错
with
流程控制
语言基础
函数参数是传值,不是传引用
传递参数
函数作用域
var变量提升
let、const块级作用域
js会自动的在变量不会再使用使释放它所占的内存
在垃圾回收程序运行时,会标记内存中的所有变量,然后,将在上下文中的变量,以及被变量引用的变量的标记去掉
生下的还有标记的变量就是需要删除的
1. 标记清理
当一块内存A被赋予变量B时,表示这个内存A被引用了1次。当变量B赋予了其他的值,则内存A的引用数减1
垃圾回收运行时,清除被引用数为0的内存
循环引用永远不会被清除,如果多次调用相关的代码会导致大量内存不会被释放
这个算法有问题
2. 引用计数
垃圾回收机制
由于垃圾回收周期性运行,如果变量又多,会导致性能损失。所以垃圾回收的时间调度很重要
v8在一次完整的垃圾回收之后,会根据活跃对象的数量加上一些余量来确定何时再次垃圾回收
IE7之前的回收机制饱受诟病,因为它定死了一个阈值,比如256个变量、4096个对象/数组字面量和数组槽位或64kb字符串,只要满足其一就运行垃圾回收
问题在于,有时候可能在整个生命周期内都需要这么多的变量,这回导致垃圾回收运行过于频繁
优化:IE7之后,改为动态调优,动态分配阈值,一次垃圾回收运行后,只回收了不到15%的已分配内存,则阈值翻倍,如果回收了超过85%的内存,在阈值重置到默认值
性能
为了放置js网页耗尽电脑内存,所以分配给浏览器的内存要比桌面软件少很多,移动浏览器更少
保持内存占用少可以提高性能,也就是在数据不再使用时设置为null,解除引用
他们是块级作用域,所以他们可能会更早的被垃圾回收机制回收
const、let提高性能
内存管理
1. 内存保存在全局、一只没有解除引用
2. 定时器引用的变量不会被回收
3.闭包引用的变量不会被回收
内存泄漏
变量、作用域、内存
严格模式下省略var操作符定义全局变量报错:ReferenceError
不能定义名为eval和arguments的变量
八进制数严格模式下以0o开头,超过7报错,非严格模式0开头,超过7按十进制处理
with语句报错
use strict 严格模式
对象是某个特定引用类型的实例
Date将日期存储为1970年1月1日零时到现在的毫秒数
接受\"月/日/年\" 如\"4/9/2021\"
接受 \
接受ISO扩展格式YYYY-MM-DD __HH:mm:ss
返回该日期表示的毫秒数
Date.parse()
返回毫秒数
接受年、月(0-11)、日(1-31)、时0(0-23)、分、秒、毫秒作为参数
Date.UTC
接受毫秒数作为参数,创建日期对象
当参数不是毫秒数时,根据参数形式先调用Date.parse()或Date.UTC()生成毫秒数,再创建日期
new Date()
通常返回带时区的日期和时间,时间24小时制
有浏览器差异,注意输出不同,所以用于显示有问题
本地日期,返回上午、下午12小时制,不带时区
toLoclString()
日期对象比较实际上就是比较valueOf的返回值,因此,比较两个日期对象不用担心比较字符串产生的一些问题
valueOf()
与valueOf相同返回毫秒数
getTime
返回4位数年
getFullYear()
设置年
setFullYear()
返回0-11制的月
getMonth
设置月,超过11加年
setMonth
返回1-31日
getDate
设置日,超过该月天数加月
setDate
返回星期数,星期日0,星期六6
getDay
返回0-23小数
getHours
设置小时,大于23加日
setHours
获取分钟0-59
getMinutes()
设置分钟,超过59加时
setMinutes
获取秒,0-59
getSeconds
设置秒,超过59加分钟
setSeconds
获取毫秒数
getMilliseconds
设置毫秒数
setMilliseconds
获取分钟制的时区偏移量
getTimezoneOffse
继承的方法
Date
let expression = /pattern/flags
g全局模式,查找字符串的全部内容,遇到匹配内容不结束
i,不区分大小写
y,粘附模式,只查找从lastIndex开始及以后的字符串
u,unicode模式,启用Unicode匹配
flags标记用于控制正则表达式的行为
字面量表示形式
参数:正则字符串和模式字符串
注意都是字符串,所以有时候转移需要二次转义
字面量/\\w\\\\hello\\\\123/ ====>> 传入RegExp的字符串 /\\\\w\\\\\\\\hello\\\\\\\\123/
global是否全局匹配
ignoreCase是否忽略大小写
unicode是否开启unicode匹配
sticky是否开启粘滞y标记
mutiline是否设置m标记
dotAll,是否这是s标记
lastIndex
source正则表达式的字面量,注意返回没有前后/
flags返回标记字符串
RegExp实例属性
和捕获组配合使用,接受一个字符串参数
没有匹配返回null
有匹配返回一个数组,第一个元素是匹配成功的字符串,之后的是匹配成功的捕获组
index,表示字符串中成功匹配的起始位置
input表示输入的字符串
有g,每次执行都会在lastIndex基础上向前匹配,直到最后
没有g,lastIndex都是0,每次都返回第一个匹配信息
注意有没有g全局匹配标识,方法的行为不同
exec
返回是否能够匹配成功,boolean类型
test
返回正则的字面量形式
和toString相同,返回字面量形式
实例方法
最后搜索的字符串
$_
input
最后匹配的文本
$&
lastMatch
最后匹配的捕获组
$+
lastParen
input字符串中出现在lastMarch左侧的文本
$`
leftContent
input字符串中出现在lastMarch右侧的文本
$'
rightContent
1~9个捕获组
$1~$9
注意:构造函数的所有属性都没有web标准,生产环境中使用有危险
构造函数/静态属性
RegExp构造
RegExp
1. 创建一个对应的包装值类型实例
2.执行相应的类方法
3.销毁包装值类型实例
以读模式访问原始值步骤
不要使用包装值类型,因为包装值类型typeof 为object,在做判断时有迷惑性
falseObj == true
const falseObj= new Boolean(false)
取x位小数,四舍五入
toFixed()
toExponential()
根据情况返回最合理的输出结果,可能是固定长度也可能是科学计数法
toPrecision
是否是整数
(1.00).isInteger==true
isInteger
整数是否在安全 范围内
isSafaInteger
js字符串由16位码元组成,对于大多数字符来说,16位码元对应一个字符
length属性就是返回字符串包含多少个16位码元
charAt返回给定索引位置的字符,就是查找制定索引位置的16位码元,并返回该码元对应的字符
js字符
返回对应索引的的字符
charAt
返回对应索引的字符编码
charCodeAt
返回根据字符编码得到的字符拼接起来的字符串
fromCharCode
返回索引对应的码点
码点是Unicode中对一个字符的完整标识,他可能是16位也可能是32位
注意如果传入的索引不是代理对的开头,会返回错误的结果,可以使用遍历字符串来解决这个问题
codePointAt
使用码点创建字符串
fromCodePoint
解决策略是再使用另一个16位一起表示字符,叫做代理对
这时候字符串的方法就会出问题,比如笑脸字符
\"ab😊de\".length === 6
\"ab😊de\".charAt(1) === b
\"ab😊de\".charAt(2) ===><?>
这时候索引2和索引3被看成一个代理对,只对应一个字符
由于每个字符都是16位表示,所以对超过16位编码的字符就会无法表述
由于有些字符,既可以使用16位表示也可以使用32位表示,甚至还有其他表示方法,虽然字符样子相同,但编码不同因此不相等
NFKC
NFC
NFKD
NFD
为了解决这个问题有4中规范策略
传入规范化策略,返回规范化的字符串
normalize
连接字符串,不改变原字符串
+连接更方便
concat
两个参数,1是起始位置,2是结束位置不改变原字符串
负参数会转换成0,会根据两个参数的大小,从小截取到大
subString
两个参数,1是起始位置,2是多少个字符,不改变原字符串
负参数,第一个参数+length,第二个参数转换成0,后一个参数比前一个参数小,返回''空字符串
subStr
两个参数,1是起始位置,2是结束位置,不改变原字符串
负参数会+字符串length,后一个参数比前一个参数小,返回''空字符串
slice
是否以s开头,第二个参数吧index作为开头
是否以s结尾,二个参数以index作为结尾
从index开始搜索s,返回boolean
删除前后空格,不影响原数据
trim
返回复制num次的字符串拼接
repeat(num)
复制num位的字符串,不够num位在前面使用s填充
复制糯米位的字符串,不够num位的在后面填充
padEnd
字符串解构为数组
字符串由一个Symbol.iterator方法,因此可以使用for-of遍历
解构
字符串小写
toLowerCase
某些地区转大小写需要使用地区特定的方法
toLocaleLowerCase
字符串大写
toUpperCase
toLocaleUpperCase
返回与exec相同
match
匹配符合正则的索引位置,没有返回-1
search(RegExp)
第一个参数是字符串或正则
第一个参数是字符串,只会替换第一个子字符串,替换所有需要使用正则+g标记
第二个参数可以是字符串或函数
函数必须返回字符串,函数参数有匹配的字符串、开始位置,原始字符串等
replace
使用传入的字符分隔成数组
第二个参数可以限制生成的数组大小
split
按照字母顺序,字符串应该排在字符串参数前头,返回-1
字符串与参数相等返回0
按照字母顺序,字符创排在字符串后头,返回1
localeCompaare()
big
fontSize(size)
fontColor(color)
link(url)
会生成html标签,但是生成的不是语义化的标签因此基本不会再使用了,还有一些其他方法不再列举
html方法
String
包装值类型
isNan
parseFloat
isFinite
有效的URI不能包括某些字符比如空格,因此可以使用一下两个方法进行编码
encodeURI不会编码属于URL的特殊字符比如冒号、斜杠、问号、井号
encodeURI
encodeURIComponent会编码发现的所有非标准字符,就连http:中的冒号也会编码
因此他适用于编码URI中的单独组件、比如?后面的某一段
使用encodeURIComponent比encodeURI更多,因为编码查询字符串比编码基准URI次数更多
encodeURIComponent
decodeURI只能对encodeURI解码
decodeURI
只能对encodeURIComponent解码
decodeURIComponent
这个方法是整个ECMAScript中最强大的方法
他就是一个完整的js解释器
接受一个即将执行的js字符串
通过eval执行的代码,属于该调用所在的上下文,这意味着,定义在包含上下文中的变量可以在eval内部被调用
eval内部声明的变量和方法也可以在外部代码引用
这个方法非常危险,这个方法会对xss利用暴露出很大的攻击面,尤其是解释用户输入的内容时,用户恶意的插入会导致网站崩溃
eval
Global
浏览器将window对象实现为Global对象的代理
全局作用域中声明的变量和函数都成为了window的属性
获取Global对象
window对象
Math中进行的计算比直接在js中实现快得多,因为Math对象计算使用了js引擎更高效的实现和处理指令
对数基数e
Math.E
以10为底的自然对数
Math.LN10
以2为底的自然对数
Math.LN2
以10为底e的对数
Matg.LOG10E
π
Math.PI
2的平方根
Math.SQRT2
1/2的平方根
Math.SQRT1_2
一组数中的最小值
Math.min
Math.max
向上取整
Math.ceil
向下取整
Math.floor
四舍五入
Math.round
返回最接近的单精度浮点数表示
某些精度不高的场合下,可以通过两个浮点数转32位浮点数比较来解决564位浮点数比较不正确的问题
Math.fround
0~1范围内的随机数,包含0不包含1
random
绝对值
abs
x的y次方
平方根
sqrt
立方根
cbrt
sign
返回整数部分
trunc
三角函数
Math
单例内置对象
基本引用类型
param如果是数字,那么会创建一个param长度的空数组
如果param是非数字,会把参数当成元素
new Array(param)
数组字面量
创建数组
就是任何可迭代的结构都能转成数组
map
set
实现了Symbol.iterator的对象,Symbol.iterator一般是一个生成器
把类数字转成数组
Array.from
把一组参数转换成数组
Array.of
字面量初始化数组时,使用一串逗号来创建空位
arr.lengthv===5
for-of、Array.from、解构都能取到空位,且空位值为undefined
map方法取不到空位,空位会被忽略
由于行为不一致,因此避免使用空位,可以使用undefined填充
数组空位
length不是只读属性
改变length可以在末尾添加或删除元素
length属性
Array.isArray
注意Array实际上是在global中的一个类型,在有多个global(意思是有多个全局上下文,比如网页中多个iframe中,就有多个全局上下文)的环境中,有多个版本的Array构造函数,如果把数组从一个框架传给另一个,导致这个数组的构造函数在两个框架中不一样
value instanceof Array
arr.__proto__.constructor == Array
判断原型,缺点是如果普通对象直接换成数组原型,那么判断会不准确
arr.__proto__ == Array.prototype
Object.getProtoTypeOf(arr) == Array.prototype
Array.prototype.isPrototypeOf(arr)
让arr调用最顶级原型Object原型上的toString
Object.prototype.toString.call(arr) === '[Object Array]'
检测是否是数组
返回索引迭代器
keys()
返回元素迭代器
values()
返回索引/值对的迭代器
entries()
迭代器方法
把s填充入startIndex到endIndex
startIndex和endIndex可以忽略,都没有时全部元素填充为s
只有一个startIndex时,从startIndex开始填充到末尾
填充不会超过数组大小,忽略索引相反,忽略索引过高或过低
复制startIndex到endIndex的元素到index的位置,并向后覆盖
没有endIndex,表示从startIndex复制到最后
复制和填充
返回每个元素的等效字符串,再使用逗号拼接成字符串
它会调用每个元素的toLocalString方法,使用逗号连接成字符串
返回数组本身
使用参数连接成字符串
join
转换
接受无限多个参数,添加到数组末尾
返回length
push
删除最后一个元素
返回删除的元素
pop
删除第一项
shift
开头添加任意多个值
unshift
会导致位数不同的数字比较有问题
默认将元素转成字符串再排序
接受一个比较函数
sort
反向排列
reverse
创建一个副本,并把数组参数每一项添加到副本末尾,把非数组直接添加到末尾
返回这个副本
可以定义参数的Symbol.isConcatspreable来强制打平或直接添加到末尾
数组切片
返回start到end 之间的数组副本
数组中间插入元素
从startIndex开始删除length个元素,然后再startIndex开始插入a,b,c...
从index开始向后搜索,执行严格相等
执行严格相等,返回boolean
注意第二个参数,可以制定断言函数内部this的值
断言函数有3个参数,item,index,数组本身
参数同find
forEach
filter
some
every
归并函数接受:上一个归并值,当前项,当前索引,数组本身
第二个参数时初始值,有初始值时,归并函数第一次执行时的第一个参数时initData;没有初始值时,归并函数第一次执行时的第一个参数是数组的第一个元素
reduceRight
Array
提升向原生库传输数据的效率
typed array定型数组
new Map()
传入一个可迭代的对象
需要包含键值对数组,每个键值对数组都会按照迭代顺序插入到新的映射实例中
初始化
添加键值对
返回Map实例,因此可以链式调用
set()
通过键获取值
get()
是否含有某个键
has()
删除键值
delete()
清空Map
clear()
键值对个数
size
map.entries
map可以迭代,因此可以解构成数组
map.keys()
map.values()
map可以使用任何数据类型作为键,可以使用任何数据类型作为值,object只能用string或number作为key
map使用严格相等的标准来检查键的匹配
Map会维护键值对插入的顺序,object不保证键值对的顺序
固定大小的内存,map大约比object多存储50%的键值对
内存占用
相差无几,map快一点,大量插入键值对还是用map更快
插入性能
object更快,尤其使用连续整数作为key的情况下,object可以当成数组,浏览器可以优化内存布局,查询更快
查找速度
object删除属性需要delete obj.xxx;这是一种不优雅的方法,性能也差
map的删除比插入和查找更快
删除
map和object
Map
key不会阻止垃圾回收
但只要key存在,value就不会被垃圾回收
因为key随时会被垃圾回收清理,也因此没有遍历迭代键值对的能力
因为key是弱引用类型,因此不能使用原始值作为key,如果使用原始值,就无法区分初始化时使用的字符串字面量和初始化之后使用的字符串是否是一个相等的字符串
弱映射
可以只能是object或继承自object的类型,是有非对象作为键或报错,值没有限制
原始值可以使用其包装类型作为key
Map任何值都可以做key,WeakMap只能用对象做key
Map有clear方法,WeakMap没有
Map有size属性,WeakMap没有size属性
Map有keys,WeakMap没有
Map有values,WeakMap没有
Map有entries,WeakMap没有
map可以遍历,WeakMap不能遍历
WeakMap和Map
WeakMap
传入可迭代对象
new Set()
add()
set可以使用任何数据类型作为值
set不可重复,验证重复性使用的是严格相等
set会维护插入的顺序
支持解构成数组
entries
Array.from(new Set(arr))
利用Set不可重复的特性
原始值数组的去重
Set
其中的值不是正式引用,不会阻止垃圾回收
原始值可以使用其包装类型作为值
has
add
WeakSet的值只能是对象,Set可以使用任何数据类型作为值
WeakSet没有clear
没有size
没有keys
没有values
没有entries
WeakSet不可迭代
WeakSet和Set
WeakSet
集合引用类型
即可以把有些结构称为可迭代对象,因为他们实现了正式Iterable接口,而且可以通过迭代器Iterator消费
迭代器模式
每次返回一个迭代器对象,这个对象有一个next()方法
false表示没有结束迭代,done:true表示迭代结束,value代表值
表示迭代的钟乳退出需要执行的方法,返回{done:true}
break、continue、return都可以终止循环,并执行return方法
迭代器对象可以实现一个return方法
需要实现Symbol.iterator迭代器工厂函数
迭代器维护着一个指向可迭代对象的引用,着可以组织垃圾回收可迭代对象
生成器能够在一个函数块中暂停和恢复代码,能够实现自定义迭代器和实现协程
箭头函数不能定义生成器
函数名前加*表示它是一个生成器
生成器可以作为默认迭代器
生成器的返回值即生成器对象实现了迭代器,因此可以吧它当成可迭代对象直接for-of使用
中断时函数作用域的状态被保留
yield 关键字退出的生成器处于done:false状态
return xxx;返回的生成器,done:true
yield必须用在生成器函数中,其他位置报错
yield可以返回值和接受值,next()的参数可以传递给yield,第一次next()中的值不会被使用,它代表生成器函数开始执行
yield可以中断生成器,
yield*可以增强yield行为,它可以迭代一个可迭代对象,一次产出一个值,yield*和循环yield一个可迭代对象时等价的
yield*实现递归
yield*
生成器对象有一个return方法用来关闭生成器,return的值会作为终止迭代器对象的值
throw,throw作为错误处理也能终止生成器,但如果迭代器中处理了错误(try,catch处理)那么生成器可以继续向下 执行不会关闭
生成器返回一个生成器对象
迭代器与生成器
1. 对象字面量{}
2. new 构造函数,可以反复创建多个相同结构的对象
创建对象,有两种形式
封装
所有子对象公用的属性和方法,都要放在构造函数的原型对象中
只要觉得父对象继承来的成员不好用,都可以在子对象中重写同名成员或者函数重载(即同名函数参数不同)
多态
面向对象的3个特点:封装、继承、多态
xxx函数中的this指代obj
1. obj.xxx
this指代距离调用时最近的函数作用域或者全局作用域
2. 函数直接执行
哪个子对象调用的方法,this就指代谁
3. 原型上的方法中的this
默认就是window
(function(){...this...})()
arr.forEach(function(){....this....})
4. 匿名函数、回调函数、自执行函数中的this
指代这个元素
5. DOM元素上事假处理函数上的this
Vue实例
6. Vue中的this
当前函数之外最近的作用域中的this
箭头函数的底层,相当于普通函数.bind()绑定了最近作用域的this
注意bind绑定之后,再次bind或者call、apply都不能再次更换this
7. 箭头函数中的this
call,apply可以替换this,并且自动执行这个函数
bind()把函数的this一次性绑定,且不能再次更换
this的八种情况
new Object
对象字面
每个对象都是 Object的实例,继承其toString、toLocalString、valueOf
定义形式
是否可以修改
writable
是否可以配置,即能否删除属性
configurable
属性值
value
可否通过for-in循环返回
enumerable
获取函数
get
设置函数
可以通过defineProperty来定义这三个属性,已经定义configurable为false的,不能通过definProperty更改configurable为true
defineProperties
同时修改多个属性
注意,使用Object.defineProperty和 Object.defineProperties定义的属性,其enumable\\writable\\configurable属性默认都是false
数据属性
Object.getOwnPropertyDescroptors(obj)
返回对象所有属性的描述
获取属性特性
不能在两个对象之间转移获取函数和设置函数
这个函数的执行过程是,使用src对象的get函数返回值,传递给target对象的set函数来设置值
这是属性的浅拷贝,对于对象属性就会复制对象的引用
执行过程中抛出错误,可能会完成部分复制
Object.assign
对象合并
接受两个参数,比较两个参数是否相等
相当于全等比较,但考虑了更多的边界条件
true===1 false
{}==={} false
0===-0 true
+0 === -0 true
Object.is
对象比较
解构同时定义默认值
因为使用ToObject()所以,原始值会转成对象再解构,因此可以解构出许多包装值类型的属性
null和undefined不能解构
解构执行过程中出错,可能会导致部分解构成功,出错位置之后不成功
对象解构
根据参数创建对象并return出来,可以创建多个类似对象
工厂模式
按照惯例构造函数的首字母需要大写
1.在内存中创建一个新对象
2.这个新对象内部的[[Prototype]]特性被赋值为构造函数的prototype属性
执行构造函数内部的代码,给新对象添加属性
3.构造函数内部的this被赋值为这个新对象,即this指向这个新对象
4.如果构造函数返回空对象,那么返回这个对象,否则返回本来应该返回的对象
new 的执行顺序如下
构造函数也是函数,除了调用方式不同
构造函数生成的函数属性,都不相等,new出来的对象,同一个函数属性不是同一个Function对象
其实使用一个function对象就够用了
要把一个函数共享给构造函数产生的所有对象需要原型模式
构造函数的问题
构造函数
function Foo(){ getName=function(){console.log(1)} return this}Foo.getName=function(){console.log(2)}Foo.prototype.getName=function(){console.log(3)}new Foo.getName() ====> new 执行Foo.getName()的结果 ====》2new Foo().getName() ===>new 先执行new Foo() 再执行getName() ===》3
new操作符的规则,遇到小括号就执行第一个小括号左边的new
原型上定义的属性和方法可以被对象继承
每个函数都会创建一个prototype属性,它是通过构造函数创建的对象的原型,它上面的方法和属性都会被生成的对象继承,因此可以直接在原型上定义属性和方法,就能复用属性和方法了
3.构造函数、对象实例、对象原型是3个完全不同的对象
4.实例与构造函数没有直接关系,与原型对象有直接关系
理解原型
判断一个对象是否是另一个对象的原型
isPrototyppeOf()
获取对象的原型
Object.getPrototypeof()
指定obj的对象原型是src
setPrototypeOf会造成性能下降,它会设计所有访问了那些修改过[[prototype]]的对象的代码
使用obj作为原型创建一个新对象
Object.create(obj)
属性是不是实例对象属性,原型链上的属性会返回false
hasOwnProperty(key)
原型方法
首先在兑现本身搜索属性,有就返回,没有就去他的原型上找
再给对象添加一个与原型上同名的属性后,访问该属性就不会去搜索原型链上的属性了,即使给属性赋值null或undef也不行,但delete操作符可以
搜索过程
原型层级
for-in会遍历对象上可枚举的所有属性,无论属性实在对象实例上还是在原型上
单独使用in,判断属性是否在对象实例和原型上;准确说法是判断属性能否被对象访问到
获取可枚举的实例属性
Object.keys()
Object.getOwnPropertyNames
获取实例上的Symbol属性
Object.getOwnPropertySymbols(obj)
in操作符
枚举顺序不确定,取决于环境
for-in和Object.keys
先以升序枚举数字键,再以插入顺序枚举字符串和符号键
Object.getOwnPropertyNames\\Object.getOwnPropertySymbols\\Object.assign
Object.values
Object.entries
迭代
如果不定义constructor,会导致原型链上缺失constructor,如果再以构造函数判断类型就不可能了
如果简单定义constructior:Person,会导致constructor称为可枚举属性,那么constructor会出现在for-in等循环迭代中
1.以字面量替换原型
原型是以指针的形式存储,
对象产生的时候,实例的[[prototype]]属性会在 调用构造函数时自动赋值
如果使用其他对象直接替换原型,那么替换之前产生的对象其prototype指针还会指向原来的原型对象,之后产生的对象实例就会是新的原型对象
这就导致同一个构造函数产生的对象,会有不同的原型方法
原型的动态性
原生引用类型也是使用的原型模式,因此也可以修改原生对象的原型达到共享属性的目的
不推荐使用:因为可能引发命名冲突,比如一个名称在不同浏览器中可能存在,也可能不存在,也可能意外重写原生的方法
如果真要修改,那么创建一个自定义的类继承原生类型
原生的对象原型
其他原型语法
由于原型上存储的都是指针
那么原型属性上的引用属性(即object类型)值的改变会引起所有对象对应属性的改变
原型中的问题
原型模式
创建对象
js中不可能实现,因为函数没有签名
接口继承
每个构造函数都有一个原型对象,原型上有一个构造函数属性指回构造函数,实例上有一个内部指针指向原型
如果原型是另一个类型的实例,那么这个原型本身有一个内部指针指向另一个原型,相应的另一个原型也有一个指针指向另一个构造函数
这样就行成了一条链状的原型链
原型链基本构想
包含引用值时,定义在父类内部的引用属性变成了子类原型上的属性
而引用属性使用的是指针,导致一个实例操作了父类中的内部引用,所有的实例该引用属性都会产生变化
也没有办法在不影响所有对象的情况下,把参数传递给父类的构造函数
原型链继承
在子类的构造函数中调用父类构造函数,使父类中的属性称为子类的一部分
思路
必须在构造函数中定义方法,导致方法不能重用
继承是通过父类构造函数执行继承的,因此也不能访问父类原型上定义的方法
盗用构造函数/经典继承
组合使用原型继承和经典继承
既在子类内部调用父类的构造函数,获取父类构造函数上定义的属性
又把子类的原型替换成父类的实例,获取父类原型上定义的方法
复杂的继承机制
效率问题:父类构造函数会被调用两次
组合继承
以一个对象作为原型创建另一个对象
规范化的原型式继承,第一个参数是作为原型的对象。
第二个参数是给新对象定义额外属性的对象
替代方法:Object.create(obj,{config})
引用值浅拷贝
原型式继承
以一个对象作为原型返回新对象的基础上,再增强这个对象
新对象增强 的属性属于对象实例,不能重用
寄生式继承
由于组合继承需要调用两次父类的构造函数,父类构造函数上的所有属性都会放到子类的原型上,没有必要
所以只要拿到父类的原型,再增强这个原型,赋值给子类的原型就可以了
更高效的组合继承,寄生式组合继承是引用类型继承的最佳模式
同样实现代码复杂
寄生式组合继承
实现继承
类声明class Person{}
类表达式const Person = class{}
类声明式定义不能提升
函数是函数作用域,class是块级作用域
class 与Function定义的不同
类本质上是一个特殊的函数,它也有prototype属性,原型上的constructor指向类本身
类中定义的constructor函数不会被定义为构造函数
由类生成的实例,对实例使用instanceof Class.constructor,返回false
obj instanceOf Class 返回true
类是一等公民,可以传递给函数参数
类的本质
2. 这个新对象的[[prototype]]指针被赋值为构造函数的prototype属性
3. 构造函数内部的this被赋值为这个新对象
4.执行构造函数
5.返回该对象
实例化
每个类都有一个构造函数
不定义构造函数,相当于定义构造函数为空函数
new 操作符会调用构造方法
构造函数默认返回this对象,如果返回的不是this对象,那么new操作符产生的对象与类没有任何关系
类中的构造函数不能直接调用,必须使用new操作符
构造函数内部,为this添加的属性都是实例属性和方法
构造函数之外,key=value定义,也是实例属性
实例属性和方法
在构造方法之外,类块中定义的方法作为原型方法
也可定义访问器,get、set作为原型方法
原型属性和方法
static修饰的方法和属性叫做静态属性/方法
静态方法中的this指向class本身
静态属性和方法
类也可以实现迭代器,可以把类的实例变成可迭代的对象
生成器和迭代器
不仅可以继承类,也可以继承不同构造函数
关键字extends
派生类可以使用super来引用他们的原型
只能在派生类中使用,仅限于实例方法、构造函数、静态方法内部
构造函数中能够使用super()调用父类的构造函数
静态方法中能够使用super调用父类的静态方法
super是定义了构造函数和静态方法的对象的原型
没有定义构造函数,派生类会自动调用super()
注意手动返回一个对象,会使new出来的对象和类没有任何关系
如果派生类定义了构造函数,就必须调用super()或返回一个对象
因为super()调用后返回的实例才会赋值给this
构造函数中,super之前不能使用this
super
js中没有专门的抽象基类
使用new.target可以检测new关键字实例化的是哪一个类,从而阻止对抽象类的实例化
由于实例化的步骤中,调用构造函数之前就已经为对象赋值了原型,因此可以在父类中使用this.fn,直接检测对应的fn方法有没有在子类中实现
抽象基类
然后Person继承C,这样Person上就有了CBA中混合的方法和属性
即C继承B继承A
组合胜过继承,因此很多js框架抛弃了混入转向了组合模式
类的混入
类的继承
类
对象、类和面向对象编程
创建代理
返回对象中的proxy就是代理对象,执行revoke之后就把原始对象和代理对象中断了联系
撤销是不可逆的行为,revoke之后,再次对proxy对象操作会报错
可撤销的代理
行程多层次的代理结构
代理可以继续代理代理
对创建出来的代理对象的操作都能反映到目标对象上,但代理对象和目标对象不是同一个对象,他们在代码执行中的this不同,并由此可能引发问题
代理日期对象,虽然能返回proxy对象,但不能执行任何方法,执行就报错
它定义了js的13个基础操作,这些操作大多数在Object上都有对应操作
这13个基础操作也是代理可以使用的13个捕获器
反射不仅可以使用在代理的捕获器中,单独使用也可以
反射API的返回值,大多是布尔值,表示意图是否操作成功,这是判断操作成功与否的更好办法,比try\\catch好
反射代替操作符
Relect.apply可以更安全的调用函数,因为apply可能被重写
Reflect
反射
所有代理捕获器都有相应的参数,使用这些参数可以重建捕获方法的原始行为
这些原始行为js已经为我们准备好了,就是Reflect中的13个方法
代理和反射的关系
捕获器可以改变所有的基本方法的行为,但是有限制,这些限制就叫做捕获器不变式
例如目标对象有一个不可配置且不可写的数据属性,那么捕获器返回一个与该属性不同的值时会报错
其他不变式自行搜索查询
捕获器不变式
deleteProperty
defineProperty
getOwnPropertyDescriptor
ownKeys
getPrototypeOf
setPrototypeOf
isExtensible
preventExtensions
construct
apply
捕获器与反射的13个方法
属性什么时候被访问都可以在get中获取
跟踪属性访问
有一些属性不想被访问,只要在get中判断key,如果不想被取值,直接返回undefine
隐藏属性
给属性赋值触发set,只要检查value是否符合要求就可以做到
属性验证
apply和construc分别监听函数调用和构造函数new操作,能够拿到参数,再判断参数是否符合要求
函数与构造函数参数验证
对象创建时监听construct,可以把新建好的对象直接使用
对象设置值的时候,可以触发事件等
数据绑定与可观察对象
代理可以做到
代理反射
函数声明会在任何代码执行之前读取声明,并在上下文中生成函数定义
函数声明
只有执行到对应的表达式,上下文中才有对应的函数
函数表达式
箭头函数
Function构造函数
创建函数
箭头函数不能使用arguments
不能使用new.target
不能作为构造函数
箭头函数没有prototype属性
函数是一个对象
因此可以把一个函数名称复制给多个变量,他们都是一个函数
函数的名称是一个指针,指向函数
函数的本质
因为没有验证签名机制所以也就没有函数重载
参数个数、类型不影响函数调用,未传的参数都是undefined
函数不会预先检查函数声明时的参数类型和个数
argumrnt和函数参数名称同步,但和参数名称不是同一个内存,只是有同步机制
箭头函数没有arguments,但可以使用参数收集定义重载
可以通过arguments判断参数输入模拟函数重载
箭头函数没有arguments对象
argumens是一个类数组对象,但不是Array的实例,它反映了所有输入参数
使用=号可以添加默认参数
默认参数也可以是函数的返回值,但要注意作为默认参数的函数只会在函数调用,且没有传对应参数的情况下才会调用
默认参数
参数相当于在函数体内部顶部按顺序赋值
参数是按顺序初始化的,所有后面的参数可以引用前面的参数
参数存在于自己的作用域中,不能引用函数体的作用域
参数作用域
使用...可以把数组扩展到参数
给函数参数传入...params
参数扩展和收集
函数参数
函数声明会在代码执行之前被读取,并添加到上下文中
函数表达式只有执行到对应行,才会有对应的函数
函数声明和函数表达式
可以作为参数传递
可以作为返回值
可以赋值给变量
函数是一等公民
arguments对象所有函数的指针
递归防止函数改名后报错
arguments.callee
arguments
函数作为构造函数使用时,返回被调用的构造函数
作为普通函数调用。返回undefined
new.target
普通函数的this指向调用它的对象
apply第一个参数是this,第二个参数是参数数组或arguments实例
call第一个参数是this,其他参数是擦混敌给函数的参数
不同函数可以使用call、apply来指定调用对象,即this
箭头函数的this,是定义时的上下文
this
引用的时调用当前函数的函数
函数名.caller
caller
函数内部属性
命名参数的个数
函数名.length
函数原型
其中的constructor就是函数本身
函数.prototype
call
使用bind参数作为调用者(上下文)生成一个新函数
一次性绑定,不会执行,也不能再次更换this(再次apply、call、bind都不能再次替换)
bind不仅能够绑定this, 还能按照参数顺序绑定前n个参数
bind
函数属性和方法
使用arguments.callee可以使递归和函数名解耦
命名函数表达式
递归
function outerFunction(){ return innerFunction()}
1.遇到外层函数体,第一个栈帧被推到栈上
2.执行到renturn,需要先计算innerFunc
3.执行到innerFunc的函数体,把第二个栈帧推到栈上
4.innerFunc返回结果
5.值返回outerFunc,再从outerFunc返回
6.栈帧弹出栈
函数内部调用函数的过程
3.引擎发现innerFunc的执行不依赖外部变量,且innerFunc的返回就是outerFunc的返回,那么直接把outerFunc的栈帧弹出也没有问题
4.弹出outerFunc的栈帧
5.执行到innerFunc的函数体,栈帧推到栈上
6.计算innerFunc,返回值
7.弹出innerFunc的栈帧
优化后的过程
严格模式下执行
外部函数的返回值是内部函数的调用
尾调用函数返回后不需要执行额外的逻辑
为调用函数不是引用外部函数作用域中自由变量的闭包
尾调优化的条件
尾调用优化
闭包就是引用了另一个作用域中变量的函数
外部参数被一个函数所引用,如果函数不被释放,那么这个参数所在的上下文也不会被释放
闭包引起内存泄露
而且ie9之前元素使用引用计数方式回收内存,导致泄露
ie9之前,引用元素,元素再引用元素或元素的属性,会导致循环引用
内存泄露
1.构造函数
2.静态私有变量
使用字面量单例模式集合闭包封装私有变量
也可以不使用字面量,改用一个类的实例,也能对类的实例进行扩展
3.模块模式
包装私有变量
函数
以回调的形式写异步,如果异步中还有异步操作就会变成回调地狱,难以维护
以往的异步
pending
resolved、fulfiled
rejected
状态一旦落定就是不可改变的、不可逆的
状态是不能被js检测的,不能被外部代码修改的,这是为了避免以同步方式处理promise
promise状态机
初始化promise的异步行为
控制promise状态的最终转换
执行器函数是同步执行的,因为这是一个初始化程序
promise内部的函数叫做执行器函数
promise实例化
实例化一个已经解决的promise
这是一个幂等方法
可以吧任何值都转成promise
Promise.resolve()
实例化一个拒绝的promise,并抛出一个异步错误
trycatch是同步代码,异步错误会在同步代码执行完再执行,所以捕获不到
异步错误不能被try,catch捕获,只能通过拒绝处理程序捕获
Promise.reject()
不管是解决还是拒绝,函数的返回值都会被Promise.resolve包装成promise返回
.then
给promie添加拒绝处理程序
.catch
在决绝和解决状态都会执行,但finally无法知道状态是解决还是拒绝
没有返回值时,表现为父期约的传递
返回待定期约或抛出错误、返回拒绝期约,则返回相应的期约
.finally
以上方法由于都返回一个promise,所以都可以链式调用
由于promise可以有任意多个处理程序,所以他链式调用可以构建有向非循环图的结构,也就是二叉树
所有promise都解决后再解决
解决值是所有期约解决值的数组
有一个拒绝则.all拒绝,拒绝理由就是第一个拒绝理由
.all
一组期约中最先解决或拒绝的期约镜像
.race
进度监控
1.reject
2.race
promise取消
promise
为了解决利用异步结构组织代码的问题
异步函数的返回会被Promise.resolve包装成promise对象
异步函数始终返回promise对象
async用于声明异步函数
async
异步函数不会马上完成任务,需要一种暂停和恢复执行的能力
await可以暂停异步函数代码执行,等待promise解决
必须在async函数中使用
await
例子1
例子2
停止会恢复执行顺序
1.实现sleep
异步函数使用
异步编程
答案
var add=function(x){ var sum = 1; var fun=function(x){ sum = sum+x return fun } fun.toString=function(){ return sum } return fun}alert(add(1)(2)(3))console.log(add(1)(2)(3))
使用原生的call模拟实现bind
闭包题目
js基础/es6
表示浏览器实例
网页中定义的所有对象、变量、函数都以window作为其global对象
通过var声明的所有全局变量和函数都会成为window对象的属性和方法
最上层窗口
top
父窗口
parent
window本身
self
哪个窗口打开了此窗口
opener
窗口距离屏幕左侧的位置
screenLeft
窗口距离屏幕顶部的位置
screenTop
y以浏览器而定可能被禁用
窗口移动到坐标
窗口移动x、y距离
css像素参考像素是像素密度为 96dpi 且与阅读器的距离为一臂长的设备上一个像素的视角。 因此,对于 28 英寸的标称臂长,视角约为 0.0213 度。
像素比
innerWidth
innerHeight
outerWidth
outerHeight
窗口大小
文档相对于视口滚动距离纵轴
scrollX/pageXoffset
scrollY/pageYoffset
xy轴上滚动距离
滚动到xy坐标
窗口位置
打开的url
会在这个窗口打开这个url
_self
_parent
_top
_blank
目标窗口名称
新窗口的配置,比如最大化、宽、高、是否显示状态栏、工具栏等
特性字符串
新打开的窗口是否在浏览器历史记录中替代当前加载页面
返回新窗口的window对象,可以基于此对象操作新窗口的大小、位置
打开窗口
窗口
多少毫秒以后把任务添加到任务队列之中
如果队列中没有任务就立即执行,如果有任务会在已有任务完成之后再执行,因此毫秒数是不准的
const timeoutId = seTimeout
clearTimeout(timeoutId)
每个xx毫秒执行一次代码
const intervalId = setInterval
clearInterval(intervalId)
定时器
alert、confirm、prompt都是同步模态框
提示信息
alert
确认信息
confirm
带有提示输入框的弹出窗口
prompt
我在浏览器没成功调用过find
查找对话框
find
打印对话框
他们在显示的时候,代码会停止执行,在他们消失之后代码才会回复执行
同步模态框
系统对话框
window.location == location
document.location==location
location对象既是window的属性也是document的属性
#号后面的散列值
hash
f服务器名+端口号
host
服务器名
hostname
端口号
port
完整的url
href
查询参数,以?号开头
search
协议通常是http或https
protocol
路径
pathname
url的源地址
origin
查询字符串带有?的字符串,难以直接利用,需要做转换
接受一个查询字符串作为构造函数参数
new 出来的对象暴露了get、set、delete,toString方法,能够方便的操作查询字符串
URlSearchParams
查询字符串
立即启用导航到url
assign(url)
会执行和assign(url)同样的操作
window.location = url
会执行和assign(url)同样的操作,修改href是最常用的
location.href = url
以上修改方法也能用于修改hash、search等属性,修改后都会在浏览器历史记录中增加相应的记录,并且页面会重新加载
重新加载页面
reload
新页面替换当前页面,不会增加浏览器历史记录,也就无法回档之前的页面(回退按钮灰了)
操作地址
Location对象
是否开启cookie
cookieEnabled
Gb单位的内存容量
deviceMemory
cpu核心数量
hardwareConcurrency
浏览器主语言
language
浏览器偏好语言数组
languages
是否联网
onLine
系统平台
platform
安装的插件
可以用来确定浏览器类型和版本
用户代理字符串
userAgent
都可以使用plugins数组中,对象的name属性检查插件名字
ie10之后,以及其他浏览器
注意ActiveXObject类在10之后就没有了,其他浏览器也没有,所以可以先检测名称,再检测ActiveXObject是否报错
ie10之前,只能使用ActiveXObject(pluginId),实例化一个ActiveXObject能否成功来判断有没有安装对应插件
检测插件
为某个协议类型注册一个固定处理的应用程序
为mailto协议注册一个处理程序,邮件可以通过指定的url打开
registerProtocolHandler(协议, url, appname)
注册处理程序
Navigator
屏幕显示器的信息
像素宽
像素高
颜色位数
等
当前窗口首次使用以来的用户导航历史记录
为了安全考虑,他不会暴露具体的url,但它可以在不知道实际url的基础上进行前进和后退
num>0前进num页
num<0后退num页
go(num)
后退num页
back(num)
前进num页
forward(num)
当前历史记录中有多少个页面
length
把状态信息推送到历史记录中,浏览器修改url,但页面不会重绘,不会向服务器发送请求
第一个参数应该包含初始化页面状态所必须的信息
pushState
替换当前页面,不会产生新的记录,只会覆盖当前记录
replaceState
history
BOM
标签,HTMLElement,继承了Element
元素名称
nodeName==tagName
getAttribute
setAttribute
removeAttribute
创建元素
document.createElement
1
ELEMENT_NODE
元素数据类型
2
ATTRIBUTE_NODE
文本节点
文本
nodeVlaue
文本与nodeValue相同
data
向节点末尾添加文本
appendData
从offset删除count个字符
在offset位置插入text
用text替换从位置offset到offset+count的文本
在offset位置把当前文本拆分成两个
splitText(offset)
提取从offset到offset+count的文本
document.createTextNode
3
TEXT_NODE
xml中的CDATA区块
4
CDATA_SECTION_NODE
ENTITY_REFERENCE_NODE
ENTITY_NODE
PROCESSION_INSTRUCTION_NODE
注释类型
8
COMMENT_NODE
文档节点类型,文档对象是HTMLDocument实例(HTMLDocument继承Document)表示整个HTML页面
表示HTML节点
documentElement
表示body元素
body
文档类型
doctype
title
页面url
URL
可以设置,但只能放松不能收紧
例如子域名为p2p.wrox.com,可以设置为wrox. com
domain
连接到当前页面的那个页面的url
referrer
文档中所有带有name的a元素
anchors
所有form元素
forms
所有img元素
images
所有带有href的a元素
links
9
DOCUMENT_NODE
文档类型节<!DOCTYPE HTML>
10
DOCUMENT_TYPE_NODE
没有对应元素,他相当于一个元素仓库
把多个元素插入文档时,一个一个插入导致页面重绘,那么可以先把元素放入fragment中,再把fragment放入document中
document.createDocumentFragment
11
DOCUMENT_FRAGMENT_NODE
NOTATION_NODE
Node类型
类数组对象
parentNode
previousSibling
nextSibling
每个node对象都有
item(index)
childNodes
firstNode
lastNode
hasChildNodes
ownerDocument
节点关系
appendChild
把newNode插入到targetNode前面
由父节点调用次方法
要插入的节点和要替换的节点
removeChild
是否深复制,整个节点和其整个子dom树
cloneNode(boolean)
处理文档子树中的文本节点,
发现空文本节点则删除,如果两个同胞节点是相邻的,则合并为一个文本节点
节点操作
document.getElemetnById
getElementByTagName
节点定位
在Dom被修改后可以异步的执行回调,使用它可以观察整个文档或者Dom树的一部分,还可以观察属性、子节点、文本或任意组合变化
callback接受一个MutationRecord实例的数组,包含实例发生了什么变化,哪一部分收到了影响
const observer = new MutationObserver(callback)
使用实例化出来的observer来观察某个node节点,根绝options来确定观察那些属性
这个方法可以终止执行回调,observer对元素是弱引用,不会妨碍垃圾回收
会停止观察的所有目标
不会结束observer的生命,可以重新使用observer.observe()来关联到新的目标节点
observer.disconnect()
创建observer
基本用法
连续修改会生成多个MutationRecord,下次执行回调就会收到包含所有这些实例的数组,顺序就是变化时间发生的顺序
被修改影响的目标节点
target
表示变化的类型,attributes,characterData、childList
oldValue
被修改的属性名称
attributeName
attributeNamespace
childList类型的变化,返回变化中添加节点的NodeList
addedNodes
childList类型的变化,返回删除的节点NodeList
removeNodes
childList类型的变化,返回变化节点的前一个节点
childList类型的变化,返回变化节点的后一个节点
MutationRecord
控制对目标节点的观察范围,必须有一个是attribute、characterData、childList必须有一个是true
布尔值,是否观察目标节点的子节点,默认为false
subtree
布尔值,是否观察目标节点的属性变化,默认为false
attributes
字符串数组,表示要观察那些属性
为true会把attributes也置成true
attributeFilter
布尔值,表示MutationRecord是否记录变化之前的属性值,默认为false
attributeOldValue
布尔值,表示修改字符数据是否触发变化事件,默认为false
characterData
布尔值,表示MutationRecord是否记录变化之前的字符数据,默认为false
为true会把characterData也置成true
characterDataOldValue
布尔值,表示修改目标节点的子节点是否触发变化事件,默认为false
childList
MutationObserverInit
情况mutationRecord记录队列,并返回其中手游的MutationRecord
observer.takeRecords
MutationObserver拥有对要观察对象的弱引用,不会妨碍垃圾回收机制回收目标节点
目标节点拥有对MutationObserver的强引用,目标节点从dom中被移除,随后被垃圾回收,则关联的MutationObserver也会被垃圾回收
MutationObserver与目标节点之间的引用关系
记录队列中的每个MutationRecord实例至少包含对已有节点的一个引用,如果是childList类型则会包含多个节点的引用
记录队列和回调函数默认行为是耗尽这个队列,处理每个MutationRecord,然后让它们超出作用域并被垃圾回收
有时候需要保存MutationRecord,如果保存这些实例,那么也就保存了这些引用的节点,因此会妨碍垃圾回收这些节点(注意是MutationRecord而非MutationObserver)。最好的办法是,记录某些有用信息然后排期MutationRecord
MutationRecord的引用
性能、内存与垃圾回收
MutationObserver
querySelector
querySelectorAll
元素是否匹配选择符
matches
getElementByClassName
节点查询
子元素数量
childElementCount
第一个Element类型的子元素
firstElementChild
最后一个Element类型的子元素
lastElementChild
前一个Element类型的同胞
previousElementSibling
后一个Element类型的同胞
nextElementSibling
元素遍历
getElementsByClassName
向类名列表中添加字符串
判断指定的字符串是否存在
contains
删除制定的字符串
remove
如果类名列表中已经存在制定的value就删除,不存在则添加
toggle
classList
css类扩展
保护眼当前拥有焦点的DOM元素
document.activeElement
焦点管理
文档正在加载
loading
文档加载完成
complete
readyState
标准模式渲染
CSS1Compat
混杂模式渲染
BackCompat
compatMode
指向head元素,与body对应
head
HTMLDocument扩展
data-前缀标识自定义属性
自定义数据属性
返回元素所有后代的HTML字符串
赋值会覆盖所有子元素
innerHTML
返回元素本身和元素后代的的字符串
赋值会覆盖本身以及后代元素
outerHTML
把text或html字符串插入的index
这里的begin和after指的是当前元素的开始标记和结束标记的之前或之后
beforebegin
afterbegin
beforeend
afterend
index有以下值
insertAdjacentHTML(index,text)
同上
inertAdjacentText
布尔值,true窗口滚动后元素的顶部与视口顶部对齐
布尔值,tfalse窗口滚动后元素的底部与视口底部对齐
alignToTop
动画smooth、auto
behavior
定义垂直方向的对齐start,center,end,nearest
水平方向对齐,start,center,end,nearest
scrollIntoViewOptions
scrollIntoView(alignToTop或者scrollIntoViewOption)
插入标记
只包含Element类型的子节点
children
判断一个元素是否是另一个元素的后代
确定节点关系
compareDocumentPosition
返回后代文本节点
赋值会覆盖子节点
innerText
赋值会覆盖本身及其子节点
outerText
未被标准化的专有扩展
元素对象具有style属性,能够返回行内样式
直接赋值能够更改行内样式
包含style属性的中的css代码
cssText
css属性数量
length
如果属性使用了!important返回important
getPropertyPriority(propertyName)
返回属性propertyName的字符串值
getPropertyValue(propertyname)
删除css属性
removeProperty(propertyName)
设置css属性
由于样式会互相覆盖,因此提供一个api返回计算完全之后的生效样式
计算样式
返回link或style元素定义的演示表
只读属性,不可覆盖
返回CssRuleList
document.styleSheets
表示样式表中的一条规则
返回整条规则的文本
如果规则被其他规则包含,指向包含规则
parentRule
包含当前规则的样式表
parentStyleSheet
选择符
selectorText
规则类型,始终为1
Css规则CSSRule
把规则插入到第一条
sheet.insertRule(\"body {background-color:silver}\
使用styleSheets中的某个sheet
创建规则
删除第index条规则
sheet.deleteRule(index)
删除规则
样式表
元素在垂直方向上占用的像素尺寸,包括他的高度、水平滚动条的高度、上下边框的高度
offsetHeight
元素做边框外侧距离包含元素左边框内侧的像素数
offsetLeft和offsetTop是相对于包含元素的,包含元素保存在offsetParent中
offsetLeft
元素上边框外侧距离包含元素上边框内侧的像素数
offsetTop
元素在水平方向上占用的像素尺寸
offsetWidth
偏移尺寸
包含元素内容及其内边距所占用的宽度
有滚动条时,是视口的宽度,没有滚动条时和scrollWIdth一致
clientWidth
clientHeight
元素内部空间,不含滚动条空间、不含border、不含margin
客户端尺寸
没有滚动条时元素内容总高度
在没有滚动条时与clientHeight一致,有滚动条时,他是实际高度
scrollHeight
内容左侧隐藏的像素数
修改这个属性可以改变滚动条位置
scrollLeft
内容顶部隐藏的像素数
scrollTop
没有滚动条时元素内容总宽度
scrollWidth
滚动尺寸
元素左侧距离视口的像素
left
元素顶部距离视口的像素
元素右侧距离左侧视口的距离
right
元素下侧距离视口顶部的距离
bottom
width
height
返回DOMRECT对象
getBoundClientRect()
确定元素尺寸
元素尺寸
样式相关API
作为遍历根节点的节点
root
所有节点
NodeFilter.SHOW_ALL
元素节点
NodeFilter.SHOW_ELEMENT
属性节点,DOM实际上用不到
NodeFilter.SHOW_ATTRIBUTE
NodeFilter.SHOW_TEXT
注释节点
NodeFilter.SHOW_COMMENT
文档节点
NodeFilter.SHOW_DOCUMENT
文档类型节点
NodeFilter.SHOW_DOCUMENT_TYPE
CData区块节点,以下均不是html用的
NodeFilter.SHOW_CDATA_SECTION
实体节点
处理指令节点
Nodefilter.SHOW_ORICESSING_INSERUCTION
文档片段节点
NodeFilter.SHOW_DOCUMENT_FRAGMENT
记号节点
NodeFilter.SHOW_NOTATION
数值代码,表示应该访问哪些节点
WhatToShow
NodeFilter对象需要实现一个acceptNode(node){ return NodeFilter.FILTER_ACCEPT}
返回NodeFilter.FILTER_ACCEPT表示应该访问
NodeFilter.FILTER_SKIP表示跳过访问
一个NodeFilter对象或者过滤函数
过滤函数需要实现一个函数,接受node参数,返回NodeFilter.FILTER_ACCEPT或者NodeFilter.FILTER_SKIP
布尔值,表示是否扩展实体引用,html中没有效果,可以穿false
entityRefrenceExpansion
下一个节点
nextNode
上一个节点
previousNode
createNodeIterator返回一个iterator,它含有2个方法
深度优先遍历
NodeIterator
当前节点的父节点
parenNode
当前节点的第一个子节点
firstChild
当前节点的最后一个子节点
lastChild
当前节点的下一个节点
当前节点的上一个节点
他与document.createNodeIterator的不同之处在于TreeWalter可以通过api进行漫游,不只是可以下一个上一个还可以直接访问子节点或父节点
createTreeWalker返回一个treeIterator,他包含5个方法
TreeWalker
范围起点所在的节点,选区中第一个节点的父节点
startContainer
范围起点在startContainer中的偏移量。如果startContainer是文本几点,那么startOffset表示跳过的字符数,否则表示范围中第一个节点的索引
startOffset
范围终点所在的节点,选区最后一个节点的父节点
endContainer
范围终点在endContainer中的偏移量。和startOffset的含义相同
endOffset
以startContainer和endContainer为后代的最深节点,即他们共有的最接近的祖先节点
commonAncestorContainer
const range = document.createRange()
选择节点及其子节点
范围起点调整到refNode之前
setStartBefore(refNode)
范围起点调整到refNode之后
setStartAfter(refNode)
范围终点调整到refNode之前
setEndBefore(refNode)
范围终点调整到refNode之后
setEndAfter(refNode)
range.selectNode()
选择节点的子节点
调整范围同上
range.selectNodeContents()
简单选择
范围开始是refNode的offset个节点
范围结束是refNode的第offset个节点
这种方法可以跨节点进行选择,也就是可以只包含一些元素的结束标签或某些元素的开始标签
在发现选区中缺少一个开始标签/结束标签时,会在后台动态补上这个标签
复杂选择
从文档中删除选区,由于后台会补充缺失的标签,所以期DOM结构还完好的
range.deleteContents
从文档中删除选区,它会额外返回已经删除的文档片段,然后可以对选取进行额外操作,例如插入到别的位置
rang.extractContents
在范围开始的地方插入html
range.insertNode
使用参数中的html包含选区
range.surroundContents
折叠,即范围中不包含任何节点
true,折叠到起点
false,折叠刀终点
range.collapse(boolean)
是否折叠
选择范围之后判断是否折叠,可判断两个节点是否相邻
range.collapsed()
参与判断的另一个范围
range
比较两个起点
Range.START_TO_START
比较第一个范围的起点和第二个范围的终点
Range.STATRT_TO_END
比较第两个范围的终点
Range.END_TO_END
比较第一个范围的终点和第二个方位的起点
Range.END_TO_START
option可以是以下值
第一个在第二个之前返回-1
边界相同返回0
第一个边界在第二个之后返回1
返回-1, 0 , 1
range.compareBoundaryPoints(range,option)
复制范围
range.cloneRange()
range.detach()
range = null
这两步是最合理的结束使用范围的方式
解除范围对文档的引用
操作
Range
DOM遍历
DOM
从最具体的元素开始触发,然后向上传播到文档
事件冒泡
从不具体的节点出发,最具体的节点最后接受到事件
实际是为了在事件到达实际的目标元素前拦截事件
事件捕获
最先发生
为提前拦截事件提供了可能
到达目标
DOM事件流
其中的html语法字符需要转义,例如\"\" < > &
this指向元素
在html上以属性的形式添加能够执行的js代码
把函数赋值给DOM元素的一个事件处理程序属性
参数:事件名,事件处理函数,在什么阶段调用处理程序,true,表示在捕获阶段调用,false(默认值)表示在冒泡阶段调用
大多数时候使用默认值在冒泡阶段调用,因为跨浏览器兼容性好,需要拦截就改为true,在捕获阶段调用
以同样的参数删除程序处理程序
removeEventListener()
定义事件
事件是否冒泡
bubbles
是否可以取消事件默认行为
cancelable
当前事件处理程序所在的元素
currentTarget
true表示已经调用preventDefault()方法
defaultPrevented
其他相关信息
detail
调用事件处理程序的阶段1代表捕获阶段2代表到达目标3代表冒泡阶段
eventPhase
取消事件默认行为,只有cancelable为true才能调用
preventDefault()
取消后续事件的捕获和冒泡,并阻止调用任何后续处理程序
一个事件可能有多个事件处理程序,这个方法会阻止剩余的其他时间处理程序的执行
stopImmediatePropagation()
用于取消后续事件捕获或事件冒泡,只有bubbles为true才能调用
stopPropagation()
事件目标
true表示事件由浏览器生成,false表示事件由js代码创建
trusted
事件类型
与事件相关的抽象视图,等于事件发生的window对象
view
event对象通用属性
废弃,不要使用
被鼠标或键盘激活
DOMActivate
页面加载完成
图片加载完成,img元素可以触发这个事件表示图片加载完成
load
页面完全卸载
可以在页面完全卸载后清理一下内存,放置内存泄漏
unload
页面加载完成前被用户提前终止
abort
js报错
error
文本框被选贼一个或多个字符
select
window被缩放
使用时防止多次触发导致的过多计算
resize
滚动带有滚动条的元素时,在元素上触发
scroll
用户界面事件
元素失去焦点,不冒泡
blur
获得焦点,不冒泡
focus
元素获得焦点,focus的冒泡版
focusin
元素失去焦点,blur的冒泡版本
focusout
焦点事件
鼠标单机或者键盘回车触发
click
双击触发
dbclick
按下任意鼠标键触发
mousedown
鼠标从元素外部移到元素内部触发,不冒泡,鼠标经过后代元素不触发
mouseenter
鼠标从元素内部移动到外部触发,不冒泡,经过后代元素不触发
mouseleave
广光标在元素上移动时反复出发
mousemove
从一个元素移动到另一个元素触发,移动到的元素可以是原始元素的外部元素, 也可以是原始元素的子元素
mouseout
把鼠标从元素外部移动到元素内部触发
mouseover
释放鼠标键触发
mouseup
mouseDown
mouseUp
dblclick
触发顺序
clientX
clientY
客户端坐标
pageX
pageY
页面坐标
screenX
screenY
屏幕坐标
shift按下时为true
shiftKey
alt按下时为true
altKey
meta按下时为true
mac上的commond键,window上的 windows键
metaKey
修饰键
主要目标是获得光标的元素
相关元素是失去光标的元素
主要目标是失去光标的元素
相关元素是获得光标的元素
relatedTarget
相关元素
event上的button属性
主键
中键
副键
表示按下的是哪个键
鼠标按键
mousewheel
向前滚动
+120
向后滚动
-120
event属性wheeldata
滚轮事件
鼠标事件
按下键盘触发,持续按住持续触发
keydown
按下键并产生字符时触发,持续按住重复触发,更推荐textInput
keypress
释放按键触发
keyup
文本插入到文本框之前触发
textInput只在可编辑区域上触发,keypress在可获得焦点的元素触发
textInput在有新字符插入时触发,keypress对任何可能影响文本的按键触发(包括退格键)
与keypress的区别
textInput
event对象保存一个keyCode叫做键码
对于数字和字母,keyCode的值与小写字母和数字的ASCII一致
键码keyCode
对于可以产生字符的按键,会有一个charCode
keypress事件发生时,能影响屏幕上文本的按键
值就是对应按键的键码,不是字符的为0
字符码charCode
非字符时是键名(如Shift)
key
字符键时是ASCII码
非字符键是null
char
键码和字符码
键盘事件
显示上下文菜单的事件
window上是右击,mac上是ctrl+单击
contextmenu
页面卸载之前触发,可以用来阻止页面被卸载
beforeUnload
DOM数构建完成时触发,不会等待图片、就是脚本、css文件的加载
DOMContentLoaded
尚未初始化
uninitialized
正在加载数据
加载完数据
loaded
可以教会,但尚未加载完成
interactive
对象加载完成
提供文档或元素的加载状态信息
readystateChange
firefox和opera提供的一个往返缓存功能,可以记住页面前进后退的状态,基本上是记住了整个页面
页面显示时触发,无论是否来自往返缓存
event上存在persisted属性,true表示来自往返缓存
pageShow
页面卸载后,在unload之前触发,无论是否来自往返缓存
pageHide
pageHide、pageShow
在url散列值变化时触发
hashchange
HTML事件
注意是window上的属性不是event上的
垂直模式
左转水平模式,主屏幕键在右侧
90
右转水平模式,主屏幕键在左侧
-90
window.orientation
orientationchange
x轴,从设备左侧到右侧
y轴,从设备底部到上部
z轴,从设备背面到正面
坐标系
围绕z轴旋转时,y轴的度数
alpha
围绕x轴旋转时,z轴的度数
beta
围绕y轴旋转时,z轴的度数
gamma
表示设备是否返回绝对值
absolute
表示设备的指南针是否正确校准
compassCalibrated
event上的属性
deviceorientation
提示设备正在移动,而不是仅仅改变了朝向
包含xyz属性,反应不考虑重力情况下各个维度的加速信息
acceleration
包含xyz属性,反应各个维度的加速信息,包含z轴自然重力加速
accelerationIncludingGravity
毫秒,距离下次触发devicemotion事件的时间
interval
包含alpha、beta、gamma表示设备朝向
ratationRate
event属性
devicemotion
设备事件
一个手指放在屏幕上
touchstart
手指在屏幕上滑动
touchmove
手指从屏幕上离开
touchend
系统特定值跟踪触摸
touchcancel
视口坐标
事件的目标
当前屏幕上 的每个触点
touches
特定于事件目标的触点
targetTouches
自上次用户动作之后变化的触点
changedTouches
触摸事件
一个手指已经在屏幕上,另一个手指放到屏幕上时触发
gesturestart
任何一个手指在屏幕上位置发生变化触发
gesturechange
其中一个手指离开屏幕时触发
gestureend
手势事件
页面中事件处理程序的数量与页面整体性能直接相关
每个函数都是一个对象,都占用内存空间,对象越多性能越差
内存与性能
事件委托利用事件冒泡,可以只使用一个事件处理程序来管理一种类型的事件
事件委托
事件
一般屏幕的刷新频率为60hz,即1秒刷新60次
实现平滑动画的重绘间隔为1000毫秒/60=16.6,约等于17毫秒
能够实现动画
不能保证时间精度,他们只是把回调任务在n毫秒之后放入任务队列,不能保证执行时间
setTimeout和setInterval
参数是一个回调函数,回调函数接受一个时间戳作为参数,说明被调用的时刻
最大的优势是由系统来决定回调函数的执行时机,重绘、刷新之前自动调用这个回调方法,因此不用制定执行时间
若你想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用window.requestAnimationFrame()
优化:面处理未激活的状态下,该页面的屏幕刷新任务也会被系统暂停,因此跟着系统步伐走的requestAnimationFrame也会停止渲染,当页面被激活时,动画就从上次停留的地方继续执行,有效节省了CPU开销。
const id = requestAnimationFrame(callback(timestamp))
通过id取消重绘任务
cancleAnimationFrame(ID)
<canvas width='500px' height='500px'></canvas>
注意宽高不能用css来定义
canvas标签
const element = document.getElementById('xx');当然也可以用其他方法
第一步,获取canvas标签
const ctx = element.getContext('2d')
第二步获取上下文
初始化画布
填充矩形
描边矩形
清理矩形
矩形
ctx.beginPath()
开始建立路径
设置起点,如果两次路径中间没有重新moveTo,那么两次路径会被连接到一起,设置了moveTo,那么就是两个单独的路径
闭合路径。结束的点位会链接到开始的点,形成闭合图形,这个方法不一定要执行,需要闭合就调用
closePath()
直线
画圆弧
开始弧度是从x轴正方向开始,默认方向是顺时针
切线圆弧
绘制的线就是从起点到两个切点之间的线
产生的线是红色线,折线直角处是x1,y1, 蓝色线最下方是x2,y2(不是红线与蓝线交界处)
二次贝塞尔曲线
三次贝塞尔曲线
TODO:贝塞尔曲线相关知识点
向路径集合中添加子路径
troke()
fill()
显示路径
描边样式
strokeStyle
填充样式
fillStyle
文字样式
'bold 15px arial'
font
文字基线
字母基线
alphabetic
悬挂基线对齐
hanging
居中
middle
表意基线对齐
ideographic
textBaseline
文字对齐方式
start和end的意思是根据html元素的dir属性(ltr从左到右,rtl从右向左)来定义对齐方式,start就是开始的方向
start
end
textAlign
线宽
lineWidth
线条端点形状
butt平头
round圆头
square出方头
lineCap
线条交点形状
round圆转
bevel取平
miter出尖
lineJoin
样式设置
如果文字宽度大于maxWidth,那么文字会压缩以适应最大宽度
文字周围会有一个描边
获取text文字的信息,例如宽度
measureText(text)
保存上下文对象的属性,比如描边颜色、填充颜色,线宽,线条样式,线条交叉样式等
可以save多次,然后restore会一次回退到相应的状态
save()
restore()
状态管理
围绕原点图像选择angle弧度
rotate(angle)
缩放,x乘scalex,y周乘scley
scale(scalex.scaleY)
设置原点坐标
变换
把一个图片绘制到x,y坐标上,并缩放成对应的widht,height
9个参数的重载
截取img图片从imgX,imgY坐标开始imgW宽imgH高的区域
放置到画布的canvasX,canvasY位置,canvasW宽,canvasH高的区域中
导图图片类型,例如img/png
图片质量
获取图像,canvas可以直接导出图片
图像绘制
阴影颜色
shadowColor
阴影x坐标偏移量
shadowOffsetX
阴影y坐标偏移量
shadowOffsetY
阴影模糊量,默认为0,表示不模糊
shadowBlur
阴影
线性渐变
需要吧gradient赋值给fillStyle或者strokeStyle来应用
注意渐变的坐标和绘制的图形坐标需要配合,否则可能只能显示一部分渐变,或完全不显示
制定渐变色标
range,是0~1之间的值,表示什么位置,0是第一种颜色,1是最后一个颜色
color是颜色
径向渐变
参数是两个圆心的坐标和半径
同样使用addColorStop来添加颜色指标
同样注意渐变的坐标需要和图形的坐标配合
渐变
坐标以及宽度和高度
可以获取一个ImageData实例,包含width,height,data三个属性,其中data是图像原始像素信息的数组
每个像素在data中都由4个值表示,分别代表红绿蓝以及透明度,换句话说,第一个像素的信息包含在第0到第3个值中
灰阶过滤器
图像数据
所有绘制内容的透明度,默认为0
globalAlpha
控制图像相交时的行为
默认值,新图形在原有图形上面
source-over
新图形只绘制与原有图形重叠的部分,画布上其余部分全部透明
source-in
新图形只绘制与原有图形不重叠的部分,其余部分全部透明
source-out
只绘制出与原有图形重叠的部分,其余图形不受影响
source-atop
新图形在原有图形下面,重叠部分只有原图形透明像素下的部分可见
destination-over
新图形在原有图形下面,画布只剩下重叠部分,其余部分完全透明
destination-in
新图形与原有图形重叠部分完全透明,原图形其余部分不受影响
destination-out
新图形在原有图形下面,原有图形与新图形不重叠部分完全透明
destination-atop
新图形与原有图形重叠部分像素值相加,使该部分变亮
lighter
新图形奖完全擦除并取代原有图形
copy
新图形与原有图形重叠部分的像素执行异或运算
xor
globalCompositeOperation
合成
TODO:点击canvas上的图形时,如何判断点中了(点击位置是否在某些图形中)
TODO:canvas手写扇形图
canvas
动画和canvas
form.submit
表单提交之后禁止提交按钮
通过onSbumit事件处理程序取消之后的表单提交
表单重复提交
提交表单
form.reset
重置表单
获取表单中的字段集合
form.elements
使用索引获取字段
form.elements[index]
使用name获取字段
form.elements[name]
form[name]
表单字段
disabled
指针,指向表单字段所属的表单,这个属性是只读的
form
数值,表示这个字段在按tab时的切换顺序
tabIndex
表单字段属性
表单元素有一个autofocus属性,可以自动为带有该属性的元素设置焦点<imput type='text' autofocus>
表单字段方法
change
字段公共事件
文本框宽度
最多输入多少个字符
maxlength
文本宽度
cols
初始值需要放在标签中间作为子元素
textarea
选择所有文本
element.select
选择部分文本
select事件
element.selectionStart
element.selectionEnd
取得选中文本
选择文本
keypress事件结合event.preventDefault()
注意屏蔽时可能屏蔽掉赋值粘贴和设计ctrl键的其他功能,所以需要判断event.ctrlKey是否为true
屏蔽字符
before事件在safari、chrome、firefox中只会在显示文本框上下文菜单时触发,ie会在copy等事件之前触发
beforecopy
beforecut
cut
beforepaste
paste
IE
window.clipboardData
其他,只会在剪贴板事件期间访问剪贴板
event.clipboardData
剪贴板数据
clipboardData.getData('type')
剪贴板方法
剪贴板
输入过滤
文本框
type='email'
type='url'
输入必须符合正则
parttern=\"\\d+\"
验证字段是否有效,如果再表单上使用可以验证整个表单的所有值是否有效
element.checkValidity()
对象,返回一些列属性,表示字段哪些规则不匹配,或者完全匹配
如果设置了setCustomValidity()就返回true,否则返回false
customError
不匹配制定的正则返回true
patternMismatch
如果字段值大于max返回true
rangeOverflow
如果值小于min返回true
rangeUnderflow
如果字段与min,max,step的值不符合返回true
stepMisMatch
字段长度唱过maxlength返回true
tooLong
如果字段不是email或url要求的格式返回true
typeMismatch
如果其他属性都是false,则返回true,表示验证有效、通过
valid
如果必填但没有值返回true
valueMissing
element.validity
禁用验证
表单上添加noValidate
通过该按钮无需验证即可提交表单
提交按钮上添加formnovalidate
表单验证
z在relOption之前添加新的option
是否多选
multiple
控件所有option元素的HTMLCollection
options
移除给定位置的选项
remove(index)
选中项基于0的索引
selectedIndex
选择框中可见的行数
HTMLSelectElement有以下公共方法和属性
如果没有选中项,则值时空字符串
如果有一个选中项,且其value属性有值,那么选择框的值就是选中项value属性的值,即使value属性的值时空字符串也是如此
如果有一个选中项,且其value没有制定值,则选择框的值是该项的文本内容
如果有多个选项,则选择框根绝前两条规则取得第一个选中项的值
选项在options集合中的索引
index
选项的标签
label
是否选中,把他设置成true,会选中该项
selected
选项文本
text
选项的值
选项由HTMLOptionElement对象表示,属性有
option
选择框编程
在HTML中嵌入一个iframe,并把designMode属性设置为on
任何元素指定contenteditable为true、
在文档上执行既定的命令
第一个参数是命令
第二个参数是否为命令提供用户界面的布尔值,由于filefox浏览器为true时报错,为了兼容性始终为false
value:命令需要的参数
backcolor
bold
createlink
delete
fontname
fontsize
forecolor
formatblock
indent
outdent
inserthorizontalrule
insertimage
insertorderedlist
insertparagraph
insertunorderedlist
italic
justifycenter
justifyleft
removeformat
selectall
underline
unlink
与富文本交互(font color=\"#f44336\
富文本编辑
表单
catch的error对象含有message属性,表示错误信息
其他属性根据浏览器不同有不同的字段
try/catch
始终运行
如果finally中有return,那么try和catch块中的return语句不会执行(这里的不会执行指的是return本身不会执行,但它后面的语句还是会执行)
finally
基础类型,其他错误类型继承自Error
Error
js引擎内部错误,例如递归过深
InternalError
不把eval当成函数调用就报告这个类型的错误
EvalError
数值越界
例如new Array(-10)
RangeError
找不到对象时发生
例如访问不存在的对象
ReferenceError
语法错误
SyntaxError
变量不是预期类型
例如new 10
var s = '1234'; s()
TypeError
使用encodeURI和decodeURI时参数错误
例如decodeURI('%')
URIError
通过instanceof来判断错误类型
错误类型
抛出错误
throw
const error = new TypeError(message)
throw error
模拟浏览器内置类型
自定义错误类型有助于在捕获错误时更准确的区分错误
自定义错误类型
捕获错误是为了组织浏览器以默认方式响应
抛出错误是为错误提供有关发生原因的说明
任务没有被try/catch处理的错误,都会触发window上的error事件
错误信息
发生错误的url
行数
参数
返回false可以阻止浏览器报告错误的行为
error事件
记录web端产生的错误到服务器是必要的
方法接受两个参数分别是严重成都和错误信息
1.ajax都是使用库来封装,库本身也有可能出错
2.img不受跨域限制
3.所有浏览器都支持img,有些不支持XMLHttpRequest
使用img请求而不用ajax的原因在于
可以实现一个logError 方法来发送错误到服务器
记录错误到服务器
console.log
console.info
console.error
console.warn
把符合类型数据(数组、对象)打印成table
console.table(array)
情况console控制台
console.clear()
表达式为false,打印message
console.assert(表达式,message)
console打印分组,使用groupEnd(name)结束分组
console.group(name)
console.groupEnd(name)
执行次数
console.count(p)
开始计时器
console.time(name)
结束计时器,并打印name计时器花费的时间
console.timeEnd(name)
这个打印所在函数的调用过程(调用栈)
console.trace()
开始性能分析
chrome自带性能分析,可以在⋮ - >更多工具 - > JavaScript Profiler中查看报告
console.profile(name)
结束名称为name的性能分析,分析name开始到name结束期间的性能
console.profileEnd(name)
console
使用节点选择器(windwos:ctrl+shift+c),选择一个节点后,该节点在控制台上可以使用$0打印出来,方便调试
$0
debugger
调试技术
错误处理
一种数据格式,表示结构化数据
key必须使用双引号包围,不能省略引号,也不能用单引号
没有分号的结束符
与js对象字面量不同点
string转js值
表示如何还原json
fn
js值转字符串
会略过值为undefined的属性
会略过函数成员
会略过原型成员
规则
返回的结果只会包含该数组中列出的对象属性
可以是数组
根据key来对value做操作,返回value会作为key的值,返回undefined会忽略该属性
字符缩进
最大缩进为10
当indent是字符串时,就会使用这个字符串作为缩进,也是最大缩进为10,长度大于10的字符串会被截取
JSON.stringfy会调用对象的toJSON方法
箭头函数作为toJSON方法时,需要注意this指向
toJSON
如果可以获取实际的值则调用toJSON()方法获取实际的值,否则使用默认的序列化
如果提供的第二个参数,则应用过滤,传入过滤函数的值就是第一步返回的值
第二步返回的每个值都会相应的进行序列化
如果提供了第三个参数,则相应的进行缩进
stringfy的流程
JSON.stringfy(json,filter, indent)
JSON对象
解析与序列化
JSON
可扩展标记语言,用来存储和传输结构化数据
const parser = new DomParser()
const anotherChild = xmldom.createElement('child')
xmldom.documentElement.appendChild(anotherChild)
DOMPaser
const serializer = new XMLSerilizer()
const xmlString = serializer.serializeToString(xmldom)
XMLSerializer
一种在xml中查找信息的语言
Path 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的。
选取属于 bookstore 的子元素的所有 book 元素。
bookstore/book
/
选取所有 book 子元素,而不管它们在文档中的位置。
//book
选取bookstore的所有 后代book 子元素,而不管它们在后代中的位置。
bookstore//book
//
选取当前节点父节点
..
选取名为 lang 的所有属性。
//@lang
选取属性
@
选取节点
bookstore子元素中的第一个book元素
bookstoer/book[0]
last()
last()-n
前n个元素
position()<3
拥有属性名为xxx的元素
@xxx
拥有属性名为name属性值为value的元素
@name=value
元素名为xmlname的值大于num
xmlname>num
谓语,放在中括号中用于选取特定元素
任何元素节点
*
任何属性节点
@*
任何类型节点
node()
通配符
a和b节点
a|b
运算符
XPath
XSL 指扩展样式表语言(EXtensible Stylesheet Language)。
XSL 可描述如何来显示 XML 文档!
XSL 包括三部分:XSLT - 一种用于转换 XML 文档的语言。XPath - 一种用于在 XML 文档中导航的语言。XSL-FO - 一种用于格式化 XML 文档的语言。
XSL
XSLT 是 XSL 中最重要的部分。XSLT 用于将一种 XML 文档转换为另外一种 XML 文档
XSLT 使用 XPath 来定义源文档中可匹配一个或多个预定义模板的部分。一旦匹配被找到,XSLT 就会把源文档的匹配部分转换为结果文档。
https://www.runoob.com/xsl/xsl-transformation.html
XSLT
XPath表达式
expression
上下文节点
context
命名空间解析器,当xml有命名空间时才有必要
nsresolver
适合XPath的任何类型
XPathResult.ANY_TYPE
数值
XPathResult.NUMBER_TYPE
字符串
XPathResult.STRING_TYPE
XPathResult.BOOLEAN_TYPE
返回匹配节点集合,集合中节点顺序可能和文档中不一致
XPathResult.UNORDERED_NODE_ITERATOR_TYPE
返回匹配节点集合,集合中节点顺序和文档中顺序一致
XPathResult.ORDERED_NODE_ITERATOT_TYPE
返回节点集合快照,对文档的修改不会影响这个节点集合,且不保证顺序
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE
返回节点集合快照,对文档的修改不会影响这个节点集合,可以保证顺序和文档一致
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE
返回匹配节点集合,顺序可能不一致
XPathResult.ANY_UNORDERED_NODE_TYPE
返回只有一个节点的节点集合,包含的是文档中第一个匹配的节点
XPathResult.FIRST_ORDERED_NODE_TYPE
返回结果类型
XPathResult对象
result
如有有结果返回一个XPathResult对象,没有结果返回null
如果结果是一个集合,那么XpathResult上有一个iteratorNext方法,用来获取集合中的下一个元素,直到返回null
返回值
XPath.First_ORDERED_NODE_TYPE使用该方法取返回值
result.singleNodeValue
XPath.BOOLEAN_TYPE类型的返回值使用 它来获取返回值,表示expression是否有节点匹配
result.booleanValue
表示XPath匹配了多少个节点
result.numberValue
表示匹配的第一个节点其第一个子节点的值
result.stringValue
XPathResult结果获取
evaluate方法的第二个参数,如果xml文档中有命名空间定义,那么这个参数需要一个XPathNSResolver对象
把定义了命名空间的节点传给createNSResolver方法,可以获取命名空间解析器
吧命名空间解析器传递给evaluate方法就能正确解析带命名空间前缀的XPath表达式
xml.createNSResolver(namespaceElement)
命名空间
浏览器对XPath的支持
用于根据xsl文件装换xml
const processor = new XSLTProcessor()
导入xslt文档
processor.importStyleSheet(xsltdom)
吧xml根据xslt装换成完整的文档,然后返回
processor.transformToDocument(xlmdom)
得到文档片段,并插入到一个新文档中
XSLTProcessor
设置参数,Uri一般是null
设置参数
reset方法可以删除所有参数和样式表,然后就可以使用imprtStyleSheet重新加载新的样式表
processor.reset()
重置处理器
对XSLT的支持
XML
注意xhr只能同源发送,即域名、端口、协议都相同
使用ajax(asynchromous JavaScript + XML)
初始化xhr对象
const xhr = new XMLHttpRequest()
打开,请求类型、地址、是否异步
发送数据
xhr.send(data)
收到响应前可以使用abort方法取消异步请求
xhr.abort()
uninitialized, 未初始化,未open
open, 调用了open方法未send
sent, 调用了send方法,未响应
receiving, 接受中已经收到部分响应
complete,收到所有响应
当readyState状态发生变化就会触发onreadyStateChange事件,如果readyState值为4,那么表示数据已经就绪
onreadyStateChange
xhr数据完成的检测
响应体文本
responseText
如果返回内容类型是‘text/xml’或者'application/xml'那么就是包含相应数据的xml文档
responseXML
成功
2xx
从缓存读取,资源未修改过
304
服务器错误
5xx
http状态
status
http状态描述
statusText
数据发送之后,xhr对象的以下属性会被填充
浏览器可以处理的内容类型
Accept
浏览器可以显示的字符集
Accept-Charset
浏览器可以处理的压缩编码类型
Accept-Encoding
浏览器使用的语言
Accpet-Language
浏览器与服务器的连接类型
Connection
页面中设置的Cookie
Cookie
发送请求的页面所在的域
Host
发送请求的页面的URI
Referer
User-Agent
设置头部
xhr.getResponseHeader(name)
xhr.getAllResponseHeader()
获取已经设置的header
header
Get请求
POST请求
便于表单序列化
const data = new FormData()
添加数据
使用ajax发送数据
FormData
超时,发送请求后等待多少毫秒,如果请求不成功就中断请求
xhr.timeout
请求超时后的事件
xhr.ontimeout
超时
接受到响应的第一个字节时触发
loadStart
接受响应期间反复触发
XHR对象
布尔值,表示进度信息是否可用
lengthComputable
接收到的字节数
position
总字节数
totalSize
event对象
progress
请求出错触发
终止链接触发
成功接受万响应触发
童心完成时,在error,abort或load之后触发
loadend
进度事件
域名、协议、端口有一个不同就是跨域
xhr只能访问与发请求的页面在同一个于内的资源
发送请求的头部会有一个Origin字段,包含了发送请求的页面的源(协议、域名、端口)
如果这个头部与请求的Origin不匹配就不会相应浏览器请求
如果服务器决定相应请求,那么发送Access-Control-Allow-Origin头部,包含相同的源,或者值是‘*’表示任何源可访问
CORS通过预检请求的服务器验证机制,允许使用自定义头部、除Get、POST之外的方法、以及不同请求体内容类型
Origin
希望使用的方法
Access-Control-Request-Method
要是用的逗号分隔的自定义头部列表
Access-Control-Request-Headers
涉及上述高级请求时,会先发送一个预检请求,这个预检请求使用OPTIONS方法发送,头部如下
允许的源
Access-Control-Allow-Origin
允许的方法,逗号分隔的列表
Access-control-Allow-Method
服务器允许的头部,逗号分隔的列表
Access-Control-Allow-Headers
缓存预检请求的秒数
结果可以缓存一段时间,时间之内不用再发送额外的OPTIONS请求
Access-Control-Allow-Max-Age
在请求发送之后,服务器可以确定是否允许这种类型的请求,服务器会在响应中发送以下头部来与浏览器沟通
预检请求
默认情况下,跨域请求不提供凭据(cookie、http认证,客户端SSl证书),可以通过奖withCredentials设置为true来表明会发送凭据
服务器可以在相应头部中包含Access-Control-Allow-Credentials:true
凭据请求
利用任何页面都可以跨域加载图片,不同担心跨域限制的特点来发送跨域请求的技术
创建一个Img实例,把他的src替换成要发送的GET请求
通过img的onload和onerror方法就可以判断请求的成功或失败
注意:这种方法是单向通信、不能接收返回值拿不到任何数据,只能发送GET请求,常常用于跟踪用户在页面上的点击操作或动态显示广告
图片探测
动态创建<script>并为src属性指定跨域url实现的,原理和img一样,script元素能够不受限制的从其他域加载资源
从不同域拉去代码执行,可能会有恶意内容
不好确定JSONP请求是否失败,script元素的onerror事件并未被所有浏览器实现,所以经常需要写计时器来决定是否放弃等待
缺点
JSONP
替代性跨域技术
跨域
XMLHttpRequest
fetch()方法暴露在全局作用域中,包括主页面件执行线程、模块、工作线程
返回一个promise
请求完成promise会resolve一个Response对象,并可以通过这个对象来获取返回数据
注意:不管请求是否成功(状态是500、300、200)都会走resolve处理函数
超时、服务器不响应请求则会走reject处理函数,(违反cors的跨域、无网络链接等)
r.then(response=>{})
定义了如何发送请求
请求体内容,必须是Blob、BufferSource、FormData、URLSearchParams、ReadableStream、String的实例
请求方法,Get、POST、PUT、PATCH、DELETE、HEAD、OPTIONS、CONNECT、TARCE
默认为GET,没有options时也是get
method
不发送cookie
同源发送cookie,默认值
same-origin
无论同源还是跨域都发送cookie
include
credentials
请求头,Heads对象实例或者包含字符串格式键值对的普通对象
heads
允许请求存在的时间超过页面生命周期
keepalive
请求模式
允许遵守CORS协议的跨域请求
cors
允许不需要发送预检请求的跨域请求
no-cors
任何跨域请求都不允许发送
跟踪重定向请求,以最终重定向url的相应作为最终相应
follow
重定向抛出错误
不跟踪重定向,返回响应中暴露重定向的url,允许手动处理
manual
redirect
缓存交互
返回命中的有效缓存,不发送请求
命中无效缓存发送条件式请求,如果响应已经改变,更新缓存的值然后fetch()返回缓存的值
未命中缓存,发送请求并缓存响应,fetchI()返回响应
Default
不检查缓存、直接发送请求
不缓存响应,直接fetch()返回
no-store
不检查缓存,直接发送请求
缓存响应,通过fetch()返回
reload
无论命中有效缓存还是无效缓存都会发送条件式请求,如果响应已经变化则更新缓存的值,然后fetch返回缓存的值
未命中缓存,会发送请求缓存响应,fetch()返回响应
no-cache
无论命中有效缓存还是无效缓存都通过fetch()返回,不发送请求
未命中缓存会发送请求,缓存响应人后fetch()返回响应
force-cache
只在请求模式为same-origin时使用缓存
无论命中有效缓存还是无效缓存都通过fetch返回,不发送请求
未命中返回504
only-if-cached
AbortSignal的实例
用于中断进行中的fetch请求
创建中断请求实例
const abortController = new AbortController()
请求数据
执行中断
abortController.abort()
singal
cache
options选项
每一个response和Resquest对象上都会对应的Headers对象,用来获取响应和请求的头部信息
Header对象和Map类似,具有get、set、delete、has方法
初始化时和map不同,可以使用键值对对象作为初始化对象
new Header({foo:'bar'})
const header = new Headers()
header.get('foo')
true
header.has('foo')
给foo属性添加另一个baz值,此时foo变成了\
header.delete('foo')
Headers
参数和fetch参数相同
创建一个副本,可以使用新的options覆盖之前的设置
不一定得到一样的副本,第一个请求在克隆之后它的bodyUsed被设置成true
const request2 = new Request(request, options)
创建一个一模一样的副本
const request2 = request.clone()
注意:没有请求体的请求不受此限制
请求的body被读取之后(request.text()等方法)bodyUsed被置成true,bodyUsed为true的request不能被克隆,此时克隆报错
被请求过的带有请求体的request对象的bodyUsed也会变成true,同样也不能再次使用
fetch( request )
克隆Request
Request
可选的body和options
Header对象实例,或其他常规对象
headers
http状态码
http响应状态字符串
这个静态方法生成网络错误的响应对象,可以导致fetch被拒绝
Response.error()
这个静态方法生成重定向响应对象,它的status必须对应重定向
Response.redirect()
头部信息
布尔值,200-299位true,其他为false
ok
布尔值,是否经过至少一次重定向
redirected
http状态码描述
响应类型
同源响应
basic
跨域响应
响应通过Response.error()创建
表示no-cache返回的跨域响应
opaque
表示对redirect设置为manual的响应
opaqueredirect
url
response对象字段
const response2 = response.clone()
bodyUsed为true的响应对象不能克隆,注意没有响应体的response不受此限制
有body的响应,只能被读取一次,多次读取报错,注意没有响应体的response不受此限制
克隆
Response
Request和Response都使用了Fetch API的body混入,使他们可以使用body的一些属性和方法
只读,ReadableStream的实例
产生一个读取器const reader = body.getReader()
通过done判断流是否全部读取完成
这个实例是一个流,具有getReader()方法
只读,body流是否被读取
bodyUsed
返回promise,resolve为字符串
Body.text()
返回promise, resolve为JSON
Body.json()
返回promise, resolve为FormData实例
Body.formData()
返回promise, resolve为ArrayBuffer实例
Body.arrayBuffer()
返回promise, resolve为Blob实例
Body.Blob()
Body混入构建在ReadableStream之上的,所有犯法都只能使用一次,多次调用报错,没有body也就没有这个限制
Reques、Response以及Body混入
用于在页面关闭之后也能发送请求,多用于在页面生命周期中尽量晚的时候向服务器发送分析数据
body载荷可以是ArrayBufferView、Blob、DomString、formData实例
sendBeacon不是只能在页面生命周期末尾使用,在任何时候都可以使用
调用sendBeacon之后,浏览器会把请求添加到一个内部队列,浏览器会主动发送队列中的请求
浏览器保障原始页面关闭的情况下也会发送请求
状态码、超时和其他网络原因造成的失败是完全不透明的,不能通过编程处理
beacon请求会携带senBeacon时所有相关的cookie
Beacon
长时链接实现与服务器全双工、双向通信
创建webSocket时,一个http请求会被发送到服务器,用来初始化链接,服务器响应之后,链接使用http的upgrade头部从http协议切换到websocket协议
websocket使用了自定义协议,因此需要使用ws://和wss://,前者是不安全链接,后者是安全链接
创建websocket
const socket = new WebSocket(\"ws://xxxxxx\")
socket.send(data)
获取服务器向客户端发送的数据,event.data
socket.onmessage=function(event){}
正在建立连接
WebSocket.OPENING(0)
已经建立连接
WebSocket.OPEN(1)
正在关闭
WebSocket.CLOSING(2)
已经关闭
WebSocket.CLOSE(3)
连接成功触发
onopen
发生错误触发,连接无法存续
onerror
连接关闭触发
onclose
WebSocket
fetch API
网络请求
用于早客户端存储会话信息
服务器在响应http请求时,通过发送Set-Cookie HTTP头部包含会话信息,浏览器会存储会话信息,之后个请求都会通过http头部cookie发回服务器
cookie与特定域绑定,放置被恶意利用
不超过300个cookie
超过大小静默设置删除
每个cookie不超过4096个字节
IE、Edge不超过50个
fireFox不超过150个
Opera不超过180个
Safari、chrome没有硬性限制
多设置的cookie会导致之前的某一个cookie被删除,不同的浏览器有不同的策略,可能删除最少使用的、可能随机删除
不同的浏览器对同一个域cookie有不同的限制
每个域最好不超过20个
每个域不超过81920字节
有空间限制
限制
表示cookie的名称,不区分大小写,但最好当成区分对待
名称
名称和值都是URL编码之后的,需要使用decodeURIComponent解码
name1=value1;name2=value2;name3=value3
通过document.cookie获取有效cookie字符串
获取值
document.cookie = 'name=xxx; expires=过期时间;domain=域名; path=路径; secure'
设置值不会删除之前的cookie,除非设置了同名值
设置值
值
有效的域,发送到这个域的请求都会带上对应cookie
域
请求url包含这个路径才会发送cookie
何时删除cookie的时间戳,默认浏览器会话结束会删除所有cookie,除非设置删除时间,这样即使关闭浏览器也能保留cookie到指定时间
把过期时间设置为过去的时间会立即删除cookie
过期时间
设置之后,只有使用https的链接才会发送
安全标志
cookie构成
cookie是不安全的,任何人都可以获取,不要存取敏感信息
cookie存储大量数据都会发送到服务器,因此大量cookie拖累请求速度
注意
cookie
删除所有数据
localstorage.clear()
getItem(name)
removeItem(name)
或者制定位置的数据
key(index)
Storage类型
只能访问同一个域的localstorage
永久存储机制
是Storage类型的实现,因此有Storage所有犯法
localstorage
跨会话存储机制,只会存储到浏览器关闭
sessionStorage
变化对应的域
旧值
新值
newValue
变化对应的键
event有4个属性
存储事件
大小有限制,取决于特定浏览器
同一个域 下,大多是5M
Web Storage
方便js对象的存储和获取,也支持查询和搜索
打开特定名称和版本的数据库的请求
如果没有对应的名称和版本会发送一个创建一个对应的数据库的请求
打开失败
request.onerror = (e)=> console.log(e)
打开成功
其中的event.target.result就是数据库对象
request.onsuccess = (e)=>db = event.target.resut
打开数据库
使用open创建一个数据库或修改版本后会触发upgradeennded事件,这个事件中可以更新数据库模式,也就是新建表
name 是数据库表名称
option:{keyPath: key}指定主键
也可以使用autoIncrement:true选择自增主键
创建对象存储
可以读取name1,name2等对象存储
option 可以是readonly,readwrite,versionchange,决定了只读、读写权限
获取名为name的对象存储
const store = transaction.objectstore(name)
const request = store.get(key)
事务
添加对象,如果对象key重复会报错
store.add(object)
添加对象,如果对象键重复则重写该对象
store.put(object)
插入
range是键的范围,可以传null,表示所有范围
unique类型的方向表示遇到重复记录跳过
const cursor = store.openCursor(range, direction)
如果有下一条记录,则是IDBCursor的实例
没有下一条记录则是null,以此判断游标是否完成遍历
event.target.result
遍历方向包括NEXT、 NEXTUNIQUE、 PREV、 PREVUNIQUE
direction
对象的键
实际的对象
游标使用的键,可能是对象键或索引键
primaryKey
IDBCursor的实例
cursor.onsuccess=(e)=>{}
游标
IDBKeyRange(key)
单独一个键
结果从key开始到最后
flag为true表示不包含key这一条记录
定义结果的下限
到键为key的记录停止
IDBKeyRange.bound(key,flag)
定义结果的上限
结果集从lowerKey到UpperKey的记录
flag1为true表示不包含lowerKey
flag2为true表示不包含upperKey
定义一个范围
键范围
索引名称
name
在key这个字段上建立索引
表示这个键在记录中是否重复,true为不重复,false为有可能重复
{unique:true}
创建索引
const index = store.index(name)
获取存储对象上已经存在的索引
在request.onsuccess的事件对象上有值,和游标的使用一样
const request = index.openCursor()
在request.onsuccess的事件对象上有值,获取索引键为key的记录
const request=index.get(key)
在request.onsuccess的事件对象上获取返回,获取所有索引键为key的记录的主键集合
const request = index.getKey(key)
使用索引查询
索引
不能跨域共享
有空间限制,但已经很大了,理论上甚至可以有无限大
IndexedDB
客户端存储
js是单线程的,webwork允许吧主线程的工作转嫁给独立的实体,而又不改变现有的单线程模型
webwork中不能使用依赖于单线程交互的api,比如DOM操作
概述
webwork是以实际线程实现的
webwork并行执行
webwor可以共享某些内存(SharedArrayBuffer),但不能公共享全部内存
webwork不一定是在同一个进程中,不同的浏览器的实现不同,可能webwork和主线程在不同进程中
创建webwork开销更大,因为有自己独立的时间循环、全局对象、事件处理、以及js运行所需要的其他环境和特性
window中全局对象即window,在webwork中全局对象为WorkerGlobalScope,通过self暴露出来
navigator
本身
performance
caches
indexedDB
工作者线程上下文知否安全
isSecureContext
fetch
setTimeout
setInterval
clearTimeout
clearInterval
属性
全局对象
让脚本单独创建一个js线程,以执行委托的任务
只能被创建它的页面使用,且它的生命周期、代码路径、输入输出都由初始化线程时提供的脚本来控制
只能加载同源脚本
const worker = new Worker('xxx.js')
创建webwork
webworker内部发生错误时触发
work.onerror
webworker向父上下文发送消息触发
worker.onmessage
webwooker无法反序列化消息时发生
work.onmessageerror
通过异步消息事件向webWork发送信息
work.postMessage()
立即终止webwork,没有为webworker提供清理的机会,脚本突然停止
work.terminate()
worker事件和方法
由webworker内部向父上下文发送消息
self.postMessage()
可以给Worker构造函数提供一个可选的字符串标识符
self.name
与worker.terminate()对应的方法,立即终止webworker,脚本突然停止
self.close()
导入任意数量的脚本
在webworker内部按顺序加载另外的脚本
importScripts(path)
意思是从webWorker内部定义的全局变量,在其他导入的脚本中也能取到
导入的脚本共享作用域
self.importScripts()
self属性和方法
new出一个worker,虽然此时worker已经在父上下文中存在,但worker本身的线程可能还没有创建完成
此时发送消息,会把消息加入队列,等待状态变为活动之后,再把消息加入到它的消息队列
之后webworker会伴随页面的整个生命周期存在,除非使用worker.termite()或self.close()手动结束
只要工作者线程仍然存在,worker对象就不会被垃圾回收机制回收
活动
worker.termite()会直接锁定webwork的消息队列,并且进行清理,因此之后发送的消息都不会被webworker内部接收
不会执行同步停止,它会通知webworker取消事件循环中的所有任务,并阻止新任务添加
这个地方这么理解:close方法会放到当前消息队列的最后一个,所以close之后的同步消息还是可以发送,但下一个微任务队列就不会再接受任务了
终止
生命周期
Worker(path, option)构造函数接受可选的配置对象作为第二个参数
webworker中通过self.name取得的字符串标识符
当成模块执行
module
常规脚本
classic
type为module时,制定如何获取与传输凭证数据相关的工作者线程模块脚本
omit、same-orign、include
worker配置
webworker内部可以再次new Worker()
子webworker也要受同源限制
委托任务到字工作者线程
webworker与父上下文通信,除了利用postMessage和onmessage还可以利用MessageChannel
简单原理就是把MessageChannel生成的其中一个端口传到webWorker中去,再利用对应的端口来接受、发送信息
worker.js
main.js
利用messageChannel实现父页面通信是多余的,因为postMessage和MessageCHannel实现的是一个操作,MessageChannel真正有用的地方在于把两个端口传递给两个不同的webworker,实现两个工作者线程之间的直接通信
MessageChannel通信
原理就是链接到同一个broadcast频道,使用这个频道来发送接收数据
注意、由于broadcastChannel的特性,如果没有实体监听信道,对应的消息就不会被处理,而worker初始化需要时间,因此不能在new出一个worker之后立即发送数据,因为此时对应channel的监听很可能还没有产生,导致消息丢失(无人处理)
Broadcast通信
专用webwork
可以被多个不同页面使用,只要是同源的脚本都可以向共享webwork发送或接收消息
const sharedWorker = new ShareWorker('xxx.js')
工作者线程名称也是标识的一部分,所有不同的name会产生不同的worker线程
sharedWorker只有在相同的标识不存在时才会新建实例,否则会建立与已有的共享线程建立连接
创建共享worker
与共享线程通信的MessagePort
shareworker属性
字符串标识符
向工作者线程导入任意数量的脚本
importScripts()
关闭工作者线程
close()
建立连接时的处理程序
onconnect
slef属性
共享webwork
拦截、重定向、修改页面发出的请求,充当网络请求的仲裁者的角色,并且可以决定那些api可以缓存以及缓存策略
必须同源才能访问,且必须是https安全上下文中使用
通过它可以管理serviceWorker
navigator.serviceWorker是ServiceWorkerContainer的实例
成功时返回promise,resolve为ServiceWorkerRegistration对象
第一次激活serviceWorker后再次在同一个页面使用相同url注册,实际上什么也不会执行,返回相同的ServiceWorkerRegistration对象
navigator.serviceWorker.register('xxx.js', options)
创建serviceWorker
它可以始终咋全局作用域中通过navigator.serviceWorker访问
在ServiceWorkerContainer获得新激活的serviceWorkerRegistration触发
oncontrollerchange
相关联工作者线程抛出错误触发
服务脚本向父上下文发送消息触发
onmessage
返回解决为ServiceWorkerRegistration对象的期约
ready
返回与当前页面关联的激活的ServiceWorker对象
controller
使用url和option创建或更新ServiceWorkerRegistration
返回promise,解决为返回与提供的作用域匹配的ServiceWorkerRegistration对象
getRegistration()
返回promise,解决为与ServiceWorkerContainer关联的ServiceWorkerRegistration对象
getRegistrations()
开始传送通过Client.postMessage()派发的消息
starMessage()
方法
ServiceWorkerContainer对象
serviceWorker开始安装新版本时触发
onupdatefound
返回服务工作者线程完整的url
scope
返回与注册对象关联的NavigationPreloadManager实例
navigationPreload
返回与注册对象关联的pushManager实例
pushManager
如果有则返回为状态未installing安装 的服务工作者线程serviceWorker对象
installing
如果有返回状态未waitin 等待的服务工作者线程serviceWorker对象
wating
如果有则返回装为 activation或active 活动 的服务工作者线程serviceWorker对象
active
返回promise 解决为Notification对象的数组
getNotifications()
显示通知,可以配置title和options参数
当用户关闭或点击消息时可以触发工作者线程内部self.onnotificationclick或self.onnotificationclose事件
showNotifications()
直接从服务器重新请求服务脚本,如果脚本不同则重新初始化
update()
取消服务工作者线程的注册,该方法会在服务工作者线程执行完再取消注册
unregister()
ServiceWorkerRegistration对象
通过ServiceWorkerContainer的controller属性获得
通过ServiceWorkerRegistration的active属性获得
获得
ServiceWorker.state变化时触发
onstateChange
解析后户注册服务工作者线程的URl
scriptUrl
返回状态
installed
activating
activated
redundant(多余)
state
serviceWor对象
ServiceWorkerGlobalScope的实例
返回CacheStorage对象
返回Clients接口,用于方位底层Client对象
clients
安徽ServiceWorkerRegistration对象
registration
强制服务工作者线程进入活动状态,需要和Clients.claim()一起使用
skipWaiting()
在服务工作者线程内如发送网络请求
fetch()
服务工作者线程进入安装状态触发,这是服务工作者线程接受的第一个事件,在线程一开始执行就会触发
self.oninstall
进入激活或已激活状态触发,服务工作者线程准备好处理功能性事件和控制客户端时触发
self.onactivate
在服务工作者线程接货来自主页面的fetch请求时触发
self.onfetch
服务工作者线程通过postMessage()获取数据时触发
self.onmessage
系统告诉浏览器用户点击了ServiceWorkerRegistration.showNotification()生成的通知时触发
self.onnofiticationclick
系统告诉浏览器用户关闭或取消了ServiceWorkerRegistration.showNitifocation()生成的通知时触发
self.onnotificationclose
在服务工作者线程接收到推送消息时触发
self.onpush
在应用外的因素(非js显式操作)导致推送订阅状态变化时触发
self.onpushsubscriptionchange
工作者线程内部的Self
用于跟踪关联的窗口、工作线程或服务工作者线程,使用self.clients获得
客户端全局唯一的标识符,可以用于通过Client.get(id) 获取客户端的引用
客户端类型,window、worker、sharedworker
客户端url
向单个客户端发送消息
postMessage()
获取客户端
get(id)
boolean,true时返回结果不包含当前服务工作者线程控制的客户端,默认fasle
includeUncontrolled
string, windwo、worker、sharedworker,默认all
matchAll(options)
在新窗口中打开指定URL,会给当前服务工作者线程添加一个新Client,新Client对象以promise的形式返回,可用于回应点击操作
openWindow(url)
强制性设置当前服务工作者线程以控制其作用域中的所有客户端。可用于不希望等待页面重新加载而让服务者线程开始管理页面
claim()
self.clients方法
工作者线程内部访问关联的窗口Client
网页缺少缓存网络请求的稳健机制,http缓存没有对js暴露编程接口,其其行为是受js运行时外部控制的
不自动缓存任何请求,所有缓存都必须明确制定
没有到期失效的概念,除非明确删除否则缓存一直有效
缓存必须手动更新和删除
版本必须手动管理,每次服务工作者线程更新,新服务者线程负责提供新的缓存键以保存新缓存
唯一的浏览器强制逐出策略基于服务工作者线程缓存占用的空间,基于最近最少使用的原则为新缓存腾出空间
serviceWorker缓存特定
const cache = self.caches
是映射到Cache对象的字符串键/值存储,api类似Map,通过self.caches属性暴露出来
===>Cache{}
caches.open('v1').then(console.log)
每个缓存是用过caches.open(key)取得,缓存不存在就会创建,它返回promise
key对应的缓存是否存在
caches.has(key)
删除key 对应的缓存
delete(key)
返回缓存中所有的key
根据Request对象所搜Cache对象,注意是Cache对象
match()
CacheStore对象
是CacheStore通过open 方法返回的promise的解决结果
它的键可以是url也可以是request对象,这些键会映射到response对象。默认情况下Cache不允许POST、PUT、DELETE等请求方法,因为这些方法意味着与服务器交换信息,一般情况下不适合客户端存储
以url或request为key, response为value 添加缓存,添加成功后返回promise
在只有request对象或url时使用此方法发送fetch请求,并缓存响应,返回promise
add(url/request)
addAll([url/request])
删除缓存
返回缓存的key数组
返回promise,解决为匹配缓存中response对象的数组
匹配时url和request可以互换,实际上request也是使用request对象中的url来匹配
返回promise,解决为匹配缓存中response,没有返回undefined
只有matchAll支持,只会匹配Cache键为制定字符串的缓存值
cacheName
boolean, true忽略url键的查询字符串
ignoreSearch
ignoreMedth
boolean, true时忽略Vary头部,该头部指定哪个请求头部导致服务器响应不同的值
如果同一个url需要根据不同的情况返回不同的数据,那么就需要一个内容协商机制,一般是用Accept(媒体类型)、Accept-Language(语言)、Accept-Charset(字符集)、Accept-Encoding(压缩形式),userAget等
如果中间有一个缓存服务器,例如serviceWorker,他就要分辨出同一个url需要返回缓存的哪种数据,这时候就需要服务端需要添加一个vary头部,来说明每一种返回的不一致性,让缓存服务器根据不同之处分别缓存,也根据不同之处返回给前端正确的数据
ignoreVary
options配置搜索行为
搜索方法
Cache对象
缓存
js代码有时候会递增更新,因此在浏览器中运行的文件,必须都属于同一个版本
网页也会向localstorage或indexedDB写入数据,也会api获取数据,不同版本的格式可能有变化,所以也要保证属于同一个版本
服务工作者线程提早失败,安装工作者线程任何预料之外的问题都可能组织安装成功,包括脚本加载失败、语法或运行时错误、设置某个缓存资源失败
服务工作者线程激进更新。浏览器再次加载脚本时哪怕一个字节不同也会启动安装新版本的服务工作者线程
未激活的服务工作者线程消极活动。当页面第一个register()时,serviceWorker会安装但不会激活,在导航事件发生前不会控制页面
活动的服务工作者线程粘连。只要至少有一个客户端与关联到活动的服务工作者线程,浏览器就会在所有页面中使用它。浏览器可以安装一个新的服务工作者线,但在与原有活动的工作者线程实例关联的客户端为0之前不会切换到新工作者线程。放置两个客户端同时运行不同版本的serviceWorker
保证一致性的手段
一致性和版本
刚通过navigator.serviceWorker.register()启动创建的serviceWorker会进入已解析状态,但改状态没有事件、没有值,永远不会返回parsed这种状态,最早的状态是installing
确保脚本来自相同的源
确保在安全上下文https中注册
确保脚本能被成功解析不报错
存储脚本快照,下次下载脚本会与这个脚本快照对比差异,决定是否更新worker
上述任务成功后进入installing状态
parsed已解析
执行所有服务工作者线程设置任务的状态,包括在服务工作者线程控制页面前必须完成的操作
他会使ServiceWorkerRegistration.installing设置为serviceWorker实例,会触发使关联的serviceWorkerRegistration的updatefound事件
用于填充服务工作者线程的缓存,在成功缓存制定资源前一直处于这个状态,任何资源缓存失败都会跳至redundant状态
可以使用installEvent中的awatiUntil方法使状态一直处于这个状态,知道对应的缓存加载完毕
installing安装中
也成为了等待中awaiting,此时worker没有事情做,准备得到许可的时候去控制客户端。如果没有活动的worker,则新安装的worker会跳到这个状态,并直接进入激活中状态
可以在已安装状态通过self.skipWaiting()强制推进服务工作者线程到下一阶段,也可以提示用户重新加载,让浏览器按部就班的推进
installed已安装
服务工作者线程即将被浏览器选中成为可以控制页面的服务工作者线程。
如果浏览器中没有活动的serviceWorker,那么新serviceWorker会自动进入激活中,如果已经有一个激活状态的serviceWorker,可以使用一下方法进入激活状态
原有的serviceWorker客户端数量变成0,意味着标签页都被关闭,再次打开会使用新的serviceWorker,注意刷新最后一个客户端也不会进入activated状态,因为刷新页面期间会发生重叠,旧页面还未卸载新页面就已经加载了
已安装的serviceWorker执行self.skipWaiting()
激活中状态下不能发送请求和推送事件,他只是个预备役
activation激活中
表示serviceWorker正在控制一个或多个客户端,能够捕获fetch事件、通知和推送事件
activated已激活
serviceWorker已经宣布死亡,不会再有事件推送给它,他随时可能被浏览器垃圾回收
redundant已失效
再次创建工作者线程但使用不同的url
浏览器导航到服务工作者线程作用域的一个页面
发生了fetch或push事件,而且至少24小时没有发生更新检查
使用ServiceWorkerRegistration.update()强制下载服务脚本
检查更新
js文件会按照cache-control头部纳入http缓存,如果工作者线程脚本被缓存,那么在缓存文件失效前都不会接受更新的服务脚本
1. 可以把cache-control头部的max-age设置为0,也就是即时失效
2.在register 服务工作者线程时,使用updateViaCache配置,来配置如何管理脚本缓存,但并不是所有浏览器都支持
默认值,顶级脚本不会被缓存,但通过importScripts加载的脚本会按照cache-controll头部设置纳入http缓存
imports
所有脚本没有特殊待遇,都会根据cache-contrl头部设置纳入http缓存
all
所有脚本都不会被缓存
这个配置有
为了尽可能更新服务脚本
服务脚本缓存
有时候,在安装完成之后,需要强制进入活动状态,这时为了服务工作者线程在不同客户端版本一致,需要强制服务工作者线程去控制关联的客户端
1.通过installEvent.waitUntil 等待安装成功
3. 此时线程还没有关联客户端,需要强制关联客户端,使用clients.claim()
过程
强制性服务工作者线程操作
更新服务工作者线程
navigator.serviceWorker.onmessage=data=>console.log(data)
接收消息
1.ServiceWorkerRegistration.active
2.navigator.serviceWorker.controller
navigator.serviceWorker.register('xxx.js').then(registeration=>{ if( navigator.serviceWorker.controller){ navigator.serviceWorker.controller.postMessage('aaaa') }})
navigator.serviceWorker.register('xxx.js').then(registeration=>{ if( registration.active){ registration.active.postMessage('aaaa') }})
发送消息
客户端
先从客户端发来的事件中获取source,也就是哪个客户端发来的,再用这个客户端发回去
worker
1.服务工作者线程接受消息后,再返回给客户端消息
self.onmessage=data=>console.log(data)
self.onactivate=()=>{ slef.clients.matchAll({includeUncontroller:true}) .then((clientMatches)=>clientMatches[0].postMessage('data'))}
发送
2.服务工作者线程主动先发送消息
消息处理
可以拦截fetch请求、js、css、图片等资源
简单转发fetch事件
self.onfetch=(fetchEvent)=>{ fetchEvent.respondWith( fetch(fetchEvent.request) ) }
1. 从网络返回
对于必定有缓存的资源,例如安装阶段缓存的资源
self.onfetch=(fetchEvent)=>{ fetchEvent.respondWith( caches.match(fetchEvent.request) ) }
2. 从缓存返回
self.onfetch=(fetchEvent)=>{ fetchEvent.respondWith( fetch(fetchEvent.request) .catch(()=>caches.match(fetchEvent.request)) ) }
以网络请求中最新的数据作为首选,如果缓存中有值也会返回缓存的值,用于离线情况下仍要展示一些信息
3. 从网络返回,缓存作为后备
self.onfetch=(fetchEvent)=>{ fetchEvent.respondWith( caches.match(fetchEvent.request) .then((response)=>response||fetch(fetchEvent.request)) ) }
这个策略有限考虑速度,仍会在没有缓存的情况下发送网络请求
4. 从缓存返回,网络作为后备
在缓存和网络都不可用的情况下,可以在安装时缓存后备资源,在都失败时返回他们
self.onfetch=(fetchEvent)=>{ fetchEvent.respondWith( caches.match(fetchEvent.request) .then((response)=>response||fetch(fetchEvent.request)) .catch(()=>caches.match('./fallback.html')) ) }
5. 通用后备
缓存策略如下
拦截fetch请求
服务工作者线程能够显示通知
能够处理通知交互
能够订阅服务器发送的推送通知
能够处理推送消息,及时应用程序没在前台运行或根本没打开
self.onactivate=()=>self.registration.showNotification('xxxx')
需要先使用Navigator.requestPermission()获取授权
navigator.serviceWorker.register(xxx).then(registration=>{ Notification.requestPermission() .then(status=>{ if(status === 'granted'){ registration.showNotification('xxxxx')} })})
1.显示通知
self.onnotificationonclick=(notification)=>console.log(notification)
self.onnotificationclose=(notification)=>console.log(notification)
2. 处理通知事件
通知处理
服务webwork
webwork
数组是否包含某个元素返回boolean
array.includes(data)
指数运算符
**
es7
异步终极方案
async/await
使用string2在字符串1之前填充到targetLength,如果填充的字符串超过了指定长度,则截断string2
使用string2在字符串1后面填充到targetLength,如果填充的字符串超过了指定长度,则截断string2
这样在参数较长、每一个参数一行显示时,可以直接添加下一行的参数。在git等版本控制中,看一看到只有新增的参数有变化
之前不允许参数尾逗号时,如果新增参数,会导致Git显示最后两行都是修改状态,看上去像是修改了两个参数一样,同时也是和对象尾逗号规则一致
函数的最后一个参数后面允许写逗号
返回对象自身所有属性的描述
Object.getOwnPropertyDescriptors
SharedArrayBuffer 对象用来表示一个通用的,固定长度的原始二进制数据缓冲区,类似于 ArrayBuffer 对象,它们都可以用来在共享内存(shared memory)上创建视图。与 ArrayBuffer 不同的是,SharedArrayBuffer 不能被分离。
new SharedArrayBuffer(length)
可以用来在worker中共享内存,可以见worker
注意:由于2018年发现的一个cpu漏洞,可以被利用进行旁路攻击,这种攻击是一种时序攻击,依赖精确的时间,所以浏览器厂商为了缓解这个问题,把performance.now()时钟精确度不同程度降低,由于sharedArrayBuffer可以构造精确时钟,因此很多厂商已经禁用了SharedArrayBuffer
SharedArrayBuffer
提供了一组静态方法用来对 SharedArrayBuffer 对象进行原子操作。这些原子操作属于 Atomics 模块。与一般的全局对象不同,Atomics 不是构造函数,因此不能使用 new 操作符调用,也不能将其当作函数直接调用。Atomics 的所有属性和方法都是静态的(与 Math 对象一样)
多个共享内存的线程能够同时读写同一位置上的数据。原子操作会确保正在读或写的数据的值是符合预期的,即下一个原子操作一定会在上一个原子操作结束后才会开始,其操作过程不会中断。
将制定位置上的数组元素与给定的值相加,并返回相加前改元素的值
将给定的值与数组上的值进行按位与操作,并将结果赋值给数组,然后返回数组该位置上的旧值。
Atomics.or()
用 给定的值替换掉数组上的值,然后返回数组的旧值
返回一个数组当中给定位置的值。
给定的值存储在数组中的指定位置,并返回该值。.
减去数组中给定位置的给定值,并在该位置返回旧值。
将指定位置上的数组元素与给定的值相异或,并返回异或操作前该元素的值。
Atomics.wake()方法唤醒在等待队列中休眠的某些代理
可以用来检测当前系统是否支持硬件级的原子操作。对于指定大小的数组,如果当前系统支持硬件级的原子操作,则返回 true;否则就意味着对于该数组,Atomics 对象中的各原子操作都只能用锁来实现。
Atomics.isLockFree(size)
Atomics 对象
es8
异步迭代 await for
无论Promise运行成功还是失败,运行相同的代码
Promise.finally()
增强了rest和扩展运算符
rest可以作用域对象
可以对对象进行浅拷贝
Rest/spread
ES2018允许命名捕获组使用符号?<name>,在打开捕获括号(后立即命名
正则表达式命名捕获组
正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?=pattern)
正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。
(?!pattern)
反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”
(?<=pattern)
反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”
(?<!pattern)
正则表达式反向断言
点 . 匹配除回车之外的所有单字符,标记为 s
正则表达式dotAll模式
正则表达式Unicode转义
非转义序列的模板字符串
es9
Array.flat(depth)
参数是一个Array.map的回调
先执行Array.map生成新数组,再执行flat(1)深度为1的展平操作
Array.flatMap()
去掉开头空格
String.trimStart()
去掉结尾空格
String.trimEnd()
返回与正则表达式匹配字符串的所有结果的迭代器,包括捕获组。
String.matchAll()
symbol对象新增的一个属性description,可以返回只读的描述
Symbol.description
Object.fromEntries()
catch之后紧跟的错误参数可以省略
可选catch
支持解析行分隔符(\\u2028)和段落分隔符(\\u2029)
JSON Superset超集
这是因为emoji表情由2个字符串代理组合而成,但是单独的一个代理字符串没有意义
单独的一个字符串在stringfy时,之前会变成特殊字符失去含义,现在可以正确保留UTF-8/UTF-16代码
pre style=\
'😀'.length === 2
JSON.stringfy()加强格式转化
之前v8在10个以上元素的数组上使用了不稳定的排序方法例如快排,现在更加稳定
可以传入排序函数,对对象数组排序
Array.sort()更加稳定
现在可以原样返回函数的字符串形式,包括注释也能正确返回
function.toString()重新修订
es10
需要根据浏览器兼容性有选择的加载一些库
在实际需要时才加载某个模块
只是单纯的希望延迟加载某些模块来渐进渲染的方式改进加载体验
es6中的导入import xx from 'xxx' 都是静态声明,无法满足一些动态导入的需求:
返回promise,在模块加载完成后解决,结果是一个对象,默认导出的key是default,具名导出项放在同名属性中
import('xxx').then(module=>{})
动态import() 按需导入
??操作符避免data||1操作时,当data为0会取1的问题
只有左边的值是null或undefined才会取右边的值
空置合并运算符 ??
当尝试访问某个对象上的属性,又不确定对象是否存在时使用
就算data为undefiend也不会报错
data?.a
函数不存在时返回undefiend
func?.()
可选链接 ?.
js number类型使用64位浮点数存储,因此最大值为2^53-1
BigInt类型可以使用任意精度的整数
数字后边后缀n
使用构造函数 new BigInt(1234)
使用方式
要注意/除法结果会向下取整,因为bigInt毕竟是int类型
支持和字符串拼接
支持和number比较大小,支持装换成boolean类型,装换和number一样,0n转换成false,其他为true
可以通过Number()转换成普通number类型,但有精度降低的问题
可以通过BigInt()把number转成BigInt
不支持和普通number一起运算
Math函数一些方法不支持BigInt
1n==1 true
1n===1 false
BigInt和number 不严格相等
不支持
BigInt
在不同环境中全局对象并不一致,例如浏览器中是window,worker中是self,node中是global
但由于安全策略,以及eval的安全性问题,这段代码可能无法运行
const globals = (new Functon('return this'))()
或者穷举各种全局对象是否存在
globalsThis在不同环境中就是不同的全局对象方便使用
为了在不同环境中可以取到全局对象可以使用
GlobalTHis
所有promise都是resolved状态后该promise转成resolved状态,有一个rejectd则该promise状态为rejected
promise.all
有任意一个resolved或rejected后,该promise切换到相同的状态
promise.race
当所有promise都切换成resolved或rejected之后,改promise切换到fullfilled状态
promise.allSettled
任意一个promise切换到fullfilled状态之后,该promise切换到fulfilled状态;所有promise都是rejected状态,该promise切换到rejected状态
promise.any
Promise.allSettled
规范了for-in的遍历顺序
for-in
es11
模式的所有匹配都会被替换,返回新字符串
string.replaceAll
任何一个promise完成时返回那个完成值的promise,所有promise都rejected,返回一个拒绝的promise
e=e??f ===> e??=f
??=
a = a||b ======> a||=b
||=
a = a&&b ======> a&&=b
&&=
逻辑赋值操作符
拿到一个对象的弱引用,并且不会妨碍垃圾回收这个对象
const ref = new WearRef(anyObj)
使用ref.deref()得到引用的值
weakRef
intl.ListFormat
Intl.DateTimeFormat
var num= 9_999_999
数字太长可读性变差,加下划线提高可读性
数字下划线分隔符
es12
es6之后各版本提案特性汇总
Node.js
useState
useEffect
useLayoutEffect
useRef
useReducer
useCallback
useMemo
useContext
useImperativeHandle
hooks
React.memo
优化
函数式
getDerivedStateFromProps
render
componentDidMount
挂载
shouldComponentUpdate
getSnapshotBeforeUpdate
ComponentDidUpdate
更新
componentWillUnmount
卸载
废弃
componentWillMount
componentWillReceiveProps
ComponentWillUpdate
继承PureComponent
类组件
React
yarn
npm
自动运行模块中的可执行二进制文件
npx
包管理工具
又称UI thread 负责UI渲染、用户行为监听,APP启动首先创建的线程
main thread
通过jsCore或Hermes引擎运行、解析js代码
javascript thread
处理虚拟Dom Diff之后的变更操作指令
shadow thread
三个线程
原生端和js端的交互式通过bridge进行的,bridge是给js引擎提供原生接口的api扩展供js调用
react native的产物是bundle文件,就是js代码,应用启动时会获取budnle,然后解析,这就天然允许开发者在云端更新budle
热更新
原生和react native交互依赖Bridge,js和native交互是异步的,所以在大量实时交互时性能不足
不足
原理解析
RN 是一个使用react和应用平台的原生功能来构建Android和IOS应用的开源框架,可以使用js来方位移动平台API
RN组件就是对原生视图的封装
<View>
<Text>
<Image>
<ScrollView>
<TextInput>
核心组件
垂直滚动列表虚拟滚动
FlatList
可分组的虚拟滚动
SectionList
长列表
Platform.OS返回ios、android
Platform
不同平台的逻辑放在不同后缀的文件中
xxx.ios.js
xxx.android.js
特定平台扩展名
平台定制
什么是RN
12版本+
node
修改文件实时更新的包
watchman
xcode
iOS包管理器
CocoaPods
安装
ios
javaJDK
Android studio
android
成本低
天然跨平台
热更新,可以通过服务器直接下发js代码,绕过审核
可扩展,可以通过原生桥的方式扩展js的原生硬件能力,且大多都是开源免费的
混合开发优势
性能问题
混合开发劣势
默认只允许https配置
NSAppTransportSecurity应用传输安全配置
其他权限可以查苹果文档
需要一个<key></key><string>xxx</string>格式配置权限,key中放置权限string中放置说明
ios/项目名/Info.plist
ios配置
android/src/debug/AndroidManifest.xml
android/src/main/AndroidManifest.xml
打包时两个配置会合并,开发环境debug/AndroidManifest.xml文件优先,生产环境main/AndroidManifest.xml优先
注意androdi:usesCleartextTraffic='true'配置可以使用http请求,它只在dev环境中,生产环境中如果也使用http请求需要加上这一行
权限配置
StyleSheet.create来集中定义样式
尺寸没有单位,它代表的是与设备像素密度武官的逻辑像素点,做到不同尺寸屏幕上都是一样大小
flexDirection默认为column
使用Image加载图片<Image source={require('./img/check.png')} />
可以根据后缀的.ios.png和 .android.png自动加载对应图片
可以根据后缀的@2x.png、@3x.png自动为不同屏幕精度提供图片
注意:为了使新的图片资源机制正常工作,require 中的图片名字必须是一个静态字符串(不能使用变量!因为 require 是在编译时期执行,而非运行时期执行!)。
网络图片的请求参数
注意:网络图片必须手动指定尺寸,为了放置图片加载过程中上下跳动使用用户体验糟糕,本地图片是已知尺寸,所以可以不指定尺寸
<ImageBackground>
必须制定宽高
背景图
图片解码可能会超过一帧的时间,这是掉帧的一大因素
rn中解码是另一线程完成的
在主线程外解码图片
图片
onPress
触摸
支持onLongPress
TouchableHighlight用于封装识图,可以正确响应触摸操作
TouchableOpacity
TouchableWithoutFeeback
交互
react-navigation
react-native-navigation
导航器
Animated.View
Animated.Text
Animated.Image
Animated.ScrollView
Animated.FlatList
Animated.SectionList
6个可以动画化的组件
同时执行
parallel
顺序执行
sequence
错开
stagger
delay
组合动画
接受一个函数作为唯一参数,在下一次重绘之前调用此函数
requestAnimationFram
useNativeDriver
使用原生动画驱动
动画
Animated
大量的打印语句会拖累js线程
第三方的npm包中也可能有大量的打印,比如redux-logger
使用babel-plugin-transform-remove-console插件在编译时删除打印语句
解决:
getItemLayout
虚拟滚动
预渲染一个缓存了静态视图的位图,并快速合成,由于会产生一个离屏的位图渲染过程,会产生内存损耗
ios:shouldRasterizeIOS
把自己和子视图渲染到GPU的硬件纹理中,大量消耗内存
android:renderToHardwareTextureAndroid
屏幕上移动视图(滚动,切换,旋转)
在IOS上修改图片尺寸都要重新剪裁和缩放原始图片,这个开销非常大
解决:使用transorm:[{scale}]的样式属性改变尺寸,比如点击图片放大到全屏
动画改变图片尺寸
操作与点击产生的透明度改变或高亮效果中间产生掉帧,比如在onPress中执行了一个setState操作,这个操作又需要大量计算工作导致掉帧
解决:onPress封装到requestAnimationFrame中,延迟到动画结束再执行onPress
touchable组件不能很好响应
开启原生动画驱动useNativeDriver
动画慢
因为要有警告、错误信息、propTypes属性验证以及其他警告的产生
开发模式会慢一些
使用require代替import在史记需要该文件时再加载
延迟加载模块
注意清除定时器
性能优化
react native
用于给第三方库打补丁
修改node_module中的代码后,使用 npx patch-package xxxx命令,会在patches文件夹中生成一个补丁文件
补丁文件可以上传到git分享给团队,之后所有人只要重新install npm包就会打上这个补丁
之后就算删除node_modules重新安装,patch-package也会根据补丁重新修改代码
注意项目引用的是源码还是编译后的代码,引用的是编译代码就要改编译的代码,此时很难修改(也可以使用源码重新编译、、、)
patch-package
小程序时图层使用webView渲染
小程序逻辑层采用ios:JSCORE android:x5内核 开发工具:chrome运行js脚本
微信能力
native系统层
JSBridge
1. js线程无法直接修改webView线程的DOM结构
3.JsBridge桥转发数据到WebView
4. diff算法对比差异更新界面
逻辑层修改数据后反应到视图层
小程序
前端技术栈
0 条评论
回复 删除
下一页