一. 变量
1.var
特点 :1.全局作用域,2.会提升变量,3.可以重新声明
console.log(a);
var a = 10
var a = 20
console.log(a);
在a变量声明之前就打印 不会报错(变量提升到顶端)
2.let
特点:1.块级作用域 2.不会提升变量 3.不能重新声明 4.可以重新赋值
3.const
特点:1.块级作用域 2.不会提升变量 3.不能重新声明 4.不能重新赋值 5.必须在声明时赋值
6.对象可以修改属性,不能重新赋值(不能更换对象) 7.数组元素可以更改添加删除,不能重新赋值数组
可以更改对象属性:
// 您可以创建 const 对象:
const car = {type:"porsche", model:"911", color:"Black"};
// 您可以更改属性:
car.color = "White";
// 您可以添加属性:
car.owner = "Bill";
不能更换对象:
const car = {type:"porsche", model:"911", color:"Black"};
car = {type:"Volvo", model:"XC60", color:"White"}; // ERROR
二. 运算符
1. 算数运算符
运算符 | 描述 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法 |
** | 幂(ES2016) |
/ | 除法 |
% | 系数 |
++ | 递增 |
-- | 递减 |
2. 赋值运算符
运算符 | 例子 | 等同于 |
---|---|---|
= | x = y | x = y |
+= | x += y | x = x + y |
-= | x -= y | x = x - y |
*= | x *= y | x = x * y |
/= | x /= y | x = x / y |
%= | x %= y | x = x % y |
3. 字符串运算符
+
运算符也可用于对字符串进行相加,不过在es6之后推荐使用``模板字符串
4. 字符串和数字的相加
数字和字符串相加,结果将是字符串
z = "Hello" + 7;//Hello7
遵循从左到右的顺序计算
let x = 911 + 7 + "hello";//918hello
5. 比较运算符
运算符 | 描述 |
---|---|
== | 等于 |
=== | 等值等型 |
!= | 不相等 |
!== | 不等值或不等型 |
> | 大于 |
< | 小于 |
>= | 大于或等于 |
<= | 小于或等于 |
? | 三元运算符 |
6. 逻辑运算符
运算符 | 描述 |
---|---|
&& | 逻辑与 |
|| | 逻辑或 |
! | 逻辑非 |
7. typeof 运算符
返回数据类型
8. constructor
返回所有 JavaScript 变量的构造器函数 可用于判断变量类型
"Bill".constructor // 返回 "function String() { [native code] }"
(3.14).constructor // 返回 "function Number() { [native code] }"
false.constructor // 返回 "function Boolean() { [native code] }"
[1,2,3,4].constructor // 返回 "function Array() { [native code] }"
{name:'Bill', age:62}.constructor // 返回" function Object() { [native code] }"
new Date().constructor // 返回 "function Date() { [native code] }"
function () {}.constructor // 返回 "function Function(){ [native code] }"
三. 数据类型
- 基本数据类型: Number、String、Boolean、Null、 Undefined、Symbol(ES6)
-
引用数据类型: Object (在JS中除了基本数据类型以外的都是对象, Object是个大类,function函数、array数组、date日期...等都归属于Object)
Undefined的数据类型是Undefined
null的数据类型是 Object
四. 字符串String
1. length
获取字符串长度
2. indexOf()
字符串中指定文本首次出现的索引,如果未找到文本返回-1,接受第二个参数作为搜索的开始位置
3. lastIndexOf()
字符串中指定文本最后一次出现的索引,,如果未找到文本返回-1,接受第二个参数作为搜索的开始位置,从末尾到开头开始搜索,如果第二个参数是 15
,则从位置 15 开始搜索,一直搜索到字符串的开头。
4. search()
搜索特定值的字符串,并返回匹配的位置,不能设置第二个参数,可以搜索正则表达式
5. slice(start,end)
提取字符串的某个部分并在新字符串中返回被提取的部分,如果省略第二个参数,则该方法将裁剪字符串的剩余部分
6. substring(start,end)
类似于slice(start,end)
7. substr(start,length)
类似于slice(start,end),不同之处在于第二个参数规定被提取部分的长度,如果省略第二个参数,则该 substr() 将裁剪字符串的剩余部分,如果首个参数为负,则从字符串的结尾计算位置,第二个参数不能为负,因为它定义的是长度
8. replace()
用另一个值替换在字符串中指定的值,对字符串大小写敏感,默认只替换首个
如需执行大小写不敏感的替换,请使用正则表达式 /i
(大小写不敏感),请注意正则表达式不带引号
str = "Please visit Microsoft!";
var n = str.replace(/MICROSOFT/i, "W3School");
如需替换所有匹配,请使用正则表达式的 g
标志(用于全局搜索)
str = "Please visit Microsoft and Microsoft!";
var n = str.replace(/Microsoft/g, "W3School");
9. toUpperCase()
把字符串转换为大写
10. toLowerCase()
把字符串转换为小写
11. trim()
删除字符串两端的空白符
12. charAt()
字符串中指定下标(位置)的字符串
13. charCodeAt()
符串中指定索引的字符 unicode 编码
14. split()
将字符串分割为数组,参数是分隔符
let txt = "a,b,c,d,e"; // 字符串
txt.split(","); // 用逗号分隔 结果:[ 'a', 'b', 'c', 'd', 'e' ]
15. match()
match() 方法根据正则表达式在字符串中搜索匹配项,并将匹配项作为 Array 对象返回。
let text = "The rain in SPAIN stays mainly in the plain";
let f = text.match(/ain/g) // 返回数组 [ain,ain,ain]
16. includes()
字符串是否包含指定值。接受第二个参数作为搜索的开始位置
17. startsWith()
字符串是否以指定值开头.接受第二个参数作为搜索的开始位置,不区分大小写
let text = "Hello world, welcome to the universe.";
text.startsWith("world", 6) // 返回 true
18. endsWith()
字符串是否以指定值结尾,接受第二个参数作为字符串长度,区分大小写
let text = "Hello world, welcome to the universe.";
text.endsWith("world", 11) // 返回 true
五. 模板字符串
反引号 (``)
字符串插值
${...}
可以替换变量,也可以替换表达式
六. Number
1. toString() 返回字符串
2. toFixed() 返回字符串 可以指定小数的位数
let x = 9.656;
x.toFixed(0); // 返回 10
x.toFixed(2); // 返回 9.66
x.toFixed(4); // 返回 9.6560
x.toFixed(6); // 返回 9.656000
3. toPrecision() 返回字符串 指定字符串的长度
var x = 9.656;
x.toPrecision(); // 返回 9.656
x.toPrecision(2); // 返回 9.7
x.toPrecision(4); // 返回 9.656
x.toPrecision(6); // 返回 9.65600
4. Number() 全局方法 用于把 JavaScript 变量转换为数值,还可以把日期转换为数字
Number(new Date("2019-04-15")); // 返回 1506729600000
5.parseInt() 全局方法 解析一段字符串并返回数值。允许空格。只返回首个数字,如果无法转换为数值,则返回 NaN
parseInt("10"); // 返回 10
parseInt("10.33"); // 返回 10
parseInt("10 20 30"); // 返回 10
parseInt("10 years"); // 返回 10
parseInt("years 10"); // 返回 NaN
6.parseFloat() 全局方法 解析一段字符串并返回数值。允许空格。只返回首个数字,如果无法转换为数值,则返回 NaN
parseFloat("10"); // 返回 10
parseFloat("10.33"); // 返回 10.33
parseFloat("10 20 30"); // 返回 10
parseFloat("10 years"); // 返回 10
parseFloat("years 10"); // 返回 NaN
七. 数组
创建:let cars = [],通过下标访问数组的元素,数组元素可以是对象,数组只能使用数字索引
1. length 数组的长度
2. 判断变量是否是数组
let fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits instanceof Array // 返回 true
2. toString() 转化成字符串
3. join() 将所有数组元素结合为一个字符串,与toString()区别是可以添加分割符号
let fruits = ["Banana", "Orange","Apple", "Mango"];
fruits.join(" * "); //Banana * Orange * Apple * Mango
4. pop() 从数组中删除最后一个元素,返回“被弹出”的值
5. push() 向数组队尾添加一个新的元素
6. shift() 删除首个数组元素,并把所有其他元素“位移”到更低的索引,返回被“位移出”的字符串
7. unshift() 添加首个数组元素
8. splice() 可以用来删除/添加 指定位置元素
删除 splice(0,1) 第一个参数表示删除的位置,第二个表示删除的长度
增加 splice(4,0,P,P,P) 第一个参数表示删除的位置,第二个表示删除的长度,为0不删除,后面的参数是增加的元素
替换 splice(4,2,P,P,P) 第一个参数表示删除的位置,第二个表示删除的长度,后面的参数是增加的元素
9. concat() 拼接数组
concat不会改变原数组,返回一个新数组
10. slice(start,end) 数组的某个片段切出新数组
11. sort() 以字母顺序对数组进行排序
数字排序:
let points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return a-b});
对象数组排序:
let cars = [
{type:"Volvo", year:2016},
{type:"Saab", year:2001},
{type:"BMW", year:2010}
];
cars.sort(function(a, b){return a.year - b.year});
console.log(cars);
获取最大值,可以使用math
let points = [40, 100, 1, 5, 25, 10];
let max =Math.max.apply(null, points)
12. reverse() 反转数组
13. forEach()
let txt = "";
let numbers = [45, 4, 9, 16, 25];
numbers.forEach(myFunction);
function myFunction(value, index, array) {
txt = txt + value + "<br>";
}
三个参数:元素值,元素索引,数组本身. index 和 array可省略
14. map()
对数组每个元素执行函数来创建新数组, index 和 array可省略
let numbers1 = [45, 4, 9, 16, 25];
let numbers2 = numbers1.map(myFunction);
function myFunction(value, index, array) {
return value * 2;
}
15. filter()
对数组每个元素过滤来创建新数组, index 和 array可省略
let numbers = [45, 4, 9, 16, 25];
let over18 = numbers.filter(myFunction);
function myFunction(value, index, array) {
return value > 18;
}
16. reduce()
在每个数组元素上运行函数,以生成单个值,第二个参数可以省略
let numbers1 = [45, 4, 9, 16, 25];
let sum = numbers1.reduce(myFunction, 100);
function myFunction(total, value) {
return total + value;
}
17. every(),some() 和 find()
与filter()类似
18. indexOf()
在数组中搜索元素值并返回其位置,如果未找到项目,Array.indexOf()
返回 -1,如果项目多次出现,则返回第一次出现的位置
19. lastIndexOf()
从数组结尾开始搜索
array.lastIndexOf(item, start)
20. findIndex()
返回通过测试函数的第一个数组元素的索引
21. includes()
检查元素是否存在于数组中
八. 日期
有 4 种方法创建新的日期对象:
- new Date() 用当前日期和时间创建新的日期对象
- new Date(year, month, day, hours, minutes, seconds, milliseconds) 用指定日期和时间创建新的日期对象
- new Date(milliseconds) 从日期字符串创建一个新的日期对象
- new Date(date string)
日期格式:
类型 | 实例 |
---|---|
ISO 日期 | "2018-02-19" (国际标准) |
短日期 | "02/19/2018" 或者 "2018/02/19" |
长日期 | "Feb 19 2018" 或者 "19 Feb 2019" |
完整日期 | "Monday February 25 2015" |
获取日期的某个部分:
方法 | 描述 |
---|---|
getDate() | 以数值返回天(1-31) |
getDay() | 以数值获取周名(0-6) |
getFullYear() | 获取四位的年(yyyy) |
getHours() | 获取小时(0-23) |
getMilliseconds() | 获取毫秒(0-999) |
getMinutes() | 获取分(0-59) |
getMonth() | 获取月(0-11) |
getSeconds() | 获取秒(0-59) |
getTime() | 获取时间(从 1970 年 1 月 1 日至今) |
日期设置方法:
方法 | 描述 |
---|---|
setDate() | 以数值(1-31)设置日 |
setFullYear() | 设置年(可选月和日) |
setHours() | 设置小时(0-23) |
setMilliseconds() | 设置毫秒(0-999) |
setMinutes() | 设置分(0-59) |
setMonth() | 设置月(0-11) |
setSeconds() | 设置秒(0-59) |
setTime() | 设置时间(从 1970 年 1 月 1 日至今的毫秒数) |
九.Math
Math.round(x)
的返回值是 x 四舍五入为最接近的整数
Math.pow(x, y)
的返回值是 x 的 y 次幂
Math.sqrt(x)
返回 x 的平方根
Math.abs(x)
返回 x 的绝对(正)值
Math.ceil(x)
向上取整
Math.floor(x)
向下取整
Math.min()
和 Math.max()
可用于查找参数列表中的最低或最高值
Math.random()
返回介于 0(包括) 与 1(不包括) 之间的随机数
Math.floor(Math.random() * 10);//返回0-9之间随机整数
十. 循环语句
for
- 多次遍历代码块for/in
- 遍历对象属性while
- 当指定条件为 true 时循环一段代码块do/while
- 当指定条件为 true 时循环一段代码块,不管条件是否为真都会执行一遍for/of
- 循环遍历可迭代对象的值
十一. 正则表达式
语法:/pattern/modifiers;
i:忽略大小写
g:全局匹配
m:多行匹配
test() 它通过模式来搜索字符串,然后根据结果返回 true 或 false。
exec() 指定的模式(pattern)搜索字符串,并返回已找到的文本,如果未找到匹配,则返回 null
十二. 代码规范
1. 对标识符名称(变量和函数)使用了驼峰式大小写
2. 所有名称以字母开头
3. 始终在运算符( = + - * / )周围以及逗号之后添加空格
4. 请始终使用对代码块缩进使用 4 个空格
5. 简单语句 请始终以分号结束单条语句
6. 复杂语句(compound)的通用规则:
- 请在第一行的结尾处写大括号
- 请在大括号前使用一个空格
- 请在新行上写闭括号,不带前导空格
- 请不要以分号来结束复杂语句
7. 对象定义的通用规则:
- 把大括号与对象名放在同一行
- 在每个属性与其值之间使用冒号加一个空格
- 不要在最后一个属性值对后面写逗号
- 请在新行上写闭括号,不带前导空格
- 请始终以分号结束对象定义
- 可以对短对象在一行中进行压缩,只在属性之间使用空格
十三. 对象
JSON.stringify()
对象/日期/数组 转换为字符串,当时不会对函数进行转换
const person = {
firstName : "Bill",
lastName : "Gates",
age: function () {return 19;}
};
console.log(JSON.stringify(person));//{"firstName":"Bill","lastName":"Gates"}
Object.values() 对象被转换为数组
Object.entries 返回对象中键/值对的数组
const fruits = {Bananas:300, Oranges:200, Apples:500};
console.log('entries',Object.entries(fruits));
console.log('values',Object.values(fruits));
结果:
entries [ [ 'Bananas', 300 ], [ 'Oranges', 200 ], [ 'Apples', 500 ] ]
values [ 300, 200, 500 ]
用大写首字母对构造器函数命名是个好习惯
Object.prototype:位于原型继承链的顶端,日期对象、数组对象和 Person 对象都继承自 Object.prototype ,用于添加给定类型的已有对象添加新属性(或方法)
Object.defineProperty() 更改对象属性
十四. Map 键值对集合
Method | Description |
---|---|
new Map() | 创建新的 Map 对象。 |
set() | 为 Map 对象中的键设置值。 |
get() | 获取 Map 对象中键的值。 |
entries() | 返回 Map 对象中键/值对的数组。 |
keys() | 返回 Map 对象中键的数组。 |
values() | 返回 Map 对象中值的数组。 |
clear() | 删除 Map 中的所有元素。 |
delete() | 删除由键指定的元素。 |
has() | 如果键存在,则返回 true。 |
forEach() | 为每个键/值对调用回调。 |
mapA.forEach((value, key, mapObj)=>{
//...
})
十五. set 集合
每个值在 Set 中只能出现一次
new Set() | 创建新的 Set 对象。 |
add() | 向 Set 添加新元素。 |
clear() | 从 Set 中删除所有元素。 |
delete() | 删除由其值指定的元素。 |
entries() | 返回 Set 对象中值的数组。 |
has() | 如果值存在则返回 true。 |
forEach() | 为每个元素调用回调。 |
keys() | 返回 Set 对象中值的数组。 |
values() | 与 keys() 相同。 |
size | 返回元素计数。 |
十六. 函数
参数: 如果调用参数时省略了参数(少于被声明的数量),则丢失的值被设置为:undefined
如果函数调用的参数太多(超过声明),则可以使用 arguments 对象来达到这些参数
函数可以作为另一个函数的参数,将函数作为参数传递时,请记住不要使用括号
function aaa(a,b,c,callback){
callback(a, a+b, a+b+c)
}
function bbb(a,b,c){
console.log(a, b, c);
}
aaa(1, 2, 3, bbb)//1 3 6
上面的例子就是回调,添加延迟,1s后才会输出 1 3 6,回调可以处理函数的异步
function aaa(a,b,c,callback){
setTimeout(()=>{
callback(a, a+b, a+b+c)
},1000)
}
function bbb(a,b,c){
console.log(a, b, c);
}
aaa(1, 2, 3, bbb)//1 3 6
十七.解构赋值
解构赋值分成对象解构赋值和数组解构赋值
对象解构赋值:
let obj = {
a: 'Tony',
b: 25,
}
let {a, b} = obj
console.log(a); // Tony
console.log(b); // 25
对象解构赋值时,赋值的变量需要用{}包裹,变量名称要与对象中属性保持一致,否则赋值为undfing
let obj = {
x: 'Tony',
b: 25,
}
let {a, b} = obj
console.log(a); // undefined
console.log(b); // 25
如果想改变名字,可以这样x:a,将对象属性x换成a
let obj = {
x: 'Tony',
b: 25,
}
let {x:a, b} = obj
console.log(a); // Tony
console.log(b); // 25
嵌套的对象结构,重命名
let obj = {
x: {
firstName: 'Tony',
familyName: 'Michael'
},
b: 25,
}
let {x:{firstName:a,familyName:c}, b} = obj
console.log(a); // Tony
console.log(c); // Michael
console.log(b); // 25
数组的解构赋值:赋值的变量需要用[]包裹,数组的解构根据数组位置进行赋值
let obj2 = ['Tony', 25, '男']
let [firstName, age, gender] = obj2
console.log(firstName); // Tony
console.log(age); // 25
console.log(gender); // 男
嵌套的数组解构,插入[]
let obj = ['Michael', 26, '女']
let obj2 = ['Tony', 25, '男']
let obj3 = [obj, obj2]
let [[firstName, age, gender], [firstName1, age1, gender1]] = obj3
console.log(firstName); // Michael
console.log(age); // 26
console.log(gender); // 女
console.log(firstName1); // Tony
console.log(age1); // 25
console.log(gender1); // 男
数组解构剩余项
let obj = ['Michael', 26, '女']
let obj2 = ['Tony', 25, '男']
let obj3 = [obj, obj2]
let [[firstName,...obj4], [firstName1, age1, gender1]] = obj3
console.log(firstName); // Michael
console.log(obj4); // [ 26, '女' ]
console.log(firstName1); // Tony
console.log(age1); // 25
console.log(gender1); // 男
数组结构可以用来交换两个变量:
let a = 1,
b = 2;
[b, a] = [a, b];
console.log(a, b); // 2 1
字符串也可以结构成单个字符
let hello = 'Hello'
let [a, b, c, d, e] = hello
console.log(a, b); // H e
混合解构(对象嵌套数组)
let obj = {
fullName: {
firstName: 'Tony',
familyName: 'Michael'
},
colour: ['red', 'black', 'blue']
}
let {fullName:{firstName:a,familyName:b},colour:[A, B, C]} = obj
console.log(a); // Tony
console.log(b); // Michael
console.log(A); // red
console.log(B); // black
console.log(C); // blue
混合解构(数组嵌套对象)
let obj = {
firstName: 'Tony',
age: 25
}
let obj2 = {
firstName: 'Michael',
age: 26
}
let obj3 = [obj,obj2]
let [{firstName, age}, {firstName:a, age:b}] = obj3
console.log(firstName); // Tony
console.log(age); // 25
console.log(a); // Michael
console.log(b); // 26
十八.Symbol
原始数据类型Symbol,Symbol值通过Symbol函数生成,属性名属于Symbol类型,Symbol值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型
let s = Symbol();
Symbol函数前不能使用new命令
Symbol函数可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分
Symbol函数的参数只是表示对当前Symbol值的描述,因此相同参数的Symbol函数的返回值是不相等的
let s1 = Symbol("foo");
let s2 = Symbol("foo");
console.log(s1 === s2); // false
由于每一个Symbol值都是不相等的,这意味着Symbol值可以作为标识符,用于对象的属性名,就能保证不会出现同名的属性。这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖
定义和使用Symbol属性
let mySymbol = Symbol('Hello');
let a = {
[mySymbol]: 'Hello 你好!'
};
console.log(a[mySymbol]); // Hello 你好!
Symbol作为属性名,该属性不会出现在for...in、for...of循环中,获取对象的所有Symbol属性名,使用Object.getOwnPropertySymbols
Symbol.for() 使用给定的key搜索现有符号,如果找到则返回符号。否则将得到一个新的使用给定的key在全局符号注册表中创建的符号。
调用Symbol.for("cat") 30次,每次都会返回同一个Symbol值,但是调用Symbol("cat") 30次,会返回30个不同的Symbol值
Symbol.keyFor(),为给定符号从全局符号注册表中检索一个共享符号键
十九. Generator
生成器 可以使函数一步一步执行
1. 创建 在函数名和funtion之间添加*号.不能使用箭头函数
2. 最标记 yield 每次执行遇到yield标记函数就暂停
3.执行 函数调用之后不会立即执行 需要使用next()执行下一步,next方法可以带一个参数,参数被当做上一条yield的返回值
function* sss(a = 1){
a = a * 2;
console.log(a);
yield '第一次';
a = yield '第二次';
console.log(a);
yield '第三次';
a = a * 4;
console.log(a);
yield '第四次';
}
let testGenerator = sss()
console.log('Generator value', testGenerator.next(1).value);//2 Generator value 第一次
console.log('Generator value', testGenerator.next(2).value);// Generator value 第二次
console.log('Generator value', testGenerator.next(3).value);//3 Generator value 第三次
console.log('Generator value', testGenerator.next(4).value);//12 Generator value 第四次
第一次执行 a = 2 返回'第一次';
第二次执行 返回 '第二次';
第三次执行 next(3),将上一次yield的值赋值给a,next里面的参数3被当作返回值赋值给a,
如果第三次不传参,a将是undefined(如果不传参,yield 永远返回 undefined)
第四次执行 a = 3 * 4
二十. Decorators
主要目的是不改写原对象或原函数的情况下,动态的给原对象添加一些属性或方法。
给MyClass添加一个logger()方法
function log(target) {
target.prototype.logger = () => `${target.name} 被调用`
}
@log
class MyClass { }
const test = new MyClass()
test.logger() // MyClass 被调用
二十一. Promise
promise是一个对象,用来传递异步操作的消息
promise实例一经创建就会调用
console.log("start");
var promise = new Promise((resolve,reject)=>{
console.log("hello world");
})
console.log("end");
打印顺序:start ==> hello world ==> end
为了能够更好的控制代码的运行时刻,可以将其包含在一个函数中,并将这个Promise作为函数的返回值
即这样:
console.log("start");
const sss = ()=>{
return new Promise((resolve,reject)=>{
console.log("hello world");
})
}
sss()
console.log("end");
打印顺序还是:start ==> hello world ==> end
promise的参数是一个函数,函数里有两个参数,这两个参数也是函数,
resolve:成功的回调
reject:失败的回调
new Promise中的函数是同步函数,但then是异步的,promise里面的函数执行完成功或失败的状态传给then函数,then()有两个参数分别对应这两个回调
console.log('start');
const sss = () => {
return new Promise((resolve, reject) => {
console.log('hello world');
resolve('A')
}).then((a) => {
console.log(`Promise函数成功返回值${a}输出`);
}, (b) => {
console.log(`Promise函数失败返回值${b}输出`);
}
)
}
async function aaa() {
await sss()
}
aaa()
console.log('end');
打印顺序还是:start ==> hello world ==> end ==> Promise函数成功返回值A输出
在promise里面添加异步的操作:比如文件读写之类的下面以setTimeout模拟
console.log('start');
const sss = () => {
return new Promise((resolve, reject) => {
console.log('hello world');
setTimeout( () => {
console.log('2s后输出');
// resolve('A')
reject('B')
}, 2000)
}).then((a) => {
console.log(`Promise函数成功返回值${a}输出`);
}, (b) => {
console.log(`Promise函数失败返回值${b}输出`);
}
)
}
async function aaa() {
await sss()
}
aaa()
console.log('end');
打印顺序是:start ==> hello world ==> end ==> 2s后输出 ==> Promise函数失败返回值B输出
promise中没有写resolve或reject则then里的函数不会执行
then()返回一个promise,所有then可以链式调用
console.log('start');
const sss = () => {
return new Promise((resolve, reject) => {
console.log('hello world');
setTimeout( () => {
console.log('2s后输出');
resolve('A')
// reject('B')
}, 2000)
}).then((a) => {
console.log(`Promise函数成功返回值${a}输出`);
return 10;
}, (b) => {
console.log(`Promise函数失败返回值${b}输出`);
}
).then((a)=>{
console.log(`上一个then函数成功返回值${a}输出`);
})
}
async function aaa() {
await sss()
}
aaa()
console.log('end');
打印顺序是:start ==> hello world ==> end ==> 2s后输出 ==> Promise函数成功返回值A输出 ==> 上一个then函数成功返回值10输出
如果then不写返回值,下一个then的参数是:undefined
promise的all方法提供了并行执行异步操作的能力,在all中所有异步操作结束后才执行回调.
function p1(){
var promise1 = new Promise(function(resolve,reject){
console.log("p1的第一条输出语句");
console.log("p1的第二条输出语句");
resolve("p1完成");
})
return promise1;
}
function p2(){
var promise2 = new Promise(function(resolve,reject){
console.log("p2的第一条输出语句");
setTimeout(()=>{console.log("p2的第二条输出语句");resolve("p2完成")},2000);
})
return promise2;
}
function p3(){
var promise3 = new Promise(function(resolve,reject){
console.log("p3的第一条输出语句");
console.log("p3的第二条输出语句");
resolve("p3完成")
});
return promise3;
}
Promise.all([p1(),p2(),p3()]).then(function(data){
console.log(data);
})
p1的第一条输出语句
p1的第二条输出语句
p2的第一条输出语句
p3的第一条输出语句
p3的第二条输出语句
p2的第二条输出语句
[ 'p1完成', 'p2完成', 'p3完成' ]
promise的race方法中,只要有一个任务完成或失败 就会回调.
all就是与,race就是或
二十二. async/await
async 是一个修饰符,被它定义的函数会默认的返回一个 Promise 的 resolve的值。
因此对 async 函数可以直接进行 then 操作,返回的值即为 then() 方法的传入函数
await同 async 一样,作为修饰符,但是它只能放在 async 内部使用
async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成
async function doSomething(){
let a = await firstDo()
console.log(`第1步完成: a = ${a}`);
let b = await secondDo()
console.log(`第2步完成: b = ${b}`);
let c = await thirdDo()
console.log(`第3步完成: c = ${c}`);
let d = await fourthDo()
console.log(`第4步完成: d = ${d}`);
}
let firstDo = ()=>{
return new Promise((resolve,reject) => {
setTimeout(() => {
console.log('第一步');
resolve(10)
}, 2000)
})
}
let secondDo = () => {
return new Promise((resolve,reject) => {
setTimeout(() => {
console.log('第二步');
resolve(20)
}, 2000)
})
}
let thirdDo = () =>{
return new Promise((resolve,reject) => {
setTimeout(() => {
console.log('第三步');
resolve(30)
}, 2000)
})
}
let fourthDo = ()=>{
return new Promise((resolve,reject) => {
setTimeout(() => {
console.log('第四步');
resolve(40)
}, 2000)
})
}
doSomething()
输出:
第一步
第1步完成: a = 10
第二步
第2步完成: b = 20
第三步
第3步完成: c = 30
第四步
第4步完成: d = 40
await针对所跟不同表达式的处理方式:
Promise对象:await 会暂停执行,等待 Promise 对象 resolve(异步操作完成),然后恢复 async 函数的执行并返回解析值
非Promise对象:继续执行async函数后面的代码
await是一个让出线程的标志,await后面的函数会先执行一遍,然后就会跳出整个async函数来执行后面js栈,等本轮事件循环执行完了之后又会跳回到async函数中等待await
代码执行顺序参考例子:Js中async/await的执行顺序详解_GJQI12的博客-CSDN博客
这个作者里面写的有点问题,第二次修改需要加上Promise
二十三. 闭包
闭包是指有权访问另一个函数作用域中变量的函数
function getCount(){
var num = 0
function addCount(){
num++
console.log("add "+num)
}
return addCount
}
var getRes = getCount()