标签:await 影响 第三方 阶段 事件处理器 破坏 转化 重载 描述
https://juejin.im/post/5c8e409ee51d4534977bc557#heading-1
https://juejin.im/post/5d136700f265da1b7c6128db
https://juejin.im/post/5a6547d0f265da3e283a1df7
https://juejin.im/post/5e55272e6fb9a07ca453436f
<div class="box">
<div class="left" style="float: left;">200px</div>
<div class="right">200px</div>
<div class="center" style="float: right;">自适应</div>
</div>
<div class="box" style="position: relative;">
<div class="left" style="position: absolute;left: 0;">200px</div>
<div class="right" style="position: absolute;right: 0;">200px</div>
<div class="center" style="margin: 0 200px;">自适应</div>
</div>
<div class="box" style="display: flex;">
<div class="left" style="width:200px">200px</div>
<div class="center" style="flex:1">自适应</div>
<div class="right" style="width:200px">200px</div>
</div>
<style>
.box {
width: 100%;
display: grid;
grid-template-columns: 200px auto 200px;
grid-template-rows: 400px;
}
</style>
<div class="box">
<div class="left">200px</div>
<div class="right">200px</div>
<div class="center">自适应</div>
</div>
position: absolute
+ transform
.container {
position: relative;
}
.box {
position:absolute;
top:50%;
left:50%;
transform:translate(-50%, -50%);
/*已知高度宽度,margin-top margin-left设置为本身高度宽度的1/2负值*/
}
position: absolute
+ margin: auto
.container {
width: 500px;
height: 500px;
border: 1px solid #000;
position: relative;
}
.box {
width: 200px;
height: 200px;
border: 1px solid #000;
/*需知道子元素的宽高*/
position: absolute;
margin: auto;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
组合使用display:table-cell和vertical-align、text-align,使父元素内的所有行内元素水平垂直居中
/*利用 table 的单元格居中效果展示*/
.container {
width: 300px;
height: 300px;
border: 1px solid #000;
display: table-cell;
text-align: center;
vertical-align: middle;
}
.box {
width: 100px;
height: 100px;
display: inline-block;
}
.container {
display:flex;
justify-content: center;
align-items:center;
}
/*方法一:父元素指定子元素的对齐方式*/
.container {
width: 500px;
height: 500px;
display:grid;
justify-content: center;
/*整个内容区域在容器里面的水平位置*/
align-content: center;
/*整个内容区域的垂直位置*/
}
/*方法二:子元素自己指定自己的对齐方式*/
.out{
width: 300px;
height: 300px;
display: grid;
}
.inner{
width: 100px;
height: 100px;
justify-self: center;
/*设置单元格内容的水平位置*/
align-self:center;
/*设置单元格内容的垂直位置*/
}
盒子模型组成:分为内容(content)、填充(padding)、边框(border)和边界(margin)
IE盒模型:属性width,height包含content、border和padding
W3C标准盒模型:属性width,height只包含内容content,不包含border和padding
/*设置IE模型*/
box-sizing: border-box;
/*设置标准模型*/
box-sizing: content-box;
页面的基本单位是Box, 而元素的类型和 display 属性,决定了 Box 的类型
不同类型的 Box 会参与不同的 Formatting Context ,Box内的元素会以不同的方式渲染
Formatting Context —— CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用
block-level box
inline-level box
run-in box
(1)根元素
(2)浮动元素float=left|right或inherit(≠none)
(3)绝对定位元素position=absolute或fixed
(4)overflow=hidden|auto或scroll(≠visible)
(5)display=inline-block|flex|inline-flex|table-cell或table-caption
包含浮动元素(清除浮动)
浮动元素会脱离文档流(绝对定位元素也会脱离文档流),导致无法计算准确的高度,这种问题称为高度塌陷
解决高度塌陷问题的前提是能够识别并包含浮动元素,也就是清除浮动
解决方法:在容器(container)中创建 BFC
避免外边距折叠
外边距折叠(Margin collapsing)只会发生在属于同一BFC的块级元素之间。如果它们属于不同的 BFC,它们之间的外边距则不会折叠
绑定监听函数
<button onclick="handleClick()">Press me</button>
element.onclick = function(){}
删除事件处理
element.onclick = null
事件不会传播,即没有事件流的概念
绑定监听函数
element.addEventListener(‘click‘, function(){}, false)
删除事件处理
element.removeEventListener(‘mousedown‘, handleMouseDown, false)
可以添加多个相同事件的处理程序
事件传播:2级DOM的事件传播分三个阶段进行
当一个事件被触发时,会创建一个事件对象(Event Object), 这个对象里面包含了与该事件相关的属性或者方法。该对象会作为第一个参数传递给监听函数
type
用于获取事件类型target
获取事件目标stopPropagation()
阻止事件冒泡preventDefault()
阻止事件默认行为type
用于获取事件类型srcElement
获取事件目标cancelBubble
阻止事件冒泡returnValue
阻止事件默认行为<ul id="parent">
<li class="child">one</li>
<li class="child">two</li>
<li class="child">three</li>
</ul>
<script type="text/javascript">
//父元素
var dom= document.getElementById(‘parent‘);
//父元素绑定事件,代理子元素的点击事件
dom.onclick= function(event) {
var event= event || window.event;
var curTarget= event.target || event.srcElement;
if (curTarget.tagName.toLowerCase() == ‘li‘) {
//事件处理
}
}
</script>
var event= new Event(‘build‘);
// listener for the event
element.addEvenetListener(‘build‘, function(e) {...}, false);
//Dispatch the event
element.dispatchEvent(event);
__proto__
属性,用来指向构造函数的原型对象
Object.getPrototypeOf(obj)
返回指定对象的原型(内部[[Prototype]]
属性的值)Object.prototype
,叫做原型链instanceof
用于检测构造函数的 prototype
属性是否出现在某个实例对象的原型链上
typeof
null
返回 "object"
,其他的正确返回"function"
,其他的返回 "object"
instanceof
Date instanceof Object
Object.prototype.toString.call(..)
——tpyeof
返回 object
的对象,内部具有[[class]]属性用于进一步区分类型
Object.prototype.toString.call( [1,2,3] ); //"[object Array]"
variableName === void 0
—— 判断是否等于 undefinedfunction Person(name, age){
this.name = name;
this.age = age;
}
function _new() {
//1.获取构造函数
let Func = [].shift.call(arguments)
//2.创建一个空对象obj,并让其继承Func.prototype
let obj = Object.create(Func.prototype)
// var obj = {}
// obj.__proto__ = Func.prototype
//3.执行构造函数,并将this指向创建的空对象obj
let res = Func.apply(obj, arguments)
//4.如果构造函数返回的值是对象则返回,不是对象则返回创建的对象obj
return typeof res === ‘object‘ ? res : obj
}
var p1 = _new(Person, ‘小鱼‘, 18)
Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的
__proto__
function createPerson(name, age, job) {
let o = new Object()
o.name = name
o.age = age
o.job = job
o.sayName() {
console.log(this.name);
}
return o
}
var p1 = createPerson(‘小鱼‘,18,‘web‘);
p1.sayName(); //小鱼
var p2 = createPerson(‘xiaoyu‘,22,‘java‘);
p2.sayName(); //xiaoyu
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
this.sayName = function() {
console.log(this.name);
}
}
var p1 = new Person(‘小鱼‘, 18, ‘Web‘);
var p2 = new Person(‘xiaoyu‘, 22, ‘java‘);
//创建对象具有特定类型
p1.constructor === Person //true
//不同的实例上的同名函数是不相等的
p1.sayName === p2.sayName;
如果将构造函数中的函数定义为全局的函数,可以解决同名函数不共享的问题。但是破坏了自定义类型的封装性
function Person() {}
Person.prototype = {
name:‘小鱼‘,
age:18,
job:‘Web‘,
sayName:function(){
console.log(this.name);
}
};
var p1 = new Person();
console.log(p1.constructor); //[Function: Object]
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.friends = [‘Shelby‘,‘Court‘];
}
Person.prototype = {
constructor:Person,
sayName:function(){
console.log(this.name);
}
};
var p1 = new Person(‘小鱼‘,18,‘Web‘);
var p2 = new Person(‘xioayu‘,22,‘Java‘);
p1.friends.push(‘biu‘);
console.log(p1.friends); //[ ‘Shelby‘, ‘Court‘, ‘biu‘ ]
console.log(p2.friends); //[ ‘Shelby‘, ‘Court‘ ]
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.friends = [‘Shelby‘,‘Court‘];
if(typeof this.sayName !== ‘function‘){
Person.prototype.sayName = function(){
console.log(this.name);
}
}
}
var p1 = new Person(‘小鱼‘, 18,‘Web‘);
p1.sayName(); //小鱼
借用构造函数:在子类构造函数内部调用超类构造函数
function Parent(name, friends) {
this.name = name
this.friends = friends // ?? 可以定义私有 引用类型不会被共享
this.share = share // ? 可以定义公有 但需要放在外部
this.log = log // ? 避免重复声明,为了复用需要放在外面
}
// ? 公有属性和方法定义在外面失去了封装性
let share = [1, 2, 3]
function log() {
return this.name
}
function Child(name, friends, gender) {
Parent.call(this, name, friends) // ?? 可以在子类传递参数给父类
this.gender = gender
}
原型链模式:通过将子类的原型指向父类的实例实现继承,注意此时子类的constructor
指向了父类
需要手动重新绑定 constructor 而且不能定义私有变量
function Parent() {}
Parent.prototype = {
constructor: Parent, // ? 需要手动绑定 constructor
name: ‘oli‘, // ? 不能定义私有属性,全部都是公有
friends: [‘alice‘, ‘troy‘], // ?? 可以定义公有属性 所有实例都引用这个
log: function() { // ?? 方法被共享了
return this.name
}
}
function Child() {} // ? 没办法向父类传递参数
Child.prototype = new Parent() // 使用 new 操作符创建并重写 prototype
Child.prototype.constructor = Child // ? 每次继承都需要手动修改 constructor
组合继承模式:上面两者结合,使用原型链实现对原型属性和方法的继承,通过借用构造函数实现对实例属性的继承
function Parent(name, friends) {
// ?? 私有的写这里
this.name = name // ?? 可以定义私有属性
this.friends = friends // ?? 可以定义公有引用属性不会被共享
}
Parent.prototype = {
// ?? 公有的写这里
constructor: Parent, // ? 需要手动绑定 constructor
share: [1, 2, 3], // ?? 这里定义的公有属性会被共享
log: function() { // ?? 方法被共享了
return this.name
}
}
// ? 封装性一般
function Child(name, friends, gender) {
Parent.call(this, name, friends) // ?? 可以向父类传递参数 ? 调用一次 Parent
this.gender = gender
}
Child.prototype = new Parent() // 使用 new 操作符创建并重写 prototype ? 调用一次 Parent
Child.prototype.constructor = Child // ? 每次继承都需要手动修改 constructor
原型式继承直接使用 ES5 Object.create
方法,
创建一个新对象,使用现有的对象来提供新创建的对象的
__proto__
该方法的原理是创建一个构造函数,构造函数的原型指向对象,然后调用 new 操作符创建实例,并返回这个实例,本质是一个浅拷贝
let parent = {
name: ‘parent‘,
share: [1, 2, 3], // ? 父类的引用属性全部被子类所共享
log: function() { // ?? 父类方法可以复用
return this.name
}
}
let child = Object.create(parent) // ? 子类不能向父类传递参数
原型式继承的基础上为子类增加属性和方法
let parent = {
name: ‘parent‘,
share: [1, 2, 3],
log: function() {
return this.name
}
}
function create(obj) {
let clone = Object.create(obj) // 本质上还是 Object.create
clone.print = function() { // 增加一些属性或方法
console.log(this.name)
}
return clone
}
let child = create(parent)
杂糅了原型链式、构造函数式、组合式、原型式、寄生式而形成的一种方式:
不必为了指定子类的原型而调用超类的构造函数,需要的无非就是超类原型的一个副本而已
组合继承的方法会调用两次 Parent,一次是在
Child.prototype = new Parent()
,一次是在Parent.call()
。寄生组合式解决了这个问题
function Parent(name, friends) {
this.name = name // ?? 可以定义私有属性
this.friends = friends // ?? 可以定义公有引用属性不会被共享
}
Parent.prototype = {
constructor: Parent, // ? 需要手动绑定 constructor
share: [1, 2, 3], // ?? 这里定义的公有属性会被共享
log: function() { // ?? 方法被共享了
return this.name
}
}
function Child(name, friends, gender) {
Parent.call(this, name, friends) // ?? 可以向父类传递参数 ? 调用了一次 Parent
this.gender = gender
}
function inherit(child, parent) {
let clonePrototype = Object.create(parent.prototype) //创建父类的原型副本
child.prototype = clonePrototype //改变子类的原型
child.prototype.constructor = child //纠正子类的构造函数
}
inherit(Child, Parent)
提供4个关键字,用于解决上面问题
class
——类声明constructor
——构造函数的声名extends
——继承super
——超类/父类class Parent {
constructor(name, friends) { // 该属性在构造函数上,不共享
this.name = name
this.friends = friends
}
log() { // 该方法在原型上,共享
return this
}
}
Parent.prototype.share = [1, 2, 3] // 原型上的属性,共享
class Child extends Parent {
constructor(name, friends, gender) {
super(name, friends)
this.gender = gender
}
}
继承方式 | 优点 | 缺陷 |
---|---|---|
借用构造函数 | 1.可以定义私有属性 2.子类可以向父类传参 |
1.不能定义公共属性和方法 2.或在在外部失去封装性 |
原型链继承 | 1.可以定义公共属性和方法 | 1.不能定义私有属性和方法 2.不可以向父类传参 3.需要修改子类的constructor |
组合继承 | 1.私有的在构造函数 2.公共的在原型 3.可以向父类传参 |
1.需要修改子类的constructor 2.创建子类调用两次父类的构造函数 |
原型式继承 | 1.父类方法可以复用 | 1.父类引用属性全部被共享 2.不可以向父类传参 |
寄生式继承 | 1.父类方法可以复用 2.增加其他属性和方法 |
1.父类引用属性全部被共享 2.不可以向父类传参 |
寄生组合继承 | 1.相比组合继承不会重复调用父类 | 1.需要修改子类的constructor 2.调用额外的方法封装性一般 |
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。查看同源策略-MDN
同源策略是浏览器的安全功能用于隔离潜在恶意文件,如果缺少同源策略浏览器容易受到XSS,CSFR等攻击
所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源
Cookie、LocalStorage、IndexDB 无法获取
访问存储在浏览器中的数据,如 localStorage 和 IndexedDB,是以源进行分割。每个源都拥有自己单独的存储空间,一个源中的 JavaScript 脚本不能对属于其它源的数据进行读写操作
Cookies 使用不同的源定义方式。一个页面可以为本域和其父域设置 cookie
DOM 无法获取
Ajax 请求不能发送(Ajax 只限于同源使用,不能跨域使用)
前端安全分两类:CSRF、XSS
常考点:基本概念和缩写、攻击原理、防御措施
<!DOCTYPE>
声明叫做文件类型定义(DTD)<!DOCTYPE>
声明必须在 HTML 文档的第一行,并不是 HTML 标签严格模式:
混杂模式(quirks mod)
关键渲染路径(Critical Rendering Path)是指与当前用户操作有关的内容
例如用户刚刚打开一个页面,首屏的显示就是当前用户操作相关的内容,具体就是浏览器收到 HTML、CSS 和 JavaScript 等资源并对其进行处理从而渲染出 Web 页面
了解浏览器渲染的过程与原理,很大程度上是为了优化关键渲染路径例如为了保障首屏内容的最快速显示,通常会提到渐进式页面渲染
从耗时的角度,浏览器请求、加载、渲染一个页面需要花费时间在 DNS 查询、TCP 连接、发送HTTP 请求、服务器处理请求返回报文、客户端解析渲染页面
DNS 解析
DNS解析就是网址到IP地址的转换的过程
->
操作系统
C:\Windows\System32\drivers\etc
->
根域名服务器 ->
COM顶级域名服务器建立TCP连接——三次握手
SYN=1
字段和客户端序列号 seq=n
,并进入SYN_SENT状态,等待服务器确认;SYN
字段,返回 SYN=1
表示同意建立连接 ack=n+1
用于确定收到客户端信息和服务端本身的序号 seq=x
,此时服务器进入SYN_RECV状态;ack=x+1
,此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手客户端 -> 服务端:SYN=1(请求进行连接) seq=n(序列号)
服务端 -> 客户端:SYN=1(同意建立连接) ack=n+1(确认收到信息) seq=x(服务端序列号)
客户端 -> 服务端:SYN=0(开始发送信息) ack=x+1(确认收到信息) seq=n+1
客户端发送HTTP 请求
http请求报文
切割为报文段
,并在各个报文上打上标记序号以及端口号,将每个报文段可靠地传给网络层
网络层
通过ip地址找到mac地址(ARP协议
,解析地址,根据通信方的ip地址反查出对应的MAC地址),在各个路由中间进行路由中转
传送到数据链路层
服务器处理请求返回报文
客户端解析渲染页面
断开连接——四次挥手
浏览器从网络或硬盘中获得HTML字节数据后会经过以下流程将字节解析为DOM树:
<html>
、<body>
、<p>
等标签以及标签中的字符串和属性等都会被转化为令牌,每个令牌具有特殊含义和规则)字节 -> 字符 -> 令牌-> 节点对象 -> 对象模型
浏览器解析遇到<link>
标签时,浏览器就开始解析CSS,像构建DOM树一样构建CSSOM树
在构建了DOM树和CSSOM树之后,浏览器只是拥有2个相互独立的对象集合,DOM树描述的文档结构和内容,CSSOM树描述了对应文档的样式规则
想要渲染出页面,就需要将DOM树、CSSOM树结合在一起,构建Render Tree渲染树
渲染树构建好后,浏览器得到了每个节点的内容与样式,下一步就是需要计算每个节点在浏览器窗口的确切位置与大小,即layout布局
布局阶段,从渲染树的根节点开始遍历,采用盒子模型的模式来表示每个节点与其他元素之间的距离,从而确定每个元素在屏幕内的位置与大小
当Layout布局完成后,浏览器会立即发出Paint事件,开始将渲染树绘制成像素,绘制所需要的时间跟CSS样式的复杂度成正比,绘制完成后,用户才能看到页面在屏幕中的最终呈现效果
通过优化渲染关键路径,可以优化页面渲染性能,减少页面白屏时间
<script>
标签添加异步属性async
,这样浏览器的HTML解析就不会被js文件阻塞<link>
标签时,浏览器就需要向服务器发出请求获得CSS文件,然后才继续构建DOM树和CSSOM树,可以合并所有CSS成一个文件,减少HTTP请求,减少关键资源往返加载的时间,优化渲染速度回流必将引起重绘,重绘不一定会引起回流。回流的成本比重绘高很多
当元素的几何尺寸或结构发生改变,需要对Render Tree
重新验证并计算。浏览器重新渲染部分或全部文档
回流需要重新计算Render Tree
而每一个DOM Tree
都有一个reflow
方法
一旦某个节点发生重排,就有可能导致子元素和父元素甚至是同级其他元素的reflow
导致回流的操作
DOM
元素CSS
伪类(例如::hover
)导致回流的属性和方法
当页面中元素样式的改变并不影响它在文档流中的位置时称为重绘
例如:color
、background-color
、visibility
等,浏览器会将新样式赋予给元素并重新绘制
导致重绘的属性和方法
CSS
absolute / fixed
属性CSS
表达式(例如:calc()
)dispaly:none
,可以使用visibility:hidden
代替,dispaly:none
会造成重排,visibility:hidden
会造成重绘table
布局style
属性,通过style
属性改变样式触发重排。JavaScript
resize
事件时,做防抖和节流处理DOM
,创建一个documentFragment
,在它上面应用所有DOM操作
,最后再把它添加到文档中浏览器的渲染进程是多线程的
setInterval
与setTimeout
所在线程单线程是指在 JavaScript 引擎中负责解释和执行 JavaScript 代码的线程唯一,同一时间上只能执行一件任务
单线程为了防止防止的同步问题,如一个线程在某个DOM节点上添加内容,另一个线程删除该节点
为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM
调用栈是解释器(如浏览器中 JavaScript 解释器)追踪函数执行流的一种机制
也称执行栈,拥有后进先出(LIFO)的数据结构,被用来存储代码运行时创建的所有执行上下文
JvaScript 是一种单线程编程语言,这意味着它只有一个 Call Stack 。因此,它一次仅能做一件事
当V8引擎遇到你编写的代码时,会创建全局的执行上下文并压入当前调用栈中,每当引擎遇到一个函数调用,它会为该函数创建一个新的函数执行上下文并压入栈的顶部
引擎会执行位于栈顶的函数,正在调用栈中执行的函数如果调用了其他函数,新函数也将添加到调用栈顶,立即执行
当前函数执行完毕后,解释器将该函数执行上下文从栈中弹出,继续执行当前执行环境下的剩余的代码
当分配的调用栈空间被占满时,会引发“堆栈溢出”错误
function first() {
console.log(‘Inside first function‘);
second();
}
function second() {
console.log(‘Inside second function‘);
}
first();
由于 JavaScript 单线程,理论上当某段代码运行变慢(比如网络请求、下载图片)时就会发生阻塞,导致浏览器不能执行后面的简单操作。所以任务分为同步任务和异步任务
任务队列
,存在于任务队列(task queue)的任务为异步任务异步执行的运行机制
一旦执行栈
中的所有同步任务执行完毕,系统就会读取任务队列
,将可运行的异步任务添加到可执行栈中,开始执行
异步与事件
消息队列中的每条消息实际上都对应着一个事件,DOM事件是一个重要的异步过程
var button = document.getElementById(‘button‘)
button.addEventListener(‘click‘, function(e) {
console.log(‘事件‘)
})
从异步的角度看,addEventListener
函数就是异步过程的发起函数,事件监听器函数就是异步过程的回调函数。
事件触发时,表示异步任务完成,会将事件监听器函数封装成一条消息放在消息队列中,等待主线程执行。
除了广义的同步任务和异步任务,我们对任务有更精细的定义
不同类型的任务会进入对应的Event Queue
事件循环的顺序
当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完全加载
当整个页面及所有依赖资源如样式表和图片都已完成加载时,将触发load事件
defer
脚本会在DOMContentLoaded
和load
事件之前执行async
会在load
事件之前执行,但并不能确保与DOMContentLoaded
的执行先后顺序绿色线代表 HTML 解析,蓝色线代表网络读取,红色线代表执行时间,蓝红线是针对脚本的;
//强制打开 <a> 标签的 dns 解析
<meta http-equiv="x-dns-prefetch-controller" content="on">
//DNS预解析
<link rel="dns-prefetch" href="//host_name_to_prefetch.com">
dns-prefeth
使得域名转化ip地址的工作提前进行,缩短了请求资源的耗时
什么时候使用呢?在页面中使用其他域名的资源时,可以将静态资源放在cdn上,就可以对cdn的域名进行预解析
用于声明块级作用域的变量且不具备变量提升
let
用于声明变量const
用于声明常量, 一经声明不能改变
数组的结构赋值——数组是按位置匹配
let [a, b, c] = [1, 2, 3];
对象的结构赋值——对象是按属性名匹配
let { bar, foo } = { foo: ‘aaa‘, bar: ‘bbb‘ };
交换变量的值—— [a,b] = [b,a]
服务器返回数据时,提取 JSON 数据—— let {data, code} = res
输入模块的指定方法
const { SourceMapConsumer, SourceNode } = require("source-map");
使得字符串的拼接更加的简洁,支持变量、HTML文档与换行
let a = "小鱼"
let b = `你好,${name}`
用于简化函数表达式和改善函数this指向的问题
箭头函数的
this
是在定义函数时绑定的,不是在执行过程中绑定的函数在定义时,
this
就继承了定义函数的对象。this
一旦确定以后不会改变
var sum = (num1, num2) => num1 + num2;
用于函数(剩余参数)——用于获取函数的多余参数,不需要使用arguments
对象
function add(...values) {
let sum = 0;
for (var val of values) { //数组
sum += val;
}
return sum;
}
用于数组或字符串——将内容依次取出
var str = "asdfghjkl"
console.log(...str) //a s d f g h j k l
var arr = [1,2,3,4,5,6]
console.log(...arr) //1 2 3 4 5 6
//复制数组
let arr2 = [...arr1]
//合并数组
[...arr1, ...arr2, ...arr3]
用于对象——克隆或者属性拷贝
var obj1 = { foo: ‘bar‘, x: 42 };
var obj2 = { foo: ‘baz‘, y: 13 };
var clonedObj = { ...obj1 };
// 克隆后的对象: { foo: "bar", x: 42 }
var mergedObj = { ...obj1, ...obj2 };
// 合并后的对象: { foo: "baz", x: 42, y: 13 }
让面向对象编程变得更加简单和易于理解
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
sayHi() {
alert(`my name is ${this.name}`)
}
}
class Worker extends Person {
constructor(name,age,job) {
super(name,age)
this.job = job
}
sayJob() {
alert(`my job is ${this.job}`)
}
}
每一个模块都有自己单独的作用域
模块的功能主要由 export 和 import 组成
异步编程的一种解决方案,比传统的解决方案callback更加的优雅
Promise
是一个容器,保存着在某个未来结束的异步操作的结果
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
promise.then().catch().finally()
成功调用 resolve
,失败调用 reject
.then
获取结果,.catch
捕获异常。捕获异常还可通过 .then
的第二个参数
.finally
无论成功失败都一定会调用
多个并发的请求,用 Promise.all()
let p = Promise.all([p1,p2,p3])
p.then(([res1, res2,res3]) => {};
p1
、p2
、p3
的状态都变成fulfilled
,p
的状态才会变成fulfilled
,此时p1
、p2
、p3
的返回值组成一个数组,传递给p
的回调函数p1
、p2
、p3
之中有一个被rejected
,p
的状态就变成rejected
,此时第一个被reject
的实例的返回值,会传递给p
的回调函数async
函数的返回值是 Promise 对象await
只能出现在 async 函数中const axios = require("axios");
async function getZhihuTopSearch(id) {
const url = "https://www.zhihu.com/api/v4/search/top_search";
//将异步操作的值赋给变量
const response = await axios(url);
console.log(response);
}
getZhihuTopSearch(5);
https://juejin.im/post/5d59f2a451882549be53b170
标签:await 影响 第三方 阶段 事件处理器 破坏 转化 重载 描述
原文地址:https://www.cnblogs.com/zengbin13/p/13384133.html