JavaScript“基本语法”笔记(自学第一天)!

一、JavaScript的用途和应用领域

JavaScript的应用领域非常广泛,主要包括以下几个方面:

  1. 网页交互性: JavaScript最初是为了增强网页的交互性而开发的,它可以控制网页的行为、样式和内容,使用户能够与网页进行实时交互,包括表单验证、动画效果、页面加载等。

  2. Web应用开发: 随着技术的发展,JavaScript已经成为创建复杂Web应用程序的主要语言之一。使用JavaScript的前端框架和库,如React、Angular、Vue.js等,开发人员可以创建功能丰富、动态和高性能的Web应用。

  3. 移动应用开发: JavaScript也被广泛应用于移动应用开发。通过使用跨平台移动应用开发框架,如React Native和Ionic,开发人员可以使用JavaScript开发原生移动应用程序,从而减少了跨平台开发的成本和复杂性。

  4. 游戏开发: JavaScript已经成为创建Web游戏的一种流行选择。借助HTML5游戏开发框架和引擎,如Phaser和Three.js,开发人员可以使用JavaScript创建高质量的2D和3D游戏。

  5. 服务器端开发: JavaScript也可以用于服务器端开发。Node.js是一个基于JavaScript的运行时环境,它使JavaScript可以在服务器端运行,从而实现了全栈JavaScript开发,为开发人员提供了构建高性能和可扩展的服务器端应用程序的能力。

二、基本语法

1. 变量(Variables)
  • 声明变量:使用 var, let, 或 const 关键字声明变量。
  • 赋值:将值赋给变量,可以是任何数据类型。
  • 命名规则:变量名必须以字母、下划线或美元符号开头,后续可以是字母、数字、下划线或美元符号。

    var let const声明的变量区别:

  1. var:

    • 使用 var 声明的变量具有函数级作用域(function scope),意味着变量的作用域仅限于声明它的函数内部。
    • 使用 var 声明的变量可以被重复声明,而不会报错。
    • var 声明的变量可以在其声明之前被访问,这种现象称为变量提升(hoisting)。
  2. let:

    • 使用 let 声明的变量具有块级作用域(block scope),意味着变量的作用域限制在当前代码块内(例如,{} 中)。
    • 使用 let 声明的变量不可以被重复声明,否则会报错。
    • let 声明的变量不会发生变量提升,即变量在声明之前不可用。
  3. const:

    • const 声明的是常量,意味着一旦被赋值,其值就不能再改变。
    • const 声明的变量具有块级作用域。
    • const 声明的变量必须在声明时进行初始化,且不能再次赋值。
    • 对于对象和数组等复合类型,虽然 const 声明的变量本身不能再被赋值,但是可以修改其内部的属性或元素。

综上所述,varletconst 在作用域、重复声明、变量提升和是否可修改等方面存在一些区别,开发者需要根据实际需求选择合适的声明方式。一般来说,推荐使用 letconst 替代 var,因为它们提供了更好的作用域控制和更明确的代码意图。

示例代码

// 使用 var 声明变量
var name = "John";
var age = 30;// 使用 let 声明变量(ES6+)
let city = "New York";
let isMarried = false;// 使用 const 声明常量
const PI = 3.14159;
const DAYS_IN_A_WEEK = 7;// 修改变量的值
name = "Jane";
age = 35;// 使用变量进行计算
let birthYear = 2022 - age;// 字符串插值:将变量的值嵌入到字符串中
console.log(`My name is ${name} and I am ${age} years old.`);// 数组变量
let numbers = [1, 2, 3, 4, 5];// 对象变量
let person = {firstName: "John",lastName: "Doe",age: 30,city: "New York"
};// 访问对象属性
console.log(person.firstName); // 输出 "John"
console.log(person["lastName"]); // 输出 "Doe"// 修改对象属性
person.age = 35;// 新增对象属性
person.gender = "male";// 删除对象属性
delete person.city;
2. 数据类型(Data Types)
  • 字符串(String):用单引号或双引号括起来的文本数据。
  • 数字(Number):整数或浮点数。
  • 布尔值(Boolean):true 或 false。
  • 数组(Array):有序的数据集合,可以容纳不同类型的数据。
  • 对象(Object):键值对的集合,用花括号 {} 表示。
3. 操作符(Operators)
  • 算术操作符:加 +, 减 -, 乘 *, 除 /, 取模 %, 自增 ++, 自减 -- 等。
  • 赋值操作符:赋值 =, 加等于 +=, 减等于 -= 等。
  • 比较操作符:等于 ==, 不等于 !=, 大于 >, 小于 <, 大于等于 >=, 小于等于 <= 等。
  • 逻辑操作符:与 &&, 或 ||, 非 ! 等。
4. 注释(Comments)
  • 单行注释:使用 // 开始,注释内容直到行尾。
  • 多行注释:使用 /* */ 将多行内容注释起来。

三、控制流程

1. 条件语句(Conditional Statements)
  • if语句:if语句用于在执行代码之前检查条件是否为真,如果条件为真,则执行特定的代码块。语法如下:
    if (condition) {// 如果条件为真,则执行此代码块
    }
    
  • if...else语句:if...else语句允许我们指定在条件为真和条件为假时要执行的不同代码块。语法如下:
    if (condition) {// 如果条件为真,则执行此代码块
    } else {// 如果条件为假,则执行此代码块
    }
    
  • if...else if...else语句:if...else if...else语句允许我们测试多个条件,并在条件链中的第一个为真时执行相应的代码块。语法如下:
    if (condition1) {// 如果条件1为真,则执行此代码块
    } else if (condition2) {// 如果条件2为真,则执行此代码块
    } else {// 如果以上条件都不为真,则执行此代码块
    }
    
  • switch语句:switch语句用于根据表达式的值选择要执行的代码块。语法如下:
    switch (expression) {case value1:// 当表达式的值等于value1时执行此代码块break;case value2:// 当表达式的值等于value2时执行此代码块break;default:// 当表达式的值不匹配任何case时执行此代码块
    }
    
2. 循环(Loops)
  • for循环:for循环用于重复执行代码块,直到指定的条件为假。语法如下:
    for (initialization; condition; iteration) {// 在每次迭代中执行的代码块
    }
    
  • while循环:while循环用于重复执行代码块,直到指定的条件为假。语法如下:
    while (condition) {// 当条件为真时执行的代码块
    }
    
  • do...while循环:do...while循环首先执行一次代码块,然后在条件为真时重复执行代码块。语法如下:
    do {// 执行的代码块
    } while (condition);
    
3. 控制语句(Control Statements)
  • break语句:break语句用于终止循环或switch语句的执行,并跳出当前代码块。它通常与条件语句结合使用。例如,在switch语句中,break语句用于在执行完一个case后退出switch语句。在循环中,break语句用于提前退出循环。语法如下:
    break;
    
  • continue语句:continue语句用于跳过当前循环中的剩余代码,并继续下一次循环迭代。在循环中,当条件满足时,continue语句会跳过当前迭代的剩余代码,直接开始下一次迭代。语法如下:
    continue;
    

四、函数

1. 函数的定义和调用
  • 函数定义:使用 function 关键字来定义函数,并给函数一个名称。语法如下:
    function functionName(parameters) {// 函数体,包含要执行的代码
    }
    
  • 函数调用:使用函数名和括号来调用函数,并传递参数(如果有)。语法如下:
    functionName(arguments);
    

示例代码:

// 定义一个简单的函数,用于打印一条消息到控制台
function greet() {console.log("Hello, world!");
}// 调用函数 greet
greet(); // 输出 "Hello, world!"
// 定义一个带参数的函数,用于打印个性化的问候语
function greetPerson(name) {console.log("Hello, " + name + "!");
}// 调用函数 greetPerson,并传入参数
greetPerson("John"); // 输出 "Hello, John!"
greetPerson("Jane"); // 输出 "Hello, Jane!"
2. 函数参数和返回值
  • 函数参数:函数可以接受零个或多个参数,这些参数是在函数调用时传递给函数的值。语法如下:
    function add(a, b) {return a + b;
    }
    
  • 函数返回值:函数可以返回一个值,使用 return 关键字后跟要返回的值。如果没有显式使用 return 语句,则函数将返回 undefined。语法如上例所示。

示例代码:

// 定义一个带参数和返回值的函数,用于计算两个数的和
function add(a, b) {return a + b;
}// 调用函数 add,并将结果存储到变量中
var result = add(3, 5);
console.log(result); // 输出 8
3. 匿名函数和箭头函数
  • 匿名函数:匿名函数是一种没有名称的函数,可以直接作为表达式使用或传递给其他函数。语法如下:
    var functionName = function(parameters) {// 函数体,包含要执行的代码
    };
    

示例代码: 

1. 将匿名函数赋值给变量

// 将匿名函数赋值给变量,然后调用该函数
var greet = function() {console.log("Hello, world!");
};// 调用变量中存储的匿名函数
greet(); // 输出 "Hello, world!"

2. 将匿名函数作为回调函数传递给其他函数

// 定义一个函数,接受一个回调函数作为参数,并在内部调用该回调函数
function performOperation(callback) {console.log("Performing operation...");callback();
}// 调用 performOperation,并传入匿名函数作为回调函数
performOperation(function() {console.log("Operation completed!");
});
// 输出:
// Performing operation...
// Operation completed!

        在这个示例中,我们首先定义了一个名为 performOperation 的函数。这个函数接受一个参数 callback我们期望这个参数是一个函数。在函数内部,我们首先输出一条消息表示正在执行操作,然后调用传入的回调函数 callback()

        然后,我们调用 performOperation 函数,并将一个匿名函数作为参数传递给它。这个匿名函数实际上就是我们期望作为回调函数执行的代码块。在这个匿名函数中,我们简单地输出一条消息表示操作已完成。

        当我们调用 performOperation 函数时,它内部会执行传入的回调函数,也就是我们传递的匿名函数。这导致首先输出 "Performing operation...",然后立即执行传入的匿名函数,输出 "Operation completed!"。

3. 在数组方法中使用匿名函数

// 定义一个数组
var numbers = [1, 2, 3, 4, 5];// 使用数组的 map 方法,并传入匿名函数作为参数,将数组中的每个元素加倍
var doubledNumbers = numbers.map(function(num) {return num * 2;
});console.log(doubledNumbers); // 输出 [2, 4, 6, 8, 10]

4. 使用箭头函数替代匿名函数(ES6+)

// 使用箭头函数定义匿名函数
var greet = () => {console.log("Hello, world!");
};// 调用箭头函数
greet(); // 输出 "Hello, world!"// 在数组方法中使用箭头函数
var doubledNumbers = numbers.map(num => num * 2);
console.log(doubledNumbers); // 输出 [2, 4, 6, 8, 10]

以上示例展示了在JavaScript中如何使用匿名函数。匿名函数是没有名称的函数,通常用于作为回调函数传递给其他函数,或者在需要临时定义函数的地方使用。通过匿名函数,可以更灵活地组织和编写代码。

  • 箭头函数:箭头函数是ES6中的一种新函数形式,提供了更简洁的语法。它使用 => 符号来定义函数,语法如下:
    var functionName = (parameters) => {// 函数体,包含要执行的代码
    };
    
  • 箭头函数的简写:当函数体只有一条返回语句时,可以省略大括号和 return 关键字。例如:
    var add = (a, b) => a + b;
    

五、作用域和闭包 

1. 全局作用域和局部作用域
  • 全局作用域(Global Scope):全局作用域是在整个程序中都可以访问的作用域,它定义了在程序的任何地方都可以访问的变量和函数。
  • 局部作用域(Local Scope):局部作用域是在函数内部声明的作用域,其中定义的变量和函数只能在该函数内部访问。

示例:

// 全局作用域
var globalVariable = "I am a global variable";function exampleFunction() {// 局部作用域var localVariable = "I am a local variable";console.log(globalVariable); // 可以访问全局变量
}exampleFunction();
console.log(localVariable); // 无法访问局部变量,会报错
2. 闭包的概念和应用场景
  • 闭包(Closure):闭包是指函数和其周围状态(词法环境)的组合。闭包可以访问函数定义时所处的词法作用域,即使函数在定义之后在其他地方执行,仍然可以访问这个词法作用域中的变量。
  • 应用场景
    • 保护变量:通过闭包可以创建私有变量,只能通过闭包内部的函数访问,从而保护数据不被外部访问和修改。
    • 延长变量的生命周期:当一个函数执行完毕后,其内部的变量通常会被销毁,但是如果有闭包存在,这些变量就会被保存在内存中,直到闭包被销毁,从而延长了变量的生命周期。

示例:

function createCounter() {var count = 0;return function() {return ++count;};
}var counter = createCounter();
console.log(counter()); // 输出 1
console.log(counter()); // 输出 2
console.log(counter()); // 输出 3

在这个示例中,createCounter 函数返回了一个内部定义的匿名函数,这个匿名函数形成了闭包。count 变量被保存在闭包内部的词法环境中,每次调用 counter 函数时,闭包都能访问并更新 count 变量的值,从而实现了计数器的功能。

闭包通俗理解:

闭包可以被理解为一个函数,它记住了创建它的环境。更简单地说,闭包就像一个包裹着的函数,它包含了在创建它的上下文中定义的所有变量和函数,即使在这个上下文已经不再存在的情况下。

举个通俗的例子来解释闭包:

假设你有一个房子,里面有一个包裹着的盒子,盒子里面有你的一些物品。即使你离开了房子,盒子仍然在那里,里面的物品也没有丢失。闭包就好像这个包裹着的盒子,它包含了函数定义时的作用域中的所有变量和函数。

下面是一个简单的例子:

function outerFunction() {var outerVariable = "I am from the outer function";function innerFunction() {console.log(outerVariable);}return innerFunction;
}var innerFunc = outerFunction(); // 调用 outerFunction 返回内部的 innerFunction
innerFunc(); // 这里会输出 "I am from the outer function"

在这个例子中,innerFunction 是一个闭包。即使 outerFunction 已经执行完毕,innerFunction 仍然能够访问 outerVariable,因为它被保存在了闭包中。当我们调用 innerFunc() 时,它仍然能够访问并输出 outerVariable 的值,因为闭包记住了创建它的环境。

六、数组(Arrays)和对象(Objects)

1. 数组(Arrays)
  • 创建数组:数组是一种有序的数据集合,可以容纳不同类型的数据。可以通过字面量表示法或构造函数来创建数组。

    // 使用字面量表示法创建数组
    var fruits = ['apple', 'banana', 'orange'];// 使用构造函数创建数组
    var numbers = new Array(1, 2, 3, 4, 5);
    

构造函数(Constructor Function)是 JavaScript 中一种特殊的函数,用于创建和初始化对象。当你使用 new 关键字来调用一个函数时,该函数被称为构造函数,并返回一个新创建的对象实例。构造函数通常用于创建多个具有相似特性的对象。(跟java语法一样)

构造函数的特点包括:

  1. 使用 new 关键字调用:构造函数通过 new 关键字来调用,例如 new Constructor()

  2. 对象初始化:构造函数通常用于初始化新创建的对象,可以在构造函数内部定义对象的属性和方法。

  3. this 关键字:构造函数内部使用 this 关键字引用新创建的对象实例,以便在对象上设置属性和调用方法。

  4. 不显式返回值:通常情况下,构造函数不需要显式地返回值。当你使用 new 关键字调用构造函数时,它会自动返回新创建的对象实例。

示例:

// 构造函数定义
function Person(name, age) {this.name = name;this.age = age;this.sayHello = function() {console.log('Hello, my name is ' + this.name + ' and I am ' + this.age + ' years old.');};
}// 使用构造函数创建对象实例
var person1 = new Person('Alice', 30);
var person2 = new Person('Bob', 25);// 调用对象方法
person1.sayHello(); // 输出 "Hello, my name is Alice and I am 30 years old."
person2.sayHello(); // 输出 "Hello, my name is Bob and I am 25 years old."

在这个示例中,Person 函数是一个构造函数,用于创建 Person 对象。通过 new Person() 调用构造函数可以创建多个 Person 对象实例,并可以使用 this 关键字在构造函数内部为每个对象设置属性和方法。

  • 访问数组元素:可以通过索引来访问数组中的元素,索引从 0 开始。

    console.log(fruits[0]); // 输出 'apple'
    
  • 操作数组:数组提供了许多方法来操作数组,如添加、删除、替换、合并等。

    // 添加元素到数组末尾
    fruits.push('grape');// 删除数组末尾的元素
    fruits.pop();// 替换数组中的元素
    fruits[1] = 'pear';// 合并两个数组
    var allFruits = fruits.concat(['kiwi', 'melon']);
    

concat() 方法解释: 

这行代码是使用 JavaScript 中的 concat() 方法将两个数组合并成一个新的数组。具体来说:

  • fruits 是一个数组,包含了一些水果的名称。
  • ['kiwi', 'melon'] 是另一个数组,包含了另外两种水果的名称。
  • concat() 方法会将两个数组合并成一个新的数组,新数组中先包含 fruits 数组中的所有元素,然后再依次添加 ['kiwi', 'melon'] 数组中的元素。
  • 最终结果存储在 allFruits 变量中,它是一个包含了所有水果名称的新数组。

举例来说,如果 fruits 数组包含 ['apple', 'banana', 'orange'],那么执行 var allFruits = fruits.concat(['kiwi', 'melon']); 后,allFruits 数组将包含 ['apple', 'banana', 'orange', 'kiwi', 'melon']

2. 对象(Objects)
  • 创建对象:对象是键值对的集合,用于存储和组织数据。可以使用对象字面量或构造函数创建对象。

    // 使用对象字面量创建对象
    var person = {name: 'John',age: 30,city: 'New York'
    };// 使用构造函数创建对象
    var car = new Object();
    car.make = 'Toyota';
    car.model = 'Camry';
    car.year = 2022;
    
  • 访问对象属性:可以使用点符号或方括号来访问对象的属性。

    console.log(person.name); // 输出 'John'
    console.log(car['make']); // 输出 'Toyota'
    
  • 对象方法:对象可以包含方法,方法是存储在对象属性中的函数。

    var circle = {radius: 5,area: function() {return Math.PI * this.radius * this.radius;}
    };console.log(circle.area()); // 输出圆的面积
    

七、DOM操作

理解 DOM(文档对象模型)操作对于前端开发至关重要

1. DOM 的概念和层次结构
  • DOM 是什么:DOM 是一种用于表示和操作 HTML、XML 和 XHTML 文档的 API(应用程序编程接口)。
  • DOM 树的层次结构:DOM 树是由多个节点组成的层次结构。每个节点代表文档中的一个元素、属性或文本。DOM 树的顶级节点是文档节点(document),其下包含了整个文档的内容,包括 <html> 元素、文本节点、注释节点等。
2. JavaScript 如何操作 DOM 元素
  • 选择元素:可以使用各种方法选择文档中的元素,如 getElementById()getElementsByClassName()getElementsByTagName()querySelector()querySelectorAll()
  • 修改元素:一旦选择了元素,就可以使用 JavaScript 来修改其内容、样式、属性等。例如,通过 innerHTML 属性来修改元素的 HTML 内容,通过 style 属性来修改元素的样式。
  • 创建和删除元素:可以使用 createElement() 方法创建新元素,并使用 appendChild()insertBefore()removeChild() 等方法来添加或删除元素。

通俗理解: 

DOM(文档对象模型)可以被理解为网页的结构化表示,它允许我们使用 JavaScript 来与网页的内容进行交互和操作。通俗地说,你可以把 DOM 想象成一个树形结构,其中每个节点代表网页中的一个元素,比如段落、图片、链接等。

举个例子来解释,假设我们有一个简单的 HTML 页面:

<!DOCTYPE html>
<html>
<head><title>DOM 示例</title>
</head>
<body><h1>欢迎来到我的网站!</h1><p>这是一个示例段落。</p><img src="example.jpg" alt="示例图片"><a href="https://example.com">示例链接</a>
</body>
</html>

在这个页面中,<html> 元素是整个文档的根节点,它包含了 <head><body> 元素。<head> 元素包含文档的头部信息,如标题(<title>);<body> 元素包含文档的主要内容,如标题(<h1>)、段落(<p>)、图片(<img>)和链接(<a>)等。

通过 JavaScript,我们可以访问和操作这些元素,比如:

// 获取标题元素
var title = document.getElementsByTagName('title')[0];// 获取段落元素
var paragraph = document.getElementsByTagName('p')[0];// 修改段落文本内容
paragraph.textContent = '这是修改后的段落内容';// 创建新的段落元素
var newParagraph = document.createElement('p');
newParagraph.textContent = '这是新创建的段落。';// 将新段落添加到文档主体
document.body.appendChild(newParagraph);

在这个例子中,我们使用了 DOM 来获取文档中的标题和段落元素,并修改了段落的内容。我们还创建了一个新的段落元素,并将其添加到文档主体中。这样,我们就可以使用 JavaScript 来动态地操作网页的内容,使之更加交互和动态。

3. 事件处理器的绑定和使用
  • 事件:事件是文档或浏览器窗口中发生的交互行为,如点击、鼠标移动、键盘按键等。
  • 事件处理器:可以使用事件处理器来捕获和处理事件,常见的事件处理器有 onclickonmouseoveronkeydown 等。也可以使用 addEventListener() 方法来动态地添加事件监听器。
  • 事件对象:当事件发生时,浏览器会创建一个事件对象,并将其传递给事件处理器。事件对象包含了关于事件的详细信息,如事件类型、触发事件的元素等。

假设我们有一个 HTML 页面,其中包含一个按钮元素:

<!DOCTYPE html>
<html>
<head><title>事件处理器示例</title>
</head>
<body><button id="myButton">点击我</button><div id="output"></div><script>// 获取按钮元素和输出元素var button = document.getElementById('myButton');var output = document.getElementById('output');// 定义点击事件处理器function handleClick() {output.textContent = '按钮被点击了!';}// 将点击事件处理器绑定到按钮上button.addEventListener('click', handleClick);</script>
</body>
</html>

在这个例子中,我们首先获取了页面中的按钮元素和一个用于输出信息的 <div> 元素。然后,我们定义了一个名为 handleClick 的函数,该函数用于处理按钮的点击事件。当按钮被点击时,handleClick 函数将在输出元素中显示一条消息。

最后,我们使用 addEventListener() 方法将 handleClick 函数与按钮的 click 事件相关联。这意味着当按钮被点击时,浏览器会调用 handleClick 函数,从而执行我们在函数中定义的操作。

八、异步编程

1. 回调函数(Callback Functions)
  • 概念:回调函数是一种通过将函数作为参数传递给另一个函数来处理异步操作的方法。当异步操作完成时,回调函数将被调用,以处理操作的结果。
  • 示例
    function fetchData(callback) {setTimeout(function() {const data = 'Some data fetched from server';callback(data); // 异步操作完成后调用回调函数,并传递数据}, 2000);
    }function processData(data) {console.log('Processing data:', data);
    }fetchData(processData); // 调用 fetchData 函数,并传递 processData 函数作为回调
    
2. Promise 对象的使用
  • 概念:Promise 是 JavaScript 中处理异步操作的对象,它代表了一个异步操作的最终完成(或失败)及其结果的值。
  • Promise 的状态:Promise 对象有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。
  • 示例
    function fetchData() {return new Promise(function(resolve, reject) {setTimeout(function() {const data = 'Some data fetched from server';resolve(data); // 异步操作成功时调用 resolve}, 2000);});
    }fetchData().then(function(data) {console.log('Data fetched:', data);}).catch(function(error) {console.error('Error fetching data:', error);});
    

通俗解释: 

想象一下,你和朋友约好了去看电影,但是你朋友总是让你等待。你希望在确定你朋友已经准备好之后再出发。这时候你可以使用 Promise 来表示这个约定。

在 JavaScript 中,Promise 是一种表示异步操作最终完成或失败的对象。它有三种状态:pending(进行中)、fulfilled(已完成)和rejected(已失败)。当异步操作完成时,Promise 变为 fulfilled 状态;当异步操作失败时,Promise 变为 rejected 状态。

下面是一个使用 Promise 的例子:

假设你要下载一张图片,并在下载完成后在页面上显示。你可以使用 Promise 来处理这个异步操作。

// 创建一个 Promise 对象
var downloadImage = new Promise(function(resolve, reject) {// 模拟下载过程setTimeout(function() {// 假设下载成功var imageUrl = 'example.jpg';resolve(imageUrl); // 标记 Promise 为成功状态,并返回图片 URL}, 2000); // 假设下载需要 2 秒钟
});// 处理 Promise 结果
downloadImage.then(function(imageUrl) {// 下载成功,显示图片var imgElement = document.createElement('img');imgElement.src = imageUrl;document.body.appendChild(imgElement);
}).catch(function(error) {// 下载失败,显示错误信息console.error('Failed to download image:', error);
});

在这个例子中,downloadImage 是一个 Promise 对象,表示图片的下载过程。当图片下载完成时,Promise 将被标记为 fulfilled 状态,并返回图片的 URL。然后我们使用 then() 方法来处理成功的情况,将图片显示在页面上。如果下载失败,Promise 将被标记为 rejected 状态,并通过 catch() 方法来处理失败的情况,打印错误信息。

3. async/await 语法的使用
  • 概念:async/await 是 ES2017(ES8)引入的异步编程语法,它提供了一种更直观、更易读的方式来处理异步操作。
  • async 函数:async 函数是返回 Promise 的函数,它内部可以包含异步操作,通过 await 关键字可以暂停函数的执行,直到异步操作完成。
  • 示例
    async function fetchData() {return new Promise(function(resolve, reject) {setTimeout(function() {const data = 'Some data fetched from server';resolve(data); // 异步操作成功时调用 resolve}, 2000);});
    }async function processAsyncData() {try {const data = await fetchData(); // 等待 fetchData 函数的完成,并获取数据console.log('Data fetched:', data);} catch (error) {console.error('Error fetching data:', error);}
    }processAsyncData();
    

    通俗解释:

想象一下你去购物,你希望先去商店购买食物,然后再去银行取钱。在拿到食物之前你不想去银行,因为你可能会饿着肚子排队等待。

在 JavaScript 中,async/await 是一种处理异步操作的方式,让代码看起来更像同步代码,更容易理解和编写。

举个例子,假设你使用 async/await 来执行上述的购物和取钱的操作:

// 定义一个购物函数,返回一个 Promise 对象
async function goShopping() {console.log('我要去商店购买食物。');// 模拟购买食物的异步操作await buyFood();console.log('我已经买到食物了!');console.log('我要去银行取钱。');// 模拟去银行取钱的异步操作await withdrawMoney();console.log('我已经取到钱了!');
}// 定义一个购买食物的函数,返回一个 Promise 对象
function buyFood() {return new Promise(resolve => {setTimeout(() => {console.log('成功购买食物!');resolve();}, 2000); // 假设购买食物需要 2 秒钟});
}// 定义一个取钱的函数,返回一个 Promise 对象
function withdrawMoney() {return new Promise(resolve => {setTimeout(() => {console.log('成功取到钱!');resolve();}, 1000); // 假设取钱需要 1 秒钟});
}// 调用购物函数
goShopping();

在这个例子中,goShopping 函数是一个异步函数,使用了 async 关键字来声明。在函数内部,我们用 await 关键字来等待购买食物和取钱的操作完成。这样,当调用 goShopping 函数时,它会按顺序执行购买食物和取钱的操作,而不会在拿到食物之前去取钱,使得整个过程更符合我们的直觉和期望。

九、错误处理和调试

  • 常见错误类型

    • 语法错误(Syntax Errors):由于代码不符合 JavaScript 的语法规则而引起的错误,通常会在代码执行之前被捕获。
    • 运行时错误(Runtime Errors):在代码执行过程中发生的错误,比如试图引用未定义的变量或调用不存在的函数等。
    • 逻辑错误(Logic Errors):代码逻辑不正确导致的错误,可能不会引发异常,但会产生错误的结果。
  • 错误处理方法

    • try-catch 语句:使用 try-catch 语句可以捕获和处理代码中的异常,以避免程序中断。
      try {// 可能会引发异常的代码
      } catch (error) {// 处理异常的代码
      }
      
    • throw 语句:使用 throw 语句手动抛出异常。
      throw new Error('This is an error message');
      
    • finally 语句块:finally 语句块包含的代码会在 try-catch 语句块执行完成后无论是否发生异常都会执行。
      try {// 可能会引发异常的代码
      } catch (error) {// 处理异常的代码
      } finally {// 无论是否发生异常都会执行的代码
      }
      

十、ES6+新特性

1. let 和 const 关键字
  • let 关键字:用于声明块级作用域的变量,其作用范围仅限于所在的块级作用域内。

    let x = 10;
    if (true) {let y = 20;console.log(x); // 输出 10console.log(y); // 输出 20
    }
    console.log(x); // 输出 10
    console.log(y); // 报错,y 在此作用域不可用
    
  • const 关键字:用于声明一个只读的常量,一旦被赋值就不能再改变。

    const PI = 3.14;
    PI = 3; // 报错,常量不能被重新赋值
    
2. 箭头函数(Arrow Functions)
  • 箭头函数是一种更简洁的函数定义方式,可以更方便地书写匿名函数,并且自动绑定了 this
    // 普通函数
    function add(a, b) {return a + b;
    }// 箭头函数
    const add = (a, b) => a + b;
    
3. 模板字符串(Template Literals)
  • 模板字符串允许在字符串中嵌入变量和表达式,使用反引号 ` 包裹字符串,并使用 ${} 来插入变量或表达式。
    const name = 'Alice';
    const greeting = `Hello, ${name}!`;
    console.log(greeting); // 输出 "Hello, Alice!"
    
4. 解构赋值(Destructuring Assignment)
  • 解构赋值允许从数组或对象中提取值,并赋给变量,可以更方便地操作数组和对象中的数据。
    // 数组解构赋值
    const [a, b] = [1, 2];
    console.log(a); // 输出 1
    console.log(b); // 输出 2// 对象解构赋值
    const { firstName, lastName } = { firstName: 'John', lastName: 'Doe' };
    console.log(firstName); // 输出 "John"
    console.log(lastName); // 输出 "Doe"
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/718064.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一个教材上的CMS网站源码在Linux服务器上登录时验证码正常,但在windows下不能正常显示

一个教材上的CMS网站源码在Linux服务器上登录时验证码正常&#xff0c;但在windows下不能正常显示。 在linux服务器上能正常显示。显示界面如下所示&#xff1a;

蜻蜓FM语音下载(mediadown)

一、介绍 蜻蜓FM语音下载&#xff08;mediadown&#xff09;&#xff0c;能够帮助你下载蜻蜓FM音频节目。如果你是蜻蜓FM会员&#xff0c;它还能帮你下载会员节目。 二、下载地址 本站下载&#xff1a;蜻蜓FM语音下载&#xff08;mediadown&#xff09; 百度网盘下载&#…

Web 应用防火墙(WAF):功能、应用场景和未来发展方向

Web 应用防火墙&#xff08;WAF&#xff09;是一种用于保护 Web 应用程序免受各种网络攻击的安全工具。WAF 可以检测并阻止对 Web 应用程序的恶意攻击&#xff0c;如SQL 注入、跨站脚本&#xff08;XSS&#xff09;和跨站请求伪造&#xff08;CSRF&#xff09;等。它通过检查 H…

【Redis 主从复制】

文章目录 1 :peach:环境配置:peach:1.1 :apple:三种配置方式:apple:1.2 :apple:验证:apple:1.3 :apple:断开复制和切主:apple:1.4 :apple:安全性:apple:1.5 :apple:只读:apple:1.6 :apple:传输延迟:apple: 2 :peach:拓扑结构:peach:2.1 :apple:⼀主⼀从结构:apple:2.2 :apple:⼀…

【MetaGPT】配置教程

MetaGPT配置教程&#xff08;使用智谱AI的GLM-4&#xff09; 文章目录 MetaGPT配置教程&#xff08;使用智谱AI的GLM-4&#xff09;零、为什么要学MetaGPT一、配置环境二、克隆代码仓库三、设置智谱AI配置四、 示例demo&#xff08;狼羊对决&#xff09;五、参考链接 零、为什么…

大数据技术(一)

大数据技术概述 大数据技术层面及其功能 数据采集与预处理 利用ETL(extract-transform-load)工具将分布的、异构数据源中的数据&#xff0c;如关系数据、平面数据文件等&#xff0c;抽取到临时中间层后进行清洗、转换、集成&#xff0c;最后加载到数据仓库或数据集市中&…

C语言什么是循环嵌套?

一、问题 分⽀结构是可以进⾏嵌套的&#xff0c;循环结构同样也⽀持嵌套&#xff0c;那什么是循环嵌套呢&#xff1f; 二、解答 ⼀个循环体内⼜包含另⼀个完整的循环结构&#xff0c;就称之为循环嵌套。内嵌的循环中还可以嵌套循环&#xff0c;这就是多层循环&#xff0c;也叫…

类与对象详解 C++ (1)

1.struct和class 与C语言不同的是&#xff0c;C中struct和class可以定义成员变量和成员函数。更偏好用class。 2.类的定义 格式如下&#xff1a; class 为 定义类的 关键字&#xff0c; ClassName 为类的名字&#xff0c; {} 中为类的主体&#xff0c;注意 类定义结束时后面…

前端canvas项目实战——简历制作网站(五):右侧属性栏(字体、字号、行间距)

目录 前言一、效果展示二、实现步骤1. 优化代码&#xff0c;提取常量2. 实现3个编辑模块3. 实现updateFontProperty方法4. 一个常见的用法&#xff1a;仅更新当前选中文字的样式 三、Show u the code后记 前言 上一篇博文中&#xff0c;我们扩充了线条对象&#xff08;fabric.…

springboot 整合oauth2

1、EnableOAuth2Client&#xff1a;客户端&#xff0c;提供OAuth2RestTemplate&#xff0c;用于客户端访问资源服务。 简要步骤&#xff1a;客户端访问资源->客户端发现没有资源访问token->客户端根据授权类型生成跳转url->浏览器 302 到认证授权服务进行认证、授权。…

Dockerfile构建过程详解

Dockerfile介绍 docker是用来构建docker镜像的文件&#xff01;命令参数脚本&#xff01; 构建步骤&#xff1a; 1、编写一个dockerfile文件 2、docker build构建成为一个镜像 3、docker run 运行镜像 …

PDF转Excel的未来:人工智能技术如何提升转换效率和准确性

随着信息技术的快速发展&#xff0c;PDF和Excel作为两种重要的文件格式&#xff0c;在日常生活和工作中扮演着至关重要的角色。PDF以其独特的跨平台阅读特性&#xff0c;成为了文件分享和传输的首选格式&#xff1b;而Excel则以其强大的数据处理能力&#xff0c;成为了数据分析…

【二分查找】【C++算法】378. 有序矩阵中第 K 小的元素

作者推荐 视频算法专题 本文涉及的基础知识点 二分查找算法合集 LeetCode378. 有序矩阵中第 K 小的元素 给你一个 n x n 矩阵 matrix &#xff0c;其中每行和每列元素均按升序排序&#xff0c;找到矩阵中第 k 小的元素。 请注意&#xff0c;它是 排序后 的第 k 小元素&…

机器人持续学习基准LIBERO系列10——文件结构

0.前置 机器人持续学习基准LIBERO系列1——基本介绍与安装测试机器人持续学习基准LIBERO系列2——路径与基准基本信息机器人持续学习基准LIBERO系列3——相机画面可视化及单步移动更新机器人持续学习基准LIBERO系列4——robosuite最基本demo机器人持续学习基准LIBERO系列5——…

力扣日记3.3-【回溯算法篇】332. 重新安排行程

力扣日记&#xff1a;【回溯算法篇】332. 重新安排行程 日期&#xff1a;2023.3.3 参考&#xff1a;代码随想录、力扣 ps&#xff1a;因为是困难题&#xff0c;望而却步了一星期。。。T^T 332. 重新安排行程 题目描述 难度&#xff1a;困难 给你一份航线列表 tickets &#xf…

牛客小白月赛86

A-水盐平衡_牛客小白月赛86 (nowcoder.com) #include<bits/stdc.h> #define endl \n #define int long long using namespace std; int a,b,c,d; void solve() {cin>>a>>b>>c>>d;if((double)a/b>(double)c/d) cout<<S<<endl;els…

关于脉冲负载应用中电阻器,您需要了解的 11 件事?

不幸的是&#xff0c;电阻器在脉冲负载下可能会失效。当脉冲功率耗散到器件的电阻元件时&#xff0c;它会产生热量并增加电阻器的温度。过热会损坏电阻元件&#xff0c;导致电阻变化甚至设备开路。为了避免在设计中出现这种情况&#xff0c;以下是您在选择元件时应了解的有关电…

excel统计分析——拉丁方设计

参考资料&#xff1a;生物统计学 拉丁方设计也是随机区组设计&#xff0c;是对随机区组设计的一种改进。它在行的方向和列的方向都可以看成区组&#xff0c;因此能实现双向误差的控制。在一般的试验设计中&#xff0c;拉丁方常被看作双区组设计&#xff0c;用于提高发现处理效应…

Skipped breakpoint at because it happened inside debugger evaluation亲测可用

问题描述&#xff1a; 在多线程项目中&#xff0c;在idea中打断点时&#xff0c;有时会遇到下面这种情况&#xff1a; idea左下角出现一行红底或者绿底文字提示&#xff1a; Skipped breakpoint at because it happened inside debugger evaluation 然后我们能感受到的就是…

HTML中自定义鼠标右键菜单

今天突然有人跟我提到了HTML中如何自定义鼠标右键菜单&#xff0c;这里大概记录一下吧&#xff0c;方便下次直接复制。免得还去看API文档。 文章目录 HTML中自定义鼠标右键菜单结果如下所示可以稍微改一下鼠标悬浮到右键菜单时的样式结果如下所示 只在某个特定的div才可以显示…