Skip to content

Latest commit

 

History

History
615 lines (407 loc) · 30.2 KB

File metadata and controls

615 lines (407 loc) · 30.2 KB

四、数据和你的朋友——JSON

现在是时候学习 JavaScript 内部如何处理数据的细节了。 这些结构大多数(几乎)与 Python 相同,但在语法和用法上存在差异。 我们在第 3 章Nitty-Gritty Grammar中提到了它们,但现在是时候深入探讨我们如何使用数据和方法和属性了。 理解如何处理数据是使用 JavaScript 的基础,特别是在处理 api 和 Ajax 等高级工作时。

本章将涵盖以下主题:

  • 数据类型——JavaScript 和 Python 都是动态类型的!
  • 探索数据类型
  • 数组和集合
  • 对象和 JSON
  • HTTP 动词
  • 前端的 API 调用——Ajax

技术要求

从 GitHub 上https://github.com/PacktPublishing/Hands-on-JavaScript-for-Python-Developers克隆或下载这本书的库,并浏览Chapter-4材料。

数据类型——JavaScript 和 Python 都是动态类型的!

在第 3 章,本质语法【显示】,我们讨论了使用typeof()确定变量的数据类型是什么以及使用letconst定义它们。 关于 JavaScript, Python 有一个共通的有趣事实:两者都是动态类型的。 与 Java 等静态类型语言不同,JavaScript 的变量类型可以在程序过程中改变。 这就是为什么typeof()可以派上用场的原因之一。

让我们看一个简单的对比 JavaScript 和 Java 的例子:

| Java | JavaScript | |

int age;
age =  38;
age = "thirty-eight";

|

let age
age = 38
age = "thirty-eight"

|

如果我们尝试运行 Java 代码,我们会得到一个错误,说明类型是不兼容的。 在 Java 中,变量有一个类型。 然而,当我们运行 JavaScript 代码时,一切都很正常。 在 JavaScript 中,有一个类型。

同样重要的是,JavaScript 是弱类型,这意味着在大多数情况下,数据类型之间的隐式转换是允许的。 如果我们回想一下第 3 章Nitty-Gritty Grammar中的松散和严格相等操作符,那么弱类型正是当前最佳实践规定尽可能使用严格相等检查的原因。

如果我们从强/弱和动态/静态的角度来看几种语言,我们可以将这些语言绘制成如下坐标轴:

Figure 4.1 – Axes of typing

JavaScript 风格通常提倡使用描述性名称而不是简写名称。 这是可以接受的原因之一是,JavaScript 代码在投入生产之前通常是精简。 它不完全像编译,但它确实压缩空格和重命名变量来压缩。 我们将在第 16 章中讨论其中一些构建过程。

JavaScript 是动态弱类型的。 这在实践中意味着什么呢? 简短的答案是:小心! 在比较操作符中混淆类型是非常容易的,或者更糟糕的是,意外地将变量强制转换为不同的类型。 在我们编写程序时,它给了我们更多的灵活性,但它也可能是一种诅咒。 有些开发人员喜欢使用匈牙利符号(https://frontstuff.io/write-more-understandable-code-with-hungarian-notation)来帮助区分变量类型,但这在 JavaScript 中并不常见。 帮助您和您的同事保持类型正确的最好方法可能是显式地使用变量名。

探索数据类型

让我们更深入地研究基本数据类型,因为它们对我们的 JavaScript 工作至关重要。 我们不仅需要知道我们正在使用的,而且为什么也很重要。 我们的原语是语言其余部分的构建块:布尔值、数字和字符串。 JavaScript 的其余部分构建在这些基本数据类型之上。 我们从布尔值开始。

布尔值

Boolean可能是最简单和最通用的数据类型,因为它本质上与二进制逻辑的 1 和 0 绑定在一起。 在 JavaScript 中,布尔值被简单地写成truefalse。 不建议使用10作为布尔值,因为它们会被解释为数字,因此无法严格相等。 布尔值是一种特定的数据类型,而在 Python 中,在语言的核心,布尔值继承自数字。

还记得在第 3 章,*Nitty-Gritty Grammar,*中我们学到的 JavaScript 中的几乎所有东西都是对象吗? 这同样适用于布尔值。 正如你在下面的截图中所看到的,如果你在浏览器中打开 JavaScript 控制台,很有可能它会自动完成你的布尔方法:

Figure 4.2 – Boolean autocomplete in Chrome

现在,我怀疑这些方法是否对您特别有用,但它是检查给定变量可用的方法的一种简便方法。

布尔值到此为止,该看看数字了。

数字

JavaScript 没有不同类型的数字的概念,比如整数、浮点数或双精度数——一切都只是一个数字。 所有基本的算术方法都是内置的,Math对象提供了您希望在编程语言中找到的其余功能。 这里有一个例子:

let myNumber = 2.14
myNumber = Math.floor(myNumber) // myNumber now equals 2

你也可以使用科学符号,如下所示:

myNumber = 123e5  // myNumber is 12300000

JavaScript 中的数字不是普通的旧数字,而是浮点数。 从技术上讲,它们按照国际 IEEE 754 标准存储为双精度浮点数。 然而,这确实会导致一些有趣的怪癖。 如果你得到了奇怪的结果,请记住这一点,比如下面的 JavaScript 控制台截图:

Figure 4.3 – Floating-point precision error

一个经验法则是考虑你希望你的计算有多精确。 你可以使用一个数字的toPrecision()方法来指定你的精度,然后使用parseFloat()函数,如下所示:

let x = 0.2 + 0.1 // x = 0.30000000000000004
x = parseFloat(x.toPrecision(1)) // x = 0.3

toPrecision()返回一个字符串,乍一看似乎是反直觉的,但它有一个很好的理由。 假设您需要您的数字有两个小数点(例如,显示美元和美分)。 如果你对一个数字使用toPrecision(),它返回一个数字,如果你要对这个整数做更多的计算,它将只渲染这个整数,除非你也操纵小数点。 这种疯狂是有原因的。

接下来:。 我们的节目需要增加一些内容!

字符串

啊,古老的字符串数据类型。 它具有一些您所期望的基本属性,例如length属性和slice()split()方法,但有两个总是让我出错的是substr()substring():

"hello world".substr(3,5) // returns "lo wo"
"hello world".substring(3,5) //  returns "lo"

这两种方法的区别在于,第一个方法指定(start, length),第二个方法指定(start, end index)。 记住两者区别的一个简便方法是,.substring()的名称中有一个“i”,与 index(字符串中停止的位置)相关。

ES6 中新增的一个让我们的生活变得更简单的新功能是模板字面量。 看看这个日志:

const name = "Bob"
let age = 50
console.log("My name is " + name + " and I am " + age + " years old.")

会有用的,但有点笨重。 让我们使用模板文字:

console.log(`My name is ${name} and I am ${age} years old.`)

在这个例子中有两件重要的事情需要注意:

  • 该字符串以反引号开始和结束,而不是引号。
  • 要插入的变量被封装在${ }中。

模板文字很方便,但不是必需的。 当您在遇到问题时在线研究代码时,您肯定会看到老式的字符串连接方式的示例。 但是,请记住这是您的一个选择。

让我们来做个练习吧!

一个基本的计算器

有了布尔值、数字和字符串的知识,让我们构建一个基本的计算器。 从https://github.com/PacktPublishing/Hands-on-JavaScript-for-Python-Developers/tree/master/chapter-4/calculator/starter-code开始克隆存储库。

在大多数情况下,您可以放心地忽略 HTML 和 CSS,但通读 HTML 会有所帮助。 让我们看看 JavaScript:

window.onload = (() => {
  const buttons = document.getElementsByTagName('button')
  const output = document.getElementsByTagName('input')[0]
  let operation = null
  let expression = firstNumber = secondNumber = 0

  output.value = expression

  const clickHandler = ((event) => {
    let value = event.target.value

    /** Write your calculator logic here.
        Use conditionals and math to modify the output variable.

        Example of how to use the operators object:
          operators['='](1, 2) // returns 3

        Expected things to use:
          if/else
          switch() - https://developer.mozilla.org/en-
           US/docs/Web/JavaScript/Reference/Statements/switch
          parseFloat()
          String concatenation
          Assignment
    */

  })

  for (let i = 0; i < buttons.length; i++) {
    buttons[i].onclick = clickHandler
  }

  const operators = {
    '+': function(a, b) { return a + b },
    '-': function(a, b) { return a - b },
    '*': function(a, b) { return a * b },
    '/': function(a, b) { return a / b }
  };
})

这不是一项容易的锻炼初学者 JavaScript,所以不要害怕检查解决方案代码和逆向工程:https://github.com/PacktPublishing/Hands-on-JavaScript-for-Python-Developers/tree/master/chapter-4/calculator/solution-code[。](https://github.com/PacktPublishing/Hands-on-JavaScript-for-Python-Developers/tree/master/chapter-4/calculator/solution-code)

接下来,让我们探索数组和 ES6 的新功能集合

数组和集合

任何编程语言都有一些数组的概念,或者是s项的集合,它们都有一些共同的特性或用途。 JavaScript 有一些:数组集合。 这两种结构都包含项,而且在许多方面,它们的用法也相似,因为它们可以被枚举、迭代和显示,以达到逻辑构造的目的。

让我们先看看数组。

数组

数组可以包含不同的数据类型。 这是一个完全可行的数组:

const myArray = ['hello',1,'goodbye',null,true,1,'hello',{ 0 : 1 }]

它包含字符串、数字、布尔值、null和一个对象。 这是好的! 虽然在实践中您可能没有混合数据类型,但没有什么可以阻止您这样做。

在数组上使用typeof()有一个奇怪的地方:因为它们不是真正的原语,typeof(myArray)将返回object。 在编写 JavaScript 时,您应该记住这一点。

.push().pop()是两个最有用的数组方法,分别用于从数组中添加项和删除项。 不过,还有很多其他可行的方法。 让我们来看几个例子。

要创建一个数组,我们可以像前面的代码那样做,或者简单地使用const myArray = []。 现在,虽然我们可以修改数组中的值,但我们可以将它声明为const,因为在大多数情况下,我们不想让程序完全重新定义它。 我们仍然可以操作数组中的值; 我们只是不想破坏和重建它。 让我们继续前面例子中的数组:

myArray.push('goodbye') // myArray is now ['hello',1,'goodbye',null,true,1,'hello',{ 0 : 1 }, 'goodbye']
myArray[3] // equals null

记住数组是零索引的,所以我们的计数从0开始。

要从数组末尾移除一个元素,可以使用.pop(),如下所示:

let myValue = myArray.pop() // myValue = 'goodbye'

使用.shift()从数组的开头删除一个对象,如下所示:

myValue = myArray.shift() // myValue now equals 'hello'

请注意,到目前为止引入的所有这些方法都直接改变了原始数组。 .pop().shift()返回被删除的值,而不是数组本身。 这种区别很重要,因为并非所有数组方法都是这样的。 让我们来看看slicesplice:

myValue =  myArray.slice(0,1) // myValue equals 1, and myArray is unchanged
myValue = myArray.splice(0,1,'oh no') // myValue = 1, and myArray equals ['oh no', 'goodbye', null, true, 1, 'hello',{ 0 : 1 }]

你可以在MDN Web Docs网站上查找这两个方法的参数。 为了引入这些方法,请注意变量上的方法的行为可以从突变变为稳定。

集合与数组密切相关,但有一些细微的区别。 让我们来看看。

set 是 ES6 中引入的一种复合数据类型。 set 是一个删除了重复项的数组,它禁止添加重复项。 试试下面的代码:

const myArray = ['oh no', 'goodbye', null, true, 1, 'hello',{ 0 : 1 }]
myArray.push('goodbye')
console.log(myArray)

const mySet = new Set(myArray)
console.log(mySet)

mySet.add('goodbye')
console.log(mySet)

myArray的长度为 8,mySet的长度为 7——甚至在尝试添加'goodbye'之后,的长度也为 7。 JavaScript 的.add()集合方法将首先进行测试,以确保添加的是唯一的值。 注意关键字new和数据类型的大写; 这不是创建集合所特有的,但它很重要。 在 ES5 和之前,以这种方式声明新变量是常见的做法,但现在这种做法被认为是遗留的,除了一些实例。

There's a common introductory-level JavaScript question in interviews that asks you to deduplicate an array. You can use a set to do this in one fell swoop instead of iterating through the array and checking each value.

虽然有许多不使用 set 来重复数据删除数组的可能解决方案,但让我们来看一个使用.sort()方法的相当基本的示例。 从名称中可以看出,该方法将按升序对数组进行排序。 如果您知道数组将包含相同的字符串或数字数据类型,则最好使用这种方法。

考虑以下数组:

const myArray = ['oh no', 'goodbye', 'hello', 'hello', 'goodbye']

我们知道一个重复数据删除的排序数组应该如下所示:

['goodbye', 'hello', 'oh no']

我们可以如下测试:

const mySet = new Set(myArray.sort())

现在,让我们试着不使用集合。 下面是一种使用重复数据删除函数的方法:

const myArray = ['oh no', 'goodbye', 'hello', 'hello', 'goodbye']

function unique(a) {
 return a.sort().filter(function(item, pos, ary) {
   return !pos || item != ary[pos - 1]
 })
}

console.log(unique(myArray))

https://github.com/PacktPublishing/Hands-on-JavaScript-for-Python-Developers/blob/master/chapter-4/deduplicate/index.html

输出是什么? 我们应该得到一个长度为 3 的数组,如下所示:

["goodbye", "hello", "oh no"]

原始方法有点复杂,对吧? 集合是对数组进行重复数据删除的一种更加友好的方式。 对象是 JavaScript 中的另一种集合类型。 正如承诺的那样,下面我们将更深入地探讨它们。

对象和 JSON

对象! 对象是 JavaScript 的核心。 正如之前在第 3 章Nitty-Gritty Grammar中所提到的,JavaScript 中的几乎所有东西在其核心上都是一个对象。 一开始,物体可能令人生畏,但从理论上讲,它们很容易掌握:

这是一个物体的骨架:

const myObject = { key: value }

对象是键/值对的集合。 它们有很多用处,特别是在包含和组织数据时。 让我们来看一下第 3 章中的 Captain Picard:

const captain = {
  "name": "Jean-Luc Picard",
  "age": 62,
  "serialNumber": "SP 937-215",
  "command": "NCC 1701-D",
  "seniorStaff": ['Riker','Data','Worf', 'Troi']
}

正如我们看到的,我们可以使用点符号来访问对象的属性,像这样:

captain.command // equals "NCC 1701-D"

我们也可以使用其他数据类型作为值,如captain.seniorStaff

和其他东西一样,对象也有自己的方法。 其中最方便的是.hasOwnProperty():

console.log(captain.hasOwnProperty('command')) // logs true

现在,让我们再次尝试我们的数组重复数据删除,但这次,让我们利用对象来创建一个 hashmap:

const myArray = ['oh no', 'goodbye', 'hello', 'hello', 'goodbye']

function unique_fast(a) {
  const seen = {};
  const out = [];
  let len = a.length;
  let j = 0;
  for (let i = 0; i < len; i++) {
    const item = a[i];
    if (seen[item] !== 1) {
      seen[item] = 1;
      out[j++] = item;
    }
  }
  return out;
}

console.log(unique_fast(myArray))

https://github.com/PacktPublishing/Hands-on-JavaScript-for-Python-Developers/blob/master/chapter-4/deduplicate/hashmap.html 虽然现在还不是很明显,但这种方法的速度几乎是我们之前探索的重复数据删除方法的两倍。 为什么? 简而言之,一个对象的值可以在 O(1)时间内被立即访问,而不是在 O(n)时间内遍历整个数组。 如果你不熟悉大 O 符号,这是一种计算代码复杂度的模糊方法,这里有一个很好的入门教程:https://www.topcoder.com/blog/big-o-notation-primer/

让我们用长度为 24,975 的数组并排比较这两种方法。

第一个实现,https://github.com/PacktPublishing/Hands-on-JavaScript-for-Python-Developers/blob/master/chapter-4/deduplicate/large.html,将产生 5 到 8 毫秒之间的时间(您的里程数可能不同)。

然而,通过对对象使用 hashmap,我们可以至少减少几毫秒的运行时间:

现在,几毫秒可能看起来微不足道(而且不可能用眼睛分辨出来),但想想一个操作,需要在相同长度的数据集上反复运行。 省下的钱加起来了。

你可以看一下https://stackoverflow.com/a/9229821/2581282,了解更多关于这个问题的想法和解释。

接下来,我们将研究一些使 JavaScript… 好吧,JavaScript! 它的继承和类的概念与其他语言非常不同。 就让我们一探究竟吧。

原型继承

继承确实是 JavaScript 的主要优势之一。 JavaScript 使用了原型继承,而不是经典的基于类的继承。 (Protip:发音为pro-to-TYPE-al,而不是pro-to-TYPICAL。 )这是因为它使用对象的原型作为模板。 你还记得以前我们在控制台中处理字符串和数字的方法时,发现了一堆我们可以使用的方法,即使是简单的数据类型? 我们可以更进一步。

JavaScript 中原型继承概念的基础是原型链,它告诉我们可以访问哪些方法。 让我们看一个图表:

Figure 4.4 – The prototype chain

那么,这意味着什么呢? 考虑Alice:我们可以看到这个变量是一个字符串,因为它是从String原型派生出来的。 所以,转换成代码,我们可以这样说:

const Alice = new String()
Alice.name = "Alice"
console.log(Alice.name)

我们将在控制台得到什么? 简单Alice。 我们已经将name属性赋予了我们的Alice字符串对象。 现在,让我们看看原型中的这个神秘的sayHello()方法。 如果我们执行以下步骤,你认为会发生什么?

Alice.sayHello()

如果您猜测我们将在sayHello()函数上得到一个未定义的错误,那么您是正确的。 我们还没有定义它。

以下是我们如何修改String原型:

String.prototype.sayHello = function() {
 console.log(`My name is ${this.name}.`)
}
const Alice = new String()
Alice.name = "Alice"
Alice.sayHello()

现在,在我们的控制台,我们将得到My name is Alice。 好吧,发生了什么?

通过直接修改String原型并添加sayHello()方法,我们可以在任何字符串上使用该方法并访问其属性。 就像我们以前使用点表示法一样,我们可以使用this关键字来引用我们正在工作的对象的属性。 因此,this.name在我们的原型中工作,等于Alice.name

现在,你可能会想这似乎有点危险。 我们正在修改一个基础数据类型,如果我们试图在一个字符串上调用.sayHello(),而没有name属性,我们将得到一个巨大的错误。 你是正确的! 还有一种更好的方法,它仍然利用了原型继承的概念。 来看看这个:

function Person(name) {
  this.name = name

  this.sayHello = function() {
    console.log(`My name is ${this.name}.`)
  }
}

const Alice = new Person('Alice')
const Bob = new Person('Bob')

Alice.sayHello()
Bob.sayHello()

如我们所料,我们得到My name is Alice.My name is Bob.。 我们不需要定义sayHello()两次; AliceBobPerson继承了方法。 效率!

现在我们来谈谈杰森。 杰森谁? 不,不,我们接下来要研究的是名为JSON的基于对象的数据结构。

JSON

JSON(读作jay-sohnjason)代表JavaScript Object Notation。 如果您以前在这个领域见过它,那么您可能知道它经常被用作方便的 api 传输格式。 我们将稍微多讨论一些 api,但现在,让我们理解什么是 JSON 以及它为什么有用。

让我们来看看它是什么样的。 我们将使用星球大战 API(SWAPI)(https://swapi.dev)作为一个方便的只读 API。 https://swapi.dev/api/people/1/?format=json:

Figure 4.5 – SWAPI people instance

JSON 的一大优点是它非常清晰,因为它不像 XML 那样有很多节点和格式。 然而,在它的原始格式,如前面的截图,它仍然是一个混乱。 浏览器有很好的工具来将 JSON 解析成清晰的树。 花一分钟为您的浏览器找到并安装一个,然后访问前面的 API 调用。 现在,你的回复应该如下面的截图所示:

Figure 4.6 – SWAPI formatted

现在清晰多了。 跟卢克·天行者打个招呼吧!

这个 API 的作者做出的设计决策之一是在每个结果中只包含结果中资源的唯一数据。 例如,对于homeworld,它不拼出“塔图因”,而是提供了一个 URI**(U***niform 资源标识符【显示】)为地球资源。 我们可以看到,homeworld及其数据是键值对,就像其他对象一样,films是一个字符串数组,整个数据集是一个开始和结束都带花括号的对象。 这就是 JSON 的全部内容:正确格式化的 JavaScript 对象。***

***现在是时候深入了解一些关于互联网如何工作的信息,以指导我们使用 JavaScript、api 和更广泛的网络。

HTTP 动词

让我们快速看一下允许我们与 api 来回通信的 HTTP 动词:

| HTTP 动词 | CRUD 等效 | | 帖子 | 创建 | | 得到 | 读 | | 把 | 更新/替换 | | 补丁 | 更新/修改 | | 删除 | 删除 |

虽然 API 中使用的实际动词取决于 API 的设计,但这些都是目前许多 API 使用的标准 REST 术语。 REST代表REpresentationalStateTransfer,是对 api 格式的标准描述。 现在,REST 或 RESTful api 并不总是必须与 json 通信——REST 是不确定格式的。 让我们看看实际中的 API 调用。

前端的 API 调用——Ajax

Ajax(也拼写为 Ajax)代表异步 JavaScript 和 XML。 然而,现在您更可能使用 JSON 而不是 XML,所以这个名称有点误导人。 关于代码:看一下https://github.com/PacktPublishing/Hands-on-JavaScript-for-Python-Developers/blob/master/chapter-4/ajax/swapi.html。 在本地打开它,在你的开发工具中,你会看到一个 JSON 对象如下:

Figure 4.7 – SWAPI Ajax result

恭喜你! 您已经完成了第一个 Ajax 调用! 让我们分解以下代码:

fetch('https://swapi.co/api/people/1/')
  .then((response) => {
    return response.json()
  })
  .then((json) => {
    console.log(json)
  })

fetch是 ES6 中一个相当新的 API,它基本上取代了旧的、更复杂的XMLHttpRequestAjax 调用方式。 如您所见,语法相当简洁。 可能不太明显的是.then()函数所扮演的角色,甚至是它们是什么。

.then()是承诺的一个例子。 我们现在不会详细讨论 promise,但它的基本前提取决于 JavaScript 的异步部分。 本质上,Promise 说:“执行这段代码,我保证以后会提供更多数据。 不要在这里阻止代码执行。”

在浏览器中本地打开https://github.com/PacktPublishing/Hands-on-JavaScript-for-Python-Developers/blob/master/chapter-4/ajax/swapi-2.html。 你应该看到加载数据,然后显示 JSON。 你可以使用浏览器的开发工具来切断网络连接,看看这是怎么回事。

下面是 JavaScript 代码:

fetch('https://swapi.co/api/people/1/')
  .then((response) => {
    return response.json()
  })
  .then((json) => {
    document.querySelector('#main').innerHTML = JSON.stringify(json)
  })
document.querySelector('#headline').innerHTML = "Luke Skywalker"

不要太担心document.querySelector行——我们将在第 6 章文档对象模型(DOM)中详细介绍。 现在,只需理解它们是用来在 HTML 文档中放置信息的。 让我们使用开发工具降低到慢速 3G 或类似的速度。 当我们刷新时,我们会看到一闪而过的 waiting Headline,然后是 Luke Skywalker,接着是 Loading Data,然后是,然后是,几秒钟后,JSON 就变成了文本。

那么,这是如何工作的呢? 将 await Headline…更改为 Luke Skywalker 的代码行出现在 Ajax 调用之后。 那么,为什么数据部分的标题在之前更改了*? 答案是promise。*

使用fetch,我们确定我们天生使用异步数据,因此.then()语句告诉我们在 promise 语句解析后可以做什么。 它释放了程序以继续程序的其他部分。 事实上,我们可以在不同的时间进行多个取回调用,并且仍然不会阻止用户使用程序。 在使用现代 JavaScript 时,异步性是一个基本概念,所以请花些时间来理解它。

接下来,让我们获得一些使用 api 的实际的经验! 是时候真正动手了,不仅要与本地代码进行交互,还要与外部代码进行交互。

SWAPI lab

让我们对这个 API 进行一些实践。 我们将要做的是相当不优雅的暂时,但它将告诉我们如何使用异步行为为我们的优势。

你应该期望看到这样的东西:

Figure 4.8 – SWAPI Promises result

请记住,由于我们使用的是 promise,并且必须在films数组上进行迭代,所以电影的顺序可能会有所不同。 如果您愿意,您可以选择按影片号订购。

这个实验将需要嵌套的承诺和一些我们还没有涉及的语法,所以如果你想做这个实验,请给自己足够的时间来实验:

与任何实验室一样,请记住,解决方案代码不会与您的代码匹配,但意味着作为思维过程的资源。

总结

数据是每个程序的核心,你的 JavaScript 程序也不例外:

  • JavaScript 是松散类型的,这意味着如果需要,变量类型可以改变。
  • 布尔值是简单的真/假语句。
  • 数字在整数、浮点数或其他类型的数字之间是无差别的。
  • 数组和集合可以包含大量的数据,使组织数据更容易。
  • 对象是用于 O(1)检索的有效存储数据的键值对。
  • API 调用实际上并没有那么可怕!

我们仔细研究了数据类型、api 和 JSON。 我们发现,数据在 JavaScript 中是非常灵活的,包括操作对象本身的原型。 看看 JSON 和 API,我们已经成功地使用了fetch()来执行我们的第一个 API 调用。

在下一章中,我们将进一步研究如何编写 JavaScript 来创建一个更有趣的应用,并了解如何构造一个应用的细节!

问题

对于以下问题,请选择正确选项:

  1. JavaScript 本质上是:

    1. 同步
    2. 异步
    3. 这两个
  2. Afetch()调用返回 A:

    1. then
    2. next
    3. finally
    4. 承诺
  3. 使用原型继承,我们可以(选择全部):

    1. 向基本数据类型添加方法。
    2. 从基本数据类型中减去方法。
    3. 重命名数据类型。
    4. 将我们的数据转换成另一种格式。
let x = !!1
console.log(x)
  1. 在前面的代码中,预期的输出是什么?
    1. 1
    2. false
    3. 0
    4. true
const Officer = function(name, rank, posting) {
  this.name = name
  this.rank = rank
  this.posting = posting
  this.sayHello = () => {
    console.log(this.name)
  }
}

const Riker = new Officer("Will Riker", "Commander", "U.S.S. Enterprise")
  1. 在前面的代码中,输出Will Riker的最佳方式是什么?
    1. Riker.sayHello()
    2. console.log(Riker.name)
    3. console.log(Riker.this.name)
    4. Officer.Riker.name()

进一步的阅读

关于静态类型语言和动态类型语言的更多信息,可以参考https://android.jlelse.eu/magic-lies-here-statically-typed-vs-dynamically-typed-languages-d151c7f95e2b

如需了解更多匈牙利符号,请参考https://frontstuff.io/write-more-understandable-code-with-hungarian-notation。***