JavaScript 学习

 一. 变量

        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 = yx = y
+=x += yx = x + y
-=x -= yx = x - y
*=x *= yx = x * y
/=x /= yx = x / y
%=x %= yx = 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 键值对集合

MethodDescription
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...infor...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()

nodejs 闭包学习_qq_36793743的博客-CSDN博客_nodejs 闭包

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值