前端---JavaScript篇

1. 介绍

JavaScript 是 前端开发人员必须学习的 3 门语言中的一门:

  1. HTML 定义了网页的内容
  2. CSS 描述了网页的布局
  3. JavaScript 控制了网页的行为

接下来开始详解JavaScript。

2.引入方法

js有两种导入方式,一种是内部脚本:直接在html页面中的<script>xxx</script>标签中写入Javascript代码,另一种是外部脚本:创建 .js 文件然后使用<script src = "xxx.js"></script>引入这个文件:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
  <script>
    document.writeln("hello world ");
  </script>
  <script src="test.js"></script>
    <body>

    </body>
</html>

3. JavaScript基础语法

3.1 书写语法

  • 区分大小写:与 Java 一样,变量名、函数名以及其他一切东西都是区分大小写的

  • 每行结尾的分号可有可无

    如果一行上写多个语句时,必须加分号用来区分多个语句。

  • 注释

    • 单行注释:// 注释内容

    • 多行注释:/* 注释内容 */

    注意:JavaScript 没有文档注释

  • 大括号表示代码块

    下面语句大家肯定能看懂,和 java 一样 大括号表示代码块。

    if (count == 3) { 
       alert(count); 
    } 

3.2 输出语句

js 可以通过以下方式进行内容的输出,只不过不同的语句输出到的位置不同

  • 使用 window.alert() 写入警告框

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        
    <script>
        window.alert("Hello Javascript ! ! !");//写入警告框
    </script>
    </body>
    </html>

    上面代码通过浏览器打开,我们可以看到如下图弹框效果

  • 使用 document.write() 写入 HTML 输出

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        
    <script>
        document.write("hello js 2~");//写入html页面
    </script>
    </body>
    </html>

    上面代码通过浏览器打开,我们可以在页面上看到 document.write(内容) 输出的内容

  • 使用 console.log() 写入浏览器控制台

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    ​
    <script>
        console.log("hello js 3");//写入浏览器的控制台
    </script>
    </body>
    </html>

    上面代码通过浏览器打开,我们可以在不能页面上看到 console.log(内容) 输出的内容,它是输出在控制台了,而怎么在控制台查看输出的内容呢?在浏览器界面按 F12 就可以看到下图的控制台

3.3 变量

JavaScript 中用 var 关键字(variable 的缩写)来声明变量。格式 var 变量名 = 数据值;。而在JavaScript 是一门弱类型语言,变量==可以存放不同类型的值==;如下在定义变量时赋值为数字数据,还可以将变量的值改为字符串类型的数

var test = 20;
test = "张三";

js 中的变量名命名也有如下规则,和java语言基本都相同

  • 组成字符可以是任何字母、数字、下划线(_)或美元符号($)

  • 数字不能开头

  • 建议使用驼峰命名

JavaScript 中 var 关键字有点特殊,有以下地方和其他语言不一样

  • 作用域:全局变量

    {
        var age = 20;
    }
    alert(age);  // 在代码块中定义的age 变量,在代码块外边还可以使用
  • 变量可以重复定义

    {
        var age = 20;
        var age = 30;//JavaScript 会用 30 将之前 age 变量的 20 替换掉
    }
    alert(age); //打印的结果是 30

针对如上的问题,ECMAScript 6 新增了 let关键字来定义变量。它的用法类似于 var,但是所声明的变量,只在 let 关键字所在的代码块内有效,且不允许重复声明。

例如:

{
    let age = 20;
}
alert(age); 

运行上面代码,浏览器并没有弹框输出结果,说明这段代码是有问题的。通过 F12 打开开发者模式可以看到如下错误信息:

而如果在代码块中定义两个同名的变量,IDEA 开发工具就直接报错了

ECMAScript 6 新增了 const关键字,用来声明一个只读的常量。一旦声明,常量的值就不能改变。通过下面的代码看一下常用的特点就可以了:

如图,常量重新赋值就会报错。

3.4 数据类型

JavaScript 中提供了两类数据类型:原始类型 和 引用类型。

使用 typeof 运算符可以获取数据类型

alert(typeof age); 以弹框的形式将 age 变量的数据类型输出

原始数据类型:

  • number:数字(整数、小数、NaN(Not a Number))

    var age = 20;
    var price = 99.8;
    ​
    alert(typeof age); // 结果是 : number
    alert(typeof price);// 结果是 : number

    ==注意:== NaN是一个特殊的number类型的值,后面用到再说

  • string:字符、字符串,单双引皆可

    var ch = 'a';
    var name = '张三'; 
    var addr = "北京";
    ​
    alert(typeof ch); //结果是  string
    alert(typeof name); //结果是  string
    alert(typeof addr); //结果是  string

    ==注意:==在 js 中 双引号和单引号都表示字符串类型的数据

  • boolean:布尔。true,false

    var flag = true;
    var flag2 = false;
    ​
    alert(typeof flag); //结果是 boolean
    alert(typeof flag2); //结果是 boolean
  • null:对象为空

    var obj = null;
    alert(typeof obj);//结果是 object

    为什么打印上面的 obj 变量的数据类型,结果是object;这个官方给出了解释,下面是从官方文档截的图:

  • undefined:当声明的变量未初始化时,该变量的默认值是 undefined

    var a ;
    alert(typeof a); //结果是 undefined

3.5 运算符

JavaScript 提供了如下的运算符。大部分和 Java语言 都是一样的,不同的是 JS 关系运算符中的 =====,一会我们只演示这两个的区别,其他运算符将不做演示

  • 一元运算符:++,--

  • 算术运算符:+,-,*,/,%

  • 赋值运算符:=,+=,-=…

  • 关系运算符:>,<,>=,<=,!=,\==,===…

  • 逻辑运算符:&&,||,!

  • 三元运算符:条件表达式 ? true_value : false_value

3.5.1  == 和 === 的区别

概述:

  • ==:

    1. 判断类型是否一样,如果不一样,则进行类型转换

    2. 再去比较其值

  • ===:js 中的全等于

    1. 判断类型是否一样,如果不一样,直接返回false

    2. 再去比较其值

代码:

let age1 = 20;
let age2 = "20";
​
alert(age1 == age2);// true
alert(age1 === age2);// false
3.5.2 类型转换

上述讲解 == 运算符时,发现会进行类型转换,所以接下来我们来详细的讲解一下 JavaScript 中的类型转换。

  • 其他类型转为number

    • string 转换为 number 类型:按照字符串的字面值,转为数字。如果字面值不是数字,则转为NaN

      将 string 转换为 number 有两种方式:

      • 使用 + 正号运算符:

        let str = +"20";
        alert(str + 1) //21
      • 使用 parseInt() 函数(方法):

        let str = "20";
        alert(parseInt(str) + 1);

      ==建议使用 parseInt() 函数进行转换。==

    • boolean 转换为 number 类型:true 转为 1,false转为 0

      let flag = +false;
      alert(flag); // 0
  • 其他类型转为boolean

    • number 类型转换为 boolean 类型:0和NaN转为false,其他的数字转为true

    • string 类型转换为 boolean 类型:空字符串转为false,其他的字符串转为true

    • null类型转换为 boolean 类型是 false

    • undefined 转换为 boolean 类型是 false

    代码如下:

    // let flag = 3;
    // let flag = "";
    let flag = undefined;
    ​
    if(flag){
        alert("转为true");
    }else {
        alert("转为false");
    }

使用场景:

在 Java 中使用字符串前,一般都会先判断字符串不是null,并且不是空字符才会做其他的一些操作,JavaScript也有类型的操作,代码如下:

let str = "abc";
//健壮性判断
if (str != null && str.length > 0) {
    alert("转为true");
} else {
    alert("转为false");
}

但是由于 JavaScript 会自动进行类型转换,所以上述的判断可以进行简化,代码如下:

let str = "abc";
//健壮性判断
if(str){
    alert("转为true");
}else {
    alert("转为false");
}

3.6 流程控制语句

JavaScript 中提供了和 Java 一样的流程控制语句,如下

  • if

  • switch

  • for

  • while

  • dowhile

3.6.1 if 语句
let count = 3;
if (count == 3) {
    alert(count);
}
3.6.2 switch 语句
let num = 3;
switch (num) {
    case 1:
        alert("星期一");
        break;
    case 2:
        alert("星期二");
        break;
    case 3:
        alert("星期三");
        break;
    case 4:
        alert("星期四");
        break;
    case 5:
        alert("星期五");
        break;
    case 6:
        alert("星期六");
        break;
    case 7:
        alert("星期日");
        break;
    default:
        alert("输入的星期有误");
        break;
}
3.6.3 for 循环语句
let sum = 0;
for (let i = 1; i <= 100; i++) { //建议for循环小括号中定义的变量使用let
    sum += i;
}
alert(sum);
3.6.4 while 循环语句
let sum = 0;
let i = 1;
while (i <= 100) {
    sum += i;
    i++;
}
alert(sum);
3.6.5 dowhile 循环语句
let sum = 0;
let i = 1;
do {
    sum += i;
    i++;
}
while (i <= 100);
alert(sum);

3.7 函数

函数(就是Java中的方法)是l被设计为执行特定任务的代码块;JavaScript 函数通过 function 关键词进行定义。

3.7.1 定义格式

函数定义格式有两种:

  • 方式1

    function 函数名(参数1,参数2..){
        要执行的代码
    }
  • 方式2

    let 函数名 = function (参数列表){
        要执行的代码
    }

==注意:==

  • 形式参数不需要类型。因为JavaScript是弱类型语言

    function add(a, b){
        return a + b;
    }

    上述函数的参数 a 和 b 不需要定义数据类型,因为在每个参数前加上 var 也没有任何意义。

  • 返回值也不需要定义类型,可以在函数内部直接使用return返回即可

3.7.2 函数调用

函数调用函数:

函数名称(实际参数列表);

eg:let result = add(10,20);

注意:

  • JS中,函数调用可以传递任意个数参数

  • 例如 let result = add(1,2,3);

    它是将数据 1 传递给了变量a,将数据 2 传递给了变量 b,而数据 3 没有变量接收。

4. JavaScript常用对象

JavaScript 提供了很多对象供使用者来使用。这些对象总共分类三类

基本对象BOM对象DOM对象
ArrayWindowDocument
BooleanNavigatorAnchor
StringScreenArea
NumberHistory
DateLocation
Math
RegExp
Function

4.1 基本对象

接下来是基本对象的详细介绍和使用方式

4.1.1 Array(数组)

用于存储和操作多个值的有序集合。它提供了许多用于操作数组元素的方法,如push、pop、slice、forEach等

  • 创建数组:使用数组字面量或构造函数。
    // 使用数组字面量创建数组
    const numbers = [1, 2, 3, 4, 5];
    
    // 使用构造函数创建数组
    const fruits = new Array('apple', 'banana', 'orange');
    
  • 访问数组元素:
    console.log(numbers[0]); // 输出:1
    console.log(fruits.length); // 输出:3
    
  • 数组方法示例:
    numbers.push(6); // 在末尾添加元素
    fruits.pop(); // 移除末尾的元素
    numbers.splice(2, 1); // 从索引2开始移除1个元素
    fruits.join(', '); // 将数组元素以逗号分隔的字符串形式返回
4.1.2. Boolean(布尔)

用于表示真(true)或假(false)的逻辑值的对象。它提供了一些用于逻辑运算的方法,如逻辑与(&&)、逻辑或(||)等。

  • 创建布尔值:
    const isTrue = true;
    const isFalse = false;
    
  • 逻辑运算示例:
    const result = isTrue && isFalse; // 逻辑与运算
    console.log(result); // 输出:false
    const result2 = isTrue || isFalse; // 逻辑或运算
    console.log(result2); // 输出:true
4.1.3. String(字符串)

用于表示和操作文本数据的对象。它提供了许多用于处理字符串的方法,如charAt、toUpperCase、substring等。

  • 创建字符串:
    const message = 'Hello, world!';
    
  • 字符串方法示例:
    message.length; // 字符串长度
    message.toUpperCase(); // 转为大写
    message.toLowerCase(); // 转为小写
    message.indexOf('world'); // 查找子串的索引
    message.substring(0, 5); // 获取子串
4.1.4 Number(数字)

用于表示和处理数字的对象。它提供了许多用于进行数学运算和数字转换的方法,如toFixed、toString、Math等。

  • 创建数字:
    const age = 25;
    
  • 数字方法示例:
    age.toString(); // 转为字符串
    Math.random(); // 生成一个0到1之间的随机数
    Math.floor(3.7); // 向下取整,输出:3
    Math.ceil(3.2); // 向上取整,输出:4
4.1.5 Date(日期)

用于表示和操作日期和时间的对象。它提供了方法来获取和设置日期、进行日期运算、格式化日期等。

  • 创建日期对象:
    const now = new Date();
    
  • 日期方法示例:
    now.getFullYear(); // 获取年份
    now.getMonth(); // 获取月份(0-11,0代表一月)
    now.getDate(); // 获取日期
    now.getHours(); // 获取小时
    now.getMinutes(); // 获取分钟
4.1.6 Math(数学)

提供了一组用于数学运算的静态方法和常量,如Math.floor、Math.random、Math.PI等。

例子:

Math.random(); // 返回0到1之间的随机数
Math.floor(3.7); // 向下取整,返回3
Math.ceil(3.2); // 向上取整,返回4
4.1.7 RegExp(正则表达式)

用于模式匹配和文本搜索的对象。它提供了一组用于创建和操作正则表达式的方法,如test、exec等。

  • 创建正则表达式对象:
    const pattern = /hello/;
    
  • 正则表达式方法示例:
    pattern.test('hello world'); // 匹配测试,返回true
    'hello world'.match(pattern); // 返回匹配到的数组
4.1.8 Function(函数)

用于定义可执行的代码块,并可以传递参数并返回值。函数本身也是一个对象,可以存储和传递。

  • 创建函数:
    function sayHello() {
      console.log('Hello!');
    }
    
    const addNumbers = function(num1, num2) {
      return num1 + num2;
    };
    
  • 函数调用:
    sayHello(); // 输出:Hello!
    const sum = addNumbers(3, 5); // 赋值为8

4.2 BOM 对象(浏览器对象模型)

4.2.1 Window(窗口)
  • Window对象表示浏览器中打开的窗口或标签页。
  • 使用代码示例:
    // 弹出对话框
    window.alert('Hello World!');
    
    // 打开新窗口
    window.open('https://www.example.com', '_blank');
    
    // 关闭当前窗口
    window.close();
    
    // 设置定时器
    window.setTimeout(function() {
      console.log('定时器触发!');
    }, 5000);
4.2.2 Navigator(导航器)
  • Navigator对象提供有关浏览器的信息。
  • 使用代码示例:
    // 获取浏览器名称
    const browserName = window.navigator.userAgent;
    
    // 检测浏览器是否支持某个特性
    const isGeolocationSupported = 'geolocation' in window.navigator;
    
    // 检测当前网络是否在线
    const isOnline = window.navigator.onLine;
    
4.2.3 Screen(屏幕)
  • Screen对象表示用户的屏幕信息。
  • 使用代码示例:
    // 获取屏幕宽度和高度
    const screenWidth = window.screen.width;
    const screenHeight = window.screen.height;
    
    // 获取屏幕可用宽度和高度(去除任务栏或工具栏等)
    const availableScreenWidth = window.screen.availWidth;
    const availableScreenHeight = window.screen.availHeight;
    
    // 获取屏幕像素密度(DPI,每英寸的像素数)
    const screenPixelDensity = window.screen.pixelDepth;
4.2.4 History(历史记录)
  • History对象保存用户在浏览器窗口中访问的URL历史记录。
  • 使用代码示例:
    // 后退一页
    window.history.back();
    
    // 前进一页
    window.history.forward();
    
    // 前进两页(相对于当前页面)
    window.history.go(2);
    
    // 获取当前历史记录中的URL数量
    const urlCount = window.history.length;
    
4.2.5 Location(位置)
  • Location对象表示当前加载的文档的URL信息。
  • 使用代码示例:
    // 获取当前URL
    const currentURL = window.location.href;
    
    // 加载新的URL
    window.location.href = 'https://www.example.com';
    
    // 获取当前页面的域名
    const domain = window.location.hostname;
    
    // 获取当前页面的路径名
    const path = window.location.pathname;
    
    // 重新加载当前页面(刷新)
    window.location.reload();

4.3 DOM对象(文档对象模型)

4.3.1 Document(文档)
  • Document对象表示整个HTML文档,它是DOM的根节点。
  • 作用:JavaScript 通过 DOM, 就能够对 HTML进行操作了

  1. 改变 HTML 元素的内容
  2. 改变 HTML 元素的样式(CSS)
  3. 对 HTML DOM 事件作出反应
  4. 添加和删除 HTML 元素
  • Document 对象中提供了以下获取 Element 元素对象的函数
  1. getElementById():根据id属性值获取,返回单个Element对象

  2. getElementsByTagName():根据标签名称获取,返回Element对象数组

  3. getElementsByName():根据name属性值获取,返回Element对象数组

  4. getElementsByClassName():根据class属性值获取,返回Element对象数组

  • 使用代码示例:
    // 获取文档标题
    const title = document.title;
    
    // 获取文档中的所有段落元素
    const paragraphs = document.getElementsByTagName('p');
    
    // 获取文档中ID为"myElement"的元素
    const element = document.getElementById('myElement');
    
    // 创建新的元素节点
    const newElement = document.createElement('div');
    
    // 将新的元素节点添加到文档中
    document.body.appendChild(newElement);
    
4.3.2 Anchor(锚点)
  • Anchor对象表示HTML文档中的锚点(链接)元素。
  • 使用代码示例:
    // 获取具有ID为"myLink"的锚点元素
    const link = document.getElementById('myLink');
    
    // 获取锚点的URL
    const href = link.href;
    
    // 设置锚点的目标位置
    link.target = '_blank';
    
    // 添加点击事件监听器
    link.addEventListener('click', function(event) {
      event.preventDefault(); // 阻止默认行为
      console.log('锚点被点击!');
    });
4.3.3 Area(图像映射区域)
  • Area对象表示HTML文档中图像映射的区域。
  • 使用代码示例:
    // 获取所有图像映射区域
    const areas = document.getElementsByTagName('area');
    
    // 获取第一个图像映射区域的坐标
    const coords = areas[0].coords;
    
    // 获取第一个图像映射区域的目标URL
    const targetURL = areas[0].href;
    
    // 添加鼠标移入事件监听器
    areas[0].addEventListener('mouseover', function() {
      console.log('鼠标移入图像映射区域!');
    });

5. 事件

事件绑定:

JavaScript 提供了两种事件绑定方式:

  • 方式一:通过 HTML标签中的事件属性进行绑定

    如下面代码,有一个按钮元素,我们是在该标签上定义 事件属性,在事件属性中绑定函数。onclick 就是 单击事件 的事件属性。onclick='on()' 表示该点击事件绑定了一个名为 on() 的函数

    <input type="button" onclick='on()’>

    下面是点击事件绑定的 on() 函数

    function on(){
        alert("我被点了");
    }
  • 方式二:通过 DOM 元素属性绑定

    如下面代码是按钮标签,在该标签上我们并没有使用 事件属性,绑定事件的操作需要在 js 代码中实现

    <input type="button" id="btn">

    下面 js 代码是获取了 id='btn' 的元素对象,然后将 onclick 作为该对象的属性,并且绑定匿名函数。该函数是在事件触发后自动执行

    document.getElementById("btn").onclick = function (){
        alert("我被点了");
    }

以下是主要的事件:

事件属性名说明
onclick鼠标单击事件
onblur元素失去焦点
onfocus元素获得焦点
onload某个页面或图像被完成加载
onsubmit当表单提交时触发该事件
onmouseover鼠标被移到某元素之上
onmouseout鼠标从某元素移开

6. 闭包

闭包的定义

闭包是指函数以及其相关的词法环境的组合。它包含两个部分:

  1. 函数:在JavaScript中,函数是一等公民,可以作为值被传递和赋值。
  2. 词法环境:词法环境是函数在定义时创建的作用域,在函数闭包中可以访问的变量集合。

闭包的特性和优势

闭包具有以下特性和优势:

  1. 访问外部变量:闭包允许函数访问其定义时的词法作用域中的变量,即使函数在其他地方执行也是如此。
  2. 保护变量:由于闭包中的变量无法从外部直接访问,可以将其用于创建私有变量和私有方法。
  3. 存储状态:通过保留对词法环境的引用,闭包可以存储函数执行时的状态,这对于处理异步操作或延迟执行非常有用。
  4. 实现模块化:闭包可以将一组相关的变量和方法封装在一个作用域内,形成一个独立且可复用的模块。

闭包的示例

下面是几个示例来演示闭包的用法:

示例 1:访问外部变量
function outerFunction() {
  var outerVariable = 'I am outside!';

  function innerFunction() {
    console.log(outerVariable);
  }

  return innerFunction;
}

var inner = outerFunction();
inner(); // 输出:I am outside!

在这个示例中,innerFunction是一个闭包,因为它可以访问outerFunction中定义的outerVariable变量,即使innerFunctionouterFunction执行后调用。

示例 2:保护变量
function counter() {
  var count = 0;

  return function() {
    count++;
    console.log(count);
  };
}

var increment = counter();
increment(); // 输出:1
increment(); // 输出:2
increment(); // 输出:3

在这个示例中,counter函数返回一个闭包,其中包含一个局部变量count。闭包内部的匿名函数可以访问和修改count变量,但外部无法直接访问它。这种方式可以实现变量的封装和保护。

示例 3:延迟执行
function delayPrint(message, delay) {
  setTimeout(function() {
    console.log(message);
  }, delay);
}

delayPrint('Hello, world!', 2000); // 2秒后输出:Hello, world!

在这个示例中,setTimeout的回调函数是一个闭包。它可以在外部函数执行完毕后,延迟指定的时间后执行,并且仍然可以访问delayPrint函数中的message变量。

7. 异步编程

我们都知道,JavaScript是一门单线程的编程语言,意味着它一次只能处理一个任务。然而,现代的Web应用程序通常需要处理许多异步操作,例如网络请求、定时器和文件读写等。为了更好地管理和处理这些异步任务,JavaScript提供了多种异步编程模式和技术。现详细介绍JavaScript的异步编程,从基础的回调函数到最新的async/await模式。

7.1 回调函数

回调函数是最早和最常见的JavaScript异步编程模式。它的基本思想是将一个函数作为参数传递给另一个函数,在操作完成后调用该回调函数。例如网络请求、定时器和文件读写等。由于JavaScript是单线程的,回调函数允许我们在等待任务完成期间执行其他操作,以避免程序的阻塞。

7.1.1 单个回调函数
function fetchData(callback) {
  // 模拟异步操作
  setTimeout(function() {
    var data = '这是从服务器返回的数据';
    callback(data); // 执行回调函数
  }, 1000);
}

function processData(data) {
  console.log('处理数据:', data);
}

fetchData(processData);

在上述代码中,fetchData函数模拟了一个异步操作,并在操作完成后调用传递的processData回调函数来处理返回的数据。

7.1.2 回调函数地狱

在复杂的异步操作中,可能存在多个操作之间的依赖关系,导致回调函数嵌套,形成回调函数地狱,降低了代码的可读性和可维护性。

function fetchData(callback) {
  setTimeout(function() {
    var data1 = '第一个异步操作的结果';
    callback(data1);
    setTimeout(function() {
      var data2 = '第二个异步操作的结果';
      callback(data2);
      // 更多嵌套的异步操作...
    }, 1000);
  }, 1000);
}

function processData(data) {
  console.log('处理数据:', data);
}

fetchData(function(data) {
  processData(data);
});

为了避免回调地狱,后续的JavaScript版本引入了Promise和async/await等新的异步编程模式。

7.2 Promise

Promise是一种对异步操作进行更好管理的方式,它提供了一种链式调用的方式来处理异步结果。

7.2.1 创建Promise对象
function fetchData() {
  return new Promise(function(resolve, reject) {
    // 模拟异步操作
    setTimeout(function() {
      var data = '这是从服务器返回的数据';
      resolve(data); // 完成操作并传递数据
    }, 1000);
  });
}

fetchData().then(function(data) {
  console.log('处理数据:', data);
});

在上述代码中,fetchData函数返回一个Promise对象。可以使用.then()方法注册处理异步操作成功的回调函数。

7.2.2 链式调用和错误处理

Promise对象可以进行链式调用,通过返回新的Promise对象实现多个异步操作的串行执行。

function fetchData() {
  return new Promise(function(resolve, reject) {
    // 模拟异步操作
    setTimeout(function() {
      var data = '这是从服务器返回的数据';
      resolve(data); // 完成操作并传递数据
    }, 1000);
  });
}

function processData(data) {
  console.log('处理数据:', data);
  return new Promise(function(resolve, reject) {
    // 模拟另一个异步操作
    setTimeout(function() {
      var result = '处理结果';
      resolve(result);
    }, 1000);
  });
}

fetchData()
  .then(function(data) {
    return processData(data);
  })
  .then(function(result) {
    console.log('处理结果:', result);
  })
  .catch(function(error) {
    console.error('发生错误:', error);
  });

在上述代码中,通过.then()方法返回新的Promise对象,实现了串行执行异步操作fetchDataprocessData

.catch()方法用于捕获错误并进行相应的处理。

7.3. async/await

async/await是ES2017引入的一种更直观、更易读的异步编程模式。

4.3.1 async函数

通过在函数前加上async关键字声明一个异步函数,异步函数会返回一个Promise对象。

async function fetchData() {
  return new Promise(function(resolve, reject) {
    // 模拟异步操作
    setTimeout(function() {
      var data = '这是从服务器返回的数据';
      resolve(data); // 完成操作并传递数据
    }, 1000);
  });
}

async function processData() {
  var data = await fetchData();
  console.log('处理数据:', data);
}

processData();

在上述代码中,fetchData函数返回一个Promise对象,并通过await关键字等待异步操作的结果。

processData函数必须也声明为async函数才能使用await

7.3.2 await表达式

await关键字可用于等待一个返回Promise对象的异步操作完成,并返回其结果。

async function fetchData() {
  return new Promise(function(resolve, reject) {
    // 模拟异步操作
    setTimeout(function() {
      var data = '这是从服务器返回的数据';
      resolve(data); // 完成操作并传递数据
    }, 1000);
  });
}

async function processData() {
  var data = await fetchData();
  console.log('处理数据:', data);
}

processData();
7.3.3 异常处理

使用try/catch块来捕获和处理await表达式中的异常。

async function fetchData() {
  return new Promise(function(resolve, reject) {
    // 模拟异步操作
    setTimeout(function() {
      reject(new Error('请求失败'));
    }, 1000);
  });
}

async function processData() {
  try {
    var data = await fetchData();
    console.log('处理数据:', data);
  } catch (error) {
    console.error('发生错误:', error.message);
  }
}

processData();

在上述代码中,如果异步操作fetchData返回的Promise对象被拒绝(rejected),await会抛出一个异常,在catch块中进行捕获。

7.4. 并行和串行执行异步任务

Promise和async/await模式可以很好地控制并行和串行执行异步任务。

7.4.1 并行执行

可以使用Promise.all()方法并行执行多个异步任务,并在所有任务完成后获得结果。

async function fetchData1() {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve('数据1');
    }, 1000);
  });
}

async function fetchData2() {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve('数据2');
    }, 2000);
  });
}

async function fetchData3() {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve('数据3');
    }, 1500);
  });
}

async function processParallel() {
  var [data1, data2, data3] = await Promise.all([fetchData1(), fetchData2(), fetchData3()]);
  console.log('并行处理数据:', data1, data2, data3);
}

processParallel();

在上述代码中,通过Promise.all()方法将多个异步任务统一封装为一个Promise对象,并使用解构赋值返回所有任务的结果。

7.4.2 串行执行

通过使用await关键字和函数的顺序调用,可以实现多个异步任务的串行执行。

async function processSeries() {
  var data1 = await fetchData1();
  var data2 = await fetchData2();
  var data3 = await fetchData3();
  console.log('串行处理数据:', data1, data2, data3);
}

processSeries();

7.5  异步编程的最佳实践

  • 尽量使用Promise和async/await,避免回调地狱。
  • 注意错误处理,使用.catch()或try/catch块捕获异常。
  • 并行执行多个异步任务时,使用Promise.all()获取结果。
  • 考虑使用工具库如axiosfetch来处理网络请求,它们已经提供了良好的异步支持。

7.6  异步编程结论

JavaScript的异步编程是处理复杂和并行任务的关键技术。通过回调函数、Promise和async/await模式,我们可以更好地管理和处理异步任务,提高应用的性能和响应性。在实际开发中,根据具体需求选择适合的异步编程方式,并注意良好的错误处理和最佳实践,以编写出高效、可维护的代码。

8. 总结

本次主要记录了Javascript的基础语法、常用对象使的使用以及事件等等基础知识,同时详解了JavaScript中的闭包、异步编程等等知识,接下来会讲述网路请求方面的知识并通过ajax和axios进行网络请求发送。

  • 20
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

stu_kk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值