十三、附录:基本 JavaScript 概念

欢迎来到这本书的最后一章。我们将这一章放在了本书的末尾,以免让有经验的 JavaScript 开发人员对介绍性概念感到厌烦。希望在尝试使用Danfo.js之前复习 JavaScript 基础知识的开发人员应该阅读本章。

到本章结束时,您将理解 JavaScript 的基本概念,这些概念对于用该语言构建应用至关重要。您将了解数据类型、条件分支和循环结构以及 JavaScript 函数。

具体来说,我们将涵盖以下概念:

  • JavaScript 快速概述
  • 理解 JavaScript 的基础

技术要求

我们将在本章的所有代码示例中使用开发人员控制台。要在默认浏览器中运行任何代码片段,您需要打开开发人员控制台。下表显示了打开为各种浏览器提供的控制台的命令:

  • 谷歌 Chrome :在谷歌 Chrome 中打开开发者控制台,从浏览器窗口右上角打开 Chrome 菜单,选择更多工具 | 开发者工具。也可以使用 macOS 上的选项 + 命令 + J 快捷键,或者 Windows/Linux 上的Shift+Ctrl+J
  • 微软 Edge :在微软 Edge 中,打开浏览器窗口右上角的 Edge 菜单,选择 F12 开发者工具,也可以直接按 F12 打开。
  • Mozilla Firefox :在 Mozilla Firefox 中,点击浏览器右上角的 Firefox 菜单,选择Web Developer|BrowserConsole。也可以使用 macOS 上的shift++j快捷方式或者 Windows/Linux 上的shift+ctrl+j快捷方式。 Apple Safari: In Safari, you'll first need to enable the Developer menu in your browser settings. To do that, open Safari's preferences (Safari Menu | Preferences), select the Advanced tab, and then enable the Developer menu. Once that menu is enabled, you will find the developer console by clicking on Develop | Show JavaScript Console. You can also use the Option + + C shortcut.

    开发人员控制台打开后,根据您的浏览器,您将看到一个类似于此处所示的控制台:*

*Figure 13.1 – Chrome browser developer console

图 13.1–Chrome 浏览器开发人员控制台

打开控制台后,您就可以开始编写和测试 JavaScript 代码了。在下一节中,我们将快速浏览 JavaScript 语言的一些重要概念。

JavaScript 快速概述

根据 Stack Overflow 2020 开发者调查(https://Stack Overflow . blog/2020/05/27/2020-Stack-Overflow-Developer-Survey-results/), JavaScript (也称为 JS )是世界上最常见的编程语言,大约有 70%的开发者使用它来完成这样或那样的任务。这一统计数据并不令人惊讶,因为在调查进行之前的很多年里,JavaScript 一直是最流行的语言。出现这种情况的原因有很多,我们将在此列出其中一些原因:

  • 它运行在最常见和最容易获得的平台——浏览器上。
  • 围绕它构建了许多有用的框架,如 Node.js、React 和 Angular。
  • 它是通用的,也就是说,它可以用于前端和后端应用。例如,您可以使用诸如 React、Vue 和 Angular 之类的 JavaScript 库来构建出色的用户界面 ( UIs ),而您可以使用诸如 Node.jS 和 Deno 之类的服务器端包来构建高效的后端/服务器端应用。
  • 可以用于物联网 ( 物联网)和跨平台移动应用。

JavaScript 最初被创建为一种只支持浏览器的语言,但很快发展到几乎可以在任何地方使用,从前端应用到使用 Node.js 的后端应用,再到物联网应用,以及最近的数据科学/ 机器学习 ( ML )领域。

注意

不要把 JavaScript 和 Java 编程语言(https://en . Wikipedia . org/wiki/Java _(programming _ language))混为一谈。虽然名字可能相似,但在用法、语法甚至语义方面却大不相同。

JavaScript 是动态的和事件驱动的,因此是众多关注的主题,尤其是对于来自其他语言的程序员。这导致了可以直接转换成 JavaScript 的语言的产生。其中一些语言是类型脚本(微软开发的一种数据类型严格的语言) Dart (谷歌开发的一种独立语言)咖啡脚本等等。

了解 JavaScript 的基础知识

在本节中,作为记忆复习,我们将快速复习现代 JavaScript 的基本概念。如果你熟悉 JavaScript,那么你可以跳过这一节。

正如我们反复提到的,JavaScript 可以用于前端和服务器端脚本,因此有特定于每个环境的语法或特性——例如,浏览器端的 JavaScript 由于安全原因不能访问诸如 Node.js 这样的文件系统。因此,在本节中,我们将介绍可以在两种环境/任何环境中工作的概念。

声明变量

变量被命名为存储数据。它们可以用来存储 JavaScript 可以操作或处理的数据。在 JavaScript 中,您可以使用两个主要关键字constlet来定义变量,尽管在旧的脚本中,您会发现var关键字用于声明变量。一般不建议使用var进行变量声明,应该很少使用。在后面的部分,我们将讨论为什么在现代 JavaScript 中鼓励使用let而不是var的一些原因。

以下语句使用let关键字声明了一个变量:

let name;
let price = 200;
let message, progress, id;

message = "This is a new message";
progress = 80;
id = "gh12345";

下一个关键字const可以用来声明一个常量变量,也就是说,一个变量的引用在应用运行期间不能被更改。

下面的代码片段显示了一些const声明的例子:

const DB_NAME;
const LAST_NAME = "Williams";
const TEXT_COLOR = "#B00";
const TITLE_COLOR = "#F00";

重要说明

在声明常量时使用大写的变量名是一种常见且被广泛鼓励的做法,不仅在 JavaScript 中,在许多编程语言中也是如此。

数据类型

JavaScript 支持八种基本数据类型。声明变量的数据类型是由 JavaScript 编译器在运行时自动推断的,因为 JavaScript 是一种动态类型语言。支持的八种数据类型为字符串布尔对象BigInt未定义空值符号

数字

number类型可以代表integersfloating-point numbersinfinity-infinity不是数字 ( NaN )。Number 类型支持加减乘除等众多数学运算。在下面的代码片段中,我们定义了一些类型为number的变量:

let num1 = 10; //integer
let num2 = 20.234; //floating point number
console.log(num1 + num2); //outputs 30.234

重要说明

infinity-infinity代表数学上的正负无穷大(∞)。这些值比任何数字都大。你可以在这里看到一个例子:

console.log(1 / 0); // Infinity

NaN子类型表示用数字进行数学运算时的一个错误——例如,试图用数字除一个字符串,如下图所示:

console.log("girl" / 2); // NaN

线

JavaScript 中的字符串表示文本,必须用单引号(' ')、双引号(" ")或反引号(' ')包围。您可以在下面的代码片段中看到一些字符串示例:

let name = "John Doe";
let msg = 'I am on my way';
let address = '10 Slow ave, NY';

双引号或单引号的选择基于偏好,因为它们都执行相同的功能。另一方面,反向报价比基本报价有更多的功能。它们允许您使用${...}模板文字语法轻松地将变量和表达式嵌入到字符串中。例如,在下面的代码片段中,我们展示了如何将轻松地将nameaddressdog_counts变量嵌入到新变量消息中:

let name = "John Doe";
let address = '10 Slow ave, NY';
let dog_counts = 10;
let msg = '${name} lives in ${address} and has ${dog_counts} dogs';
console.log(msg)

//outputs
John Doe lives in 10 Slow ave, NY and has 10 dogs

小费

字符串数据类型有许多用于操作它的内置函数。您可以在 Mozilla 开发者网络 ( MDN )文档页面(https://Developer . Mozilla . org/en-US/docs/Web/JavaScript/Reference/Global _ Objects/String)上找到其中的许多功能。

布尔代数学体系的

布尔数据类型是一种逻辑类型。它只有两个值:truefalse。布尔值主要用于比较操作和存储 / 值。让我们看看下面的例子:

let pageClicked = false; // No, the page was not clicked
let pageOpened = true; // Yes, the page was opened

if (5 > 1) { //Evaluates to the Boolean value true
  console.log("Yes! It is.")
}

接下来,我们来谈谈对象类型。

目标

JavaScript 中的对象是一个非常特殊的类型。它可能是 JavaScript 中最重要的类型,几乎用于语言的每个方面。对象数据类型是 JavaScript 中唯一的非原语类型。它可以存储不同类型数据的键控集合,包括它自己。

小费

编程语言中的基元类型是最基本的类型,通常存储单一种类的值。另一方面,非基元类型可以存储多种类型的值,也可以扩展以执行其他功能。

创建对象有两种方法,如下所示:

  • The first and most common way is to use curly brackets with an optional list of key-value properties, as illustrated here:

    let page = {}

  • And a not so common way is by using object constructor syntax, as follows:

    let page = new Object()

可以在同一个步骤中创建和初始化对象,如下面的代码片段所示:

let page = {
  title: 'Home page',
  Id: 23422,
  text: 'This is the first page in my website',
  rank: 32.09,
  "closed": false,
  owner: {
    name: 'John Doe',
    level: 'admin',
    lastLoggedIn: 'Aug 5th',
  },
}

注意一个对象页面可以存储多种类型的数据,甚至其他对象(作为所有者)。这表明对象可以嵌套以包含越来越多的对象。

要访问对象值,可以使用方括号,如下所示:

console.log(page["closed"])
//outputs false

或者,您可以使用点page.rank符号,如下所示:

console.log(page.rank)

这给出了以下输出:

//outputs 32.09

第 1 章现代 JavaScript 概述中,您了解到了一些使对象非常强大的重要属性。

条件分支和循环

条件分支和循环是任何编程语言的重要方面,JavaScript 也提供了它们。要根据某些条件执行不同的操作,可以使用ifif..else、条件/三元运算符和switch 语法。除了条件分支之外,您可能希望执行特定次数的重复操作。这就是循环发挥作用的地方。JavaScript 提供循环结构,如whiledo...whilefor..offor..in和传统的for循环。在下一节中,我们将简要介绍每一种说法。

如果语句

一条if语句计算括号中的一个表达式、一个条件或一段代码的,并且只有当它是true时才会执行该语句。这是一个单向条件,只有在为真时才会运行。您可以在下面的代码片段中看到一个这样的例子:

let age = 25
if (age >= 18){
  console.log("You're an adult!")  //will run since age is greater than 18
}
//outputs
You're an adult!

如果...else 语句

一个if...else语句提供了一个额外块,当初始条件变为false时运行。这里有一个例子:

let age = 15
if (age > 18){
  console.log("You're an adult!")
}else{
  console.log("You're still a teenager!")
}
//outputs
You're still a teenager!

条件/三元运算符

三元运算符是一种更短更“T2”的简洁方式来写一个“T0”语句。它主要用于根据两个条件分配变量。三元运算符的语法如下所示:

let result = condition ? val1 : val2;

如果条件为真,则val1执行并分配给result,否则val2被分配。下面的代码片段显示了一个使用它的示例:

let age = 20
let isAdult = age > 18 ? true : false; //age is greater than 18, so true is returned
console.log(isAdult) 
//outputs
true 

交换语句

一个switch语句可以用一个更简洁易读的方式替换多个if...else语句。语法如下所示:

switch(value) {
  case 'option1':  // if (value === 'option1')
    ...
    [break]
  case 'option2':  // if (value === 'option2')
    ...
    [break]
 case 'option3':  // if (value === 'option3')
    ...
    [break]
  default:
    ...
    [break]
}

根据每个case 语句检查switch括号中的变量或表达式,如果条件为真,则执行相应的代码。当每隔一个条件失败时,就会执行默认语句。以下代码片段显示了使用switch语句的示例:

let value = 4
switch (value) {
  case 1:
    console.log( 'You selected 1' );
    break;
  case 2:
    console.log( 'You selected 2' );
    break;
  case 4:
    console.log( 'You selected 4!' ); //gets executed
    break;
  default:
    console.log( "No such value" );
}

//outputs
"You selected 4!"

在之后的一个break声明在中是重要的,以便停止后续案件的执行。如果忽略break语句,那么后续的案例也会被执行。

while 循环

只要条件为真,一个while循环将重复执行一段代码。下面的代码片段显示了语法:

while (condition) {
  // loop body
}

让我们看看下面使用while循环的例子:

let year = 2015;
while (year <= 2020) {
  console.log( year );
  year++
}
//outputs
2015
2016
2017
2018
2019
2020

只要小于或等于2020,前面的代码就会连续打印出年份。注意year++部分。为了在某个时候打破while循环,这一点很重要。

做…同时循环

一个do...while循环非常类似于一个while循环,只有一点不同——在测试条件之前,身体至少被执行一次。语法如下所示:

do {
  // loop body
} while (condition);

让我们看看下面这个do...while循环的例子:

let year = 2015;
do {
  console.log( year );
  year++;
} while (year <= 2020);

如果您需要在执行条件检查之前至少执行一段代码一次,那么do...while循环非常重要。

重要说明

请始终记住设置一个条件,在某个时候中断一个循环,否则您的循环将永远执行,尽管理论上,浏览器和服务器端会在一定时间后停止这样的循环。

for 循环

一个for循环是 JavaScript 中最流行的循环构造。的语法如下所示:

for (initialization; condition; step) {
  // loop body
}

语法有三个重要部分,概述如下:

  • 初始化部分:在循环开始前执行。您将在这里初始化一个迭代器变量——例如(let i = 0)。
  • 条件部分:该代码在每次循环交互前都经过检查。如果为假,则循环停止。
  • 步长部分:步长很重要,因为它一般会增加一个待测试的计数器或者变量。

这里给出了一个使用for循环的的例子:

for (let i=0; i <=5; i++){
  console.log(i)
}
//outputs
0
1
2
3
4
5

注意

请注意,我们在for循环的步骤部分使用了后增量运算符(i++)?这是相当标准的,这只是i = i + 1的简写。

为...的和为的...成圈

for...offor...in循环是for循环的变体,用于在可迭代对象上迭代。iterable是特殊的数据类型,例如对象、数组、映射和具有 iterable 属性的字符串,换句话说,属性或值可以循环通过。

for...of循环主要用于迭代数组和字符串等对象。语法如下所示:

for (let val of iterable) {
  //loop body
}

让我们看看跟随使用for...of循环的例子:

let animals = [ "bear", "lion", "giraffe", "jaguar" ];
// Print out each type of animal
for (let animal of animals) {
    console.log(animal);
}
//outputs
"bear"
"lion"
"giraffe"
"jaguar"

for...in循环用于在对象上循环。语法非常类似于for...of循环,如以下代码片段所示:

for (let val in iterable) {
  //loop body
}

一个for...in循环应该是只用于像对象这样的可枚举,而不是像数组这样的可枚举。

这里显示了一个使用for...in循环的示例:

let user = {
  name: "Hannah Montana",
  age: 24,
  level: 2,
};
for (key in user) {
    console.log(user[key]);
}
//outputs
"Hannah Montana"
24
2

进一步阅读

for...infor...of是循环构造,用于迭代数据结构。它们之间的主要区别是它们迭代的数据结构。for...in迭代一个对象的所有可枚举属性键,而for...of迭代一个可迭代对象的值。

JavaScript 函数

在这一节中,我们将学习关于 JavaScript 函数的知识。函数在我们需要编写更干净的代码来重用脚本中许多部分的现有块时非常重要。从本章开始,每当我们需要向控制台打印文本时,我们就调用console.log内置函数。这表明函数是多么重要,因为单个函数一旦定义,就可以以任何方式和任何次数被调用来执行相同的操作。

JavaScript 中的一个函数通常如下所示:

function sayHi() {
  console.log('Hello World!')
}
sayHi()
//output
"Hello World!"

一个函数还可以在圆括号中包含一个逗号分隔的参数列表,用于执行计算。例如,带有一些参数的函数通常如下所示:

function sayHi(name, message) {
  console.log('This is a message from ${name}. The message read thus: ${message}')
}

sayHi("Jenny", "How are you doing?")
//output
"This is a message from Jenny. The message read thus: How are you doing?"

这里列出了一些关于函数的重要注意事项:

  • 函数内部声明的变量是该函数的局部变量,只能在函数内部访问。这里有一个例子:

    ```js function sayHi() {   let name = 'Jane'   console.log(name) }

    sayHi() //output "Jane" console.log(name) //throws error: ReferenceError: name is not defined ```

  • 一个函数可以访问全局变量。全局变量是在函数范围之外声明的变量,每个代码块都可以使用。你可以在这里看到一个例子:

    js let name = 'Jenny' function sayHi() {   console.log(name) } sayHi() //output "Jenny"

  • Functions can return values. This is important when a function performs some computation and the result needs to be used elsewhere. The functions we have been working with up till now mostly return nothing/undefined and they are referred to as void functions. Let's look at the following example of a function returning a value:

    ```js function add(num1, num2) {   let sum = num1 + num2   return sum } let result = add(25, 30) console.log(result)

    //output 55 ```

    小费

    函数中的return语句一次只能返回一个值。为了返回多个值,可以将结果作为 JavaScript 对象返回。你可以在这里看到一个例子:

    function add(num1, num2) {

    let sum = num1 + num2

    return {sum: sum, funcName: "add"}}

    let result = add(25, 30)

    console.log(result)

    //output

    Object { funcName: "add", sum: 55}

回调函数

回调在 JavaScript 中非常重要。回调是作为参数传递给另一个函数的函数。调用此参数是为了根据外部函数中的某些条件执行某些操作。让我们看下面的例子来更好地理解回调:

function showValue(value) {
  console.log(value)
}
function err() {
  console.log("Wrong value specified!!")
}

在前面的代码示例中,我们创建了两个回调函数showValueerror。您可以在下面的代码片段中看到这些正在使用:

function printValues(value, showValue, error) {
  if (value > 0){
    showValue(value)
  }else{
    error()
  }
}

showValue回调函数将传递给它的参数打印到控制台,而error回调函数打印一条错误消息。现在可以使用回调函数了,如下面的代码片段所示:

printValues(20, showValue, err);
//outputs 20

printValues(0, showValue, err);
//outputs "Wrong value specified!!"

printValues函数首先测试该值是否大于0,然后调用showValueerror回调函数。

回调不仅仅接受命名函数。他们也可以接受匿名函数;有了这个,就有可能创建嵌套回调

假设我们有一个doSomething函数,它执行一个特定的任务,我们希望在任务完成之前执行不同的操作。这意味着我们可以将一个回调函数传递给另一个回调函数,从而创建嵌套回调,如下面的代码块所示:

doSomething(((((()=>{
//dosomething A
         })=>{
    //dosomething B
       })=>{
   //dosomething C
     })=>{
  //dosomething D
   })=>{
 //dosomething E
})

前面的代码就是我们所说的回调地狱。这种方法有很多问题,变得难以管理。在 第 1 章现代 JavaScript 概述中,我们介绍了一种通过使用应用编程接口 ( API )来处理回调的现代且更高效的方法。这要干净得多,并将消除许多与回调地狱相关的问题。

重要说明

默认情况下,JavaScript 是异步的,因此长时间执行的函数会被排队,并且可能永远不会在您需要它们之前被执行。回调主要用于继续代码执行,并确保返回正确的结果。

总结

在本章中,我们介绍了 JavaScript 编程语言的基本方面。我们从一些基本的背景知识开始,解释了为什么 JavaScript 是当今世界上最流行的语言,以及 JavaScript 的各种用途。接下来,我们看了该语言的基本概念,其中我们谈到了声明变量以及 JavaScript 中可用的八种数据类型。接下来,我们讨论了 JavaScript 中的分支和循环结构,并展示了一些使用它们的示例,最后,我们简要讨论了 JavaScript 中的函数和类。*