diff --git a/files/zh-cn/learn/javascript/asynchronous/index.md b/files/zh-cn/learn/javascript/asynchronous/index.md index 181c26514669fb..504bee2a07e74b 100644 --- a/files/zh-cn/learn/javascript/asynchronous/index.md +++ b/files/zh-cn/learn/javascript/asynchronous/index.md @@ -1,5 +1,5 @@ --- -title: 异步JavaScript +title: 异步 JavaScript slug: Learn/JavaScript/Asynchronous tags: - JavaScript @@ -30,7 +30,7 @@ original_slug: learn/JavaScript/异步 ## 预备知识 -异步 JavaScript 是一个相当高级的话题,建议你先完成 [JavaScript 第一步](/zh-CN/docs/Learn/JavaScript/First_steps)和[创建JavaScript代码块](/zh-CN/docs/Learn/JavaScript/Building_blocks) 两个模块的学习后再来学习。 +异步 JavaScript 是一个相当高级的话题,建议你先完成 [JavaScript 第一步](/zh-CN/docs/Learn/JavaScript/First_steps)和[创建 JavaScript 代码块](/zh-CN/docs/Learn/JavaScript/Building_blocks) 两个模块的学习后再来学习。 > **备注:** 如果你工作在一个无权创建自己文件的电脑/平板/其他设备上,你需要在一个在线编程工具上试验(大多数)代码示例,如 [JSBin](https://jsbin.com/) 或者 [Glitch](https://glitch.com). diff --git a/files/zh-cn/learn/javascript/asynchronous/introducing/index.md b/files/zh-cn/learn/javascript/asynchronous/introducing/index.md index 6f21025d8d54ed..d3b6c4d6548472 100644 --- a/files/zh-cn/learn/javascript/asynchronous/introducing/index.md +++ b/files/zh-cn/learn/javascript/asynchronous/introducing/index.md @@ -40,7 +40,7 @@ original_slug: learn/JavaScript/异步/简介 ## 同步编程 -观察下面的代码: +观察下面的代码: ```js const name = 'Miriam'; @@ -49,7 +49,7 @@ console.log(greeting); // "Hello, my name is Miriam!" ``` -这段代码: +这段代码: 1. 声明了一个叫做 `name` 的字符串常量 2. 声明了另一个叫做 `greeting` 的字符串常量(并使用了 `name` 常量的值) @@ -259,7 +259,7 @@ function doOperation() { doOperation(); ``` -现在我们有一个被分成三步的操作,每一步都依赖于上一步。在这个例子中,第一步给输入的数据加1,第二步加2,第三步加3。从输入0开始,最终结果是6(0+1+2+3)。作为同步代码,这很容易理解。但是如果我们用回调来实现这些步骤呢? +现在我们有一个被分成三步的操作,每一步都依赖于上一步。在这个例子中,第一步给输入的数据加 1,第二步加 2,第三步加 3。从输入 0 开始,最终结果是 6(0+1+2+3)。作为同步代码,这很容易理解。但是如果我们用回调来实现这些步骤呢? ```js function doStep1(init, callback) { diff --git a/files/zh-cn/learn/javascript/asynchronous/introducing_workers/index.md b/files/zh-cn/learn/javascript/asynchronous/introducing_workers/index.md index 65cf1b1c0bbc16..5a279573ac5b1a 100644 --- a/files/zh-cn/learn/javascript/asynchronous/introducing_workers/index.md +++ b/files/zh-cn/learn/javascript/asynchronous/introducing_workers/index.md @@ -143,7 +143,7 @@ textarea { // 在 "generate.js" 中创建一个新的 worker const worker = new Worker('./generate.js'); -// 当用户点击 "Generate primes" 时, 给 worker 发送一条消息。 +// 当用户点击 "Generate primes" 时,给 worker 发送一条消息。 // 消息中的 command 属性是 "generate", 还包含另外一个属性 "quota",即要生成的质数。 document.querySelector('#generate').addEventListener('click', () => { const quota = document.querySelector('#quota').value; @@ -232,7 +232,7 @@ worker 要做的第一件事情就是开始监听来自主脚本的消息。这 在本文中,我们介绍了 web workers,它使得 web 应用能够离线加载任务到单独的线程中。主线程和 worker 不直接共享任何变量,但是可以通过发送消息来进行通信,这些消息作为 `message` 事件被对方接受。 -Workers 尽管不能访问主应用程序能访问的所有 API,尤其是不能访问 DOM, 但是可以作为使主应用程序保持响应的一个有效的方式。 +Workers 尽管不能访问主应用程序能访问的所有 API,尤其是不能访问 DOM,但是可以作为使主应用程序保持响应的一个有效的方式。 ## 参见 diff --git a/files/zh-cn/learn/javascript/asynchronous/promises/index.html b/files/zh-cn/learn/javascript/asynchronous/promises/index.html index 345f0c20814987..14ce8c5706e1c2 100644 --- a/files/zh-cn/learn/javascript/asynchronous/promises/index.html +++ b/files/zh-cn/learn/javascript/asynchronous/promises/index.html @@ -8,24 +8,24 @@
Promise 是 JavaScript 语言的一个相对较新的功能,允许你推迟进一步的操作,直到上一个操作完成或响应其失败。这对于设置一系列异步操作以正常工作非常有用。本文向你展示了promises如何工作,如何在Web API中使用它们以及如何编写自己的API
+Promise 是 JavaScript 语言的一个相对较新的功能,允许你推迟进一步的操作,直到上一个操作完成或响应其失败。这对于设置一系列异步操作以正常工作非常有用。本文向你展示了 promises 如何工作,如何在 Web API 中使用它们以及如何编写自己的 API
前提条件: | -基本的计算机素养,具备基础的JavaScript知识 | +前提条件: | +基本的计算机素养,具备基础的 JavaScript 知识 |
---|---|---|---|
目标: | -理解并使用学习如何使用Promises | +目标: | +理解并使用学习如何使用 Promises |
我们在教程的第一篇文章中简要地了解了 Promises,接下来我们将在更深层次理解Promise。
+我们在教程的第一篇文章中简要地了解了 Promises,接下来我们将在更深层次理解 Promise。
本质上,Promise 是一个对象,代表操作的中间状态 —— 正如它的单词含义 '承诺' ,它保证在未来可能返回某种结果。虽然 Promise 并不保证操作在何时完成并返回结果,但是它保证当结果可用时,你的代码能正确处理结果,当结果不可用时,你的代码同样会被执行,来优雅的处理错误。
@@ -35,7 +35,7 @@该按钮的处理程序调用 {{domxref("MediaDevices.getUserMedia", "getUserMedia()")}} 来访问用户的摄像头和麦克风。由于 getUserMedia()
必须确保用户具有使用这些设备的权限,并询问用户要使用哪个麦克风和摄像头(或者是否仅进行语音通话,以及其他可能的选项),因此它会产生阻塞,直到用户做出所有的决定,并且摄像头和麦克风都已启用。此外,用户可能不会立即响应权限请求。所以 getUserMedia()
可能需要很长时间。
由于 getUserMedia()
是在浏览器的主线程进行调用,整个浏览器将会处于阻塞状态直到 getUserMedia()
返回,这是不应该发生的;不使用Promise,浏览器将处于不可用状态直到用户为摄像头和麦克风做出决定。因此 getUserMedia()
返回一个Promise对象,即 {{jsxref("promise")}},一旦 {{domxref("MediaStream")}} 流可用才去解析,而不是等待用户操作、启动选中的设备并直接返回从所选资源创建的 {{domxref("MediaStream")}} 流。
由于 getUserMedia()
是在浏览器的主线程进行调用,整个浏览器将会处于阻塞状态直到 getUserMedia()
返回,这是不应该发生的;不使用 Promise,浏览器将处于不可用状态直到用户为摄像头和麦克风做出决定。因此 getUserMedia()
返回一个 Promise 对象,即 {{jsxref("promise")}},一旦 {{domxref("MediaStream")}} 流可用才去解析,而不是等待用户操作、启动选中的设备并直接返回从所选资源创建的 {{domxref("MediaStream")}} 流。
上述视频聊天应用程序的代码可能像下面这样:
@@ -52,14 +52,14 @@这个函数在开头调用 setStatusMessage()
来更新状态显示信息"Calling...", 表示正在尝试通话。接下来调用 getUserMedia()
,请求具有视频及音频轨的流,一旦获得这个流,就将其显示在"selfViewElem"的video元素中。接下来将这个流的每个轨道添加到表示与另一个用户的连接的 WebRTC,参见{{domxref("RTCPeerConnection")}}。在这之后,状态显示为"Connected"。
这个函数在开头调用 setStatusMessage()
来更新状态显示信息"Calling...", 表示正在尝试通话。接下来调用 getUserMedia()
,请求具有视频及音频轨的流,一旦获得这个流,就将其显示在"selfViewElem"的 video 元素中。接下来将这个流的每个轨道添加到表示与另一个用户的连接的 WebRTC,参见{{domxref("RTCPeerConnection")}}。在这之后,状态显示为"Connected"。
如果getUserMedia()
失败,则catch块运行。这使用setStatusMessage()
更新状态框以指示发生错误。
如果getUserMedia()
失败,则 catch 块运行。这使用setStatusMessage()
更新状态框以指示发生错误。
这里重要的是getUserMedia()
调用几乎立即返回,即使尚未获得相机流。即使handleCallButton()
函数向调用它的代码返回结果,当getUserMedia()
完成工作时,它也会调用你提供的处理程序。只要应用程序不假设流式传输已经开始,它就可以继续运行。
注意: 如果你有兴趣,可以在文章Signaling and video calling中了解有关此高级主题的更多信息。在该示例中使用与此类似的代码,但更完整。
+注意: 如果你有兴趣,可以在文章Signaling and video calling中了解有关此高级主题的更多信息。在该示例中使用与此类似的代码,但更完整。
这很麻烦且难以阅读(通常称为“回调地狱”),需要多次调用failureCallback()
(每个嵌套函数一次),还有其他问题。
Promises使得上面的情况更容易编写,解析和运行。如果我们使用异步promises代表上面的伪代码,我们最终会得到这样的结果:
+Promises 使得上面的情况更容易编写,解析和运行。如果我们使用异步 promises 代表上面的伪代码,我们最终会得到这样的结果:
chooseToppings() .then(function(toppings) { @@ -102,7 +102,7 @@-使用promise改良
}) .catch(failureCallback);
这要好得多 - 更容易看到发生了什么,我们只需要一个.catch()
块来处理所有错误,它不会阻塞主线程(所以我们可以在等待时继续玩视频游戏为了准备好收集披萨),并保证每个操作在运行之前等待先前的操作完成。我们能够以这种方式一个接一个地链接多个异步操作,因为每个.then()
块返回一个新的promise,当.then()
块运行完毕时它会解析。聪明,对吗?
这要好得多 - 更容易看到发生了什么,我们只需要一个.catch()
块来处理所有错误,它不会阻塞主线程(所以我们可以在等待时继续玩视频游戏为了准备好收集披萨),并保证每个操作在运行之前等待先前的操作完成。我们能够以这种方式一个接一个地链接多个异步操作,因为每个.then()
块返回一个新的 promise,当.then()
块运行完毕时它会解析。聪明,对吗?
使用箭头函数,你可以进一步简化代码:
@@ -138,21 +138,21 @@注意: 你可以使用 async/await
语法进行进一步的改进,我们将在下一篇文章中深入讨论。
最基本的,promise与事件监听器类似,但有一些差异:
+最基本的,promise 与事件监听器类似,但有一些差异:
Promises 很重要,因为大多数现代Web API都将它们用于执行潜在冗长任务的函数。要使用现代Web技术,你需要使用promises。在本章的后面我们将看看如何编写自己的promises,但是现在我们将看一些你将在Web API中遇到的简单示例。
+Promises 很重要,因为大多数现代 Web API 都将它们用于执行潜在冗长任务的函数。要使用现代 Web 技术,你需要使用 promises。在本章的后面我们将看看如何编写自己的 promises,但是现在我们将看一些你将在 Web API 中遇到的简单示例。
-在第一个示例中,我们将使用fetch()
方法从Web获取图像,blob()
方法来转换获取响应的原始内容到 Blob 对象,然后在 <img> 元素内显示该blob
。这与我们在 first article of the series中看到的示例非常相似,但是会在构建你自己的基于 promise 的代码时有所不同。
在第一个示例中,我们将使用fetch()
方法从 Web 获取图像,blob()
方法来转换获取响应的原始内容到 Blob 对象,然后在 <img> 元素内显示该blob
。这与我们在 first article of the series中看到的示例非常相似,但是会在构建你自己的基于 promise 的代码时有所不同。
注意: 下列代码无法直接运行(i.e. via a file://
URL)。你需要本地测试服务器,或是 Glitch 和 GitHub pages 这样的在线解决方案。
注意:下列代码无法直接运行 (i.e. via a file://
URL)。你需要本地测试服务器,或是 Glitch 和 GitHub pages 这样的在线解决方案。
首先,下载我们的 simple HTML template和sample image file。
将 {{htmlelement("script")}} 元素添加在HTML {{htmlelement("body")}} 的底部。
+将 {{htmlelement("script")}} 元素添加在 HTML {{htmlelement("body")}} 的底部。
在 {{HTMLElement("script")}} 元素内,添加以下行:
let promise = fetch('coffee.jpg');-
这会调用 fetch()
方法,将图像的URL作为参数从网络中提取。这也可以将options对象作为可选的第二个参数,但我们现在只使用最简单的版本。我们将 fetch()
返回的promise对象存储在一个名为promise的变量中。正如我们之前所说的,这个对象代表了一个最初既不成功也不失败的中间状态 - 这个状态下的promise的官方术语叫作pending。
这会调用 fetch()
方法,将图像的 URL 作为参数从网络中提取。这也可以将 options 对象作为可选的第二个参数,但我们现在只使用最简单的版本。我们将 fetch()
返回的 promise 对象存储在一个名为 promise 的变量中。正如我们之前所说的,这个对象代表了一个最初既不成功也不失败的中间状态 - 这个状态下的 promise 的官方术语叫作pending。
then()
方法。 .then()
块中的回调(称为执行程序)仅在promise调用成功完成时运行并返回{{domxref("Response")}}对象 - 在promise-speak中,当它已被满足时。它将返回的{{domxref("Response")}}对象作为参数传递。then()
方法。 .then()
块中的回调(称为执行程序)仅在 promise 调用成功完成时运行并返回{{domxref("Response")}}对象 - 在 promise-speak 中,当它已被满足时。它将返回的{{domxref("Response")}}对象作为参数传递。注意: .then()
块的工作方式类似于使用AddEventListener()
向对象添加事件侦听器时的方式。它不会在事件发生之前运行(当promise履行时)。最显着的区别是.then()
每次使用时只运行一次,而事件监听器可以多次调用。
注意: .then()
块的工作方式类似于使用AddEventListener()
向对象添加事件侦听器时的方式。它不会在事件发生之前运行(当 promise 履行时)。最显着的区别是.then()
每次使用时只运行一次,而事件监听器可以多次调用。
我们立即对此响应运行blob()
方法以确保响应主体完全下载,并且当它可用时将其转换为我们可以执行某些操作的Blob
对象。返回的结果如下:
好的,我们还需要做点额外的工作。Fetch promises 不会产生 404 或 500错误,只有在产生像网路故障的情况时才会不工作。总的来说,Fetch promises 总是成功运行,即使response.ok 属性是 false
。为了产生404错误,我们需要判断 response.ok
,如果是 false
,抛出错误,否则返回 blob。就像下面的代码这样做。
好的,我们还需要做点额外的工作。Fetch promises 不会产生 404 或 500 错误,只有在产生像网路故障的情况时才会不工作。总的来说,Fetch promises 总是成功运行,即使response.ok 属性是 false
。为了产生 404 错误,我们需要判断 response.ok
,如果是 false
,抛出错误,否则返回 blob。就像下面的代码这样做。
let promise2 = promise.then(response => {
if (!response.ok) {
@@ -197,7 +197,7 @@ 解释promise的
}
});
-5. 每次调用.then()
都会创建一个新的promise。这非常有用;因为blob()
方法也返回一个promise,我们可以通过调用第二个promise的.then()
方法来处理它在履行时返回的Blob
对象。因为我们想要对blob
执行一些更复杂的操作,而不仅仅运行单个方法并返回结果,这次我们需要将函数体包装成花括号(否则会抛出错误)。
5. 每次调用.then()
都会创建一个新的 promise。这非常有用;因为blob()
方法也返回一个 promise,我们可以通过调用第二个 promise 的.then()
方法来处理它在履行时返回的Blob
对象。因为我们想要对blob
执行一些更复杂的操作,而不仅仅运行单个方法并返回结果,这次我们需要将函数体包装成花括号(否则会抛出错误)。
将以下内容添加到代码的末尾:
@@ -210,25 +210,25 @@这里我们运行{{domxref("URL.createObjectURL()")}}方法,将其作为Blob
在第二个promise实现时返回的参数传递。这将返回指向该对象的URL。然后我们创建一个{{htmlelement("img")}}元素,将其src
属性设置为等于对象URL并将其附加到DOM,这样图像就会显示在页面上!
这里我们运行{{domxref("URL.createObjectURL()")}}方法,将其作为Blob
在第二个 promise 实现时返回的参数传递。这将返回指向该对象的 URL。然后我们创建一个{{htmlelement("img")}}元素,将其src
属性设置为等于对象 URL 并将其附加到 DOM,这样图像就会显示在页面上!
如果你保存刚刚创建的HTML文件并将其加载到浏览器中,你将看到图像按预期显示在页面中。干得好!
+如果你保存刚刚创建的 HTML 文件并将其加载到浏览器中,你将看到图像按预期显示在页面中。干得好!
注意: 你可能会注意到这些例子有点做作。你可以取消整个fetch()
和blob()
链,只需创建一个<img>元素并将其src
属性值设置为图像文件的URL,即coffee.jpg
。然而,我们选择了这个例子,因为它以简单的方式展示了promise,而不是真实世界的适当性。
注意: 你可能会注意到这些例子有点做作。你可以取消整个fetch()
和blob()
链,只需创建一个<img>元素并将其src
属性值设置为图像文件的 URL,即coffee.jpg
。然而,我们选择了这个例子,因为它以简单的方式展示了 promise,而不是真实世界的适当性。
缺少一些东西 - 如果其中一个promise失败(rejects,in promise-speak),目前没有什么可以明确地处理错误。我们可以通过运行前一个promise的 .catch()
方法来添加错误处理。立即添加:
缺少一些东西 - 如果其中一个 promise 失败(rejects,in promise-speak),目前没有什么可以明确地处理错误。我们可以通过运行前一个 promise 的 .catch()
方法来添加错误处理。立即添加:
let errorCase = promise3.catch(e => {
console.log('There has been a problem with your fetch operation: ' + e.message);
});
-要查看此操作,请尝试拼错图像的URL并重新加载页面。该错误将在浏览器的开发人员工具的控制台中报告。
+要查看此操作,请尝试拼错图像的 URL 并重新加载页面。该错误将在浏览器的开发人员工具的控制台中报告。
-如果你根本不操心包括的 .catch()
块,这并没有做太多的事情,但考虑一下(指.catch()块) ––这会使我们可以完全控制错误处理方式。在真实的应用程序中,你的.catch()
块可以重试获取图像,或显示默认图像,或提示用户提供不同的图像URL等等。
如果你根本不操心包括的 .catch()
块,这并没有做太多的事情,但考虑一下(指.catch() 块) ––这会使我们可以完全控制错误处理方式。在真实的应用程序中,你的.catch()
块可以重试获取图像,或显示默认图像,或提示用户提供不同的图像 URL 等等。
注意: 你可以参考 our version of the example live (参阅 source code ).
@@ -236,7 +236,7 @@这是写出来的一种非常简便的方式;我们故意这样做是为了帮助你清楚地了解发生了什么。如本文前面所示,你可以将.then()
块(以及.catch()
块)链接在一起。上面的代码也可以这样写(参阅GitHub上的simple-fetch-chained.html ):
这是写出来的一种非常简便的方式;我们故意这样做是为了帮助你清楚地了解发生了什么。如本文前面所示,你可以将.then()
块(以及.catch()
块)链接在一起。上面的代码也可以这样写 (参阅 GitHub 上的simple-fetch-chained.html ):
fetch('coffee.jpg')
.then(response => {
@@ -256,31 +256,31 @@ 将代码块链在一起
console.log('There has been a problem with your fetch operation: ' + e.message);
});
-请记住,履行的promise所返回的值将成为传递给下一个 .then()
块的executor函数的参数。
请记住,履行的 promise 所返回的值将成为传递给下一个 .then()
块的 executor 函数的参数。
注意: promise中的.then()/catch()
块基本上是同步代码中try...catch
块的异步等价物。请记住,同步try ... catch
在异步代码中不起作用。
注意: promise 中的.then()/catch()
块基本上是同步代码中try...catch
块的异步等价物。请记住,同步try ... catch
在异步代码中不起作用。
在上面的部分中有很多要介绍的内容,所以让我们快速回过头来给你一个简短的指南,你可以将它添加到书签中,以便将来更新你的记忆。你还应该再次阅读上述部分,以确保这些概念坚持下去。
.then()
块链接到promise链的末尾来访问该值。 .then()
块中的执行程序函数将包含promise的返回值。.catch()
块链接到promise链的末尾来访问此原因。.then()
块链接到 promise 链的末尾来访问该值。 .then()
块中的执行程序函数将包含 promise 的返回值。.catch()
块链接到 promise 链的末尾来访问此原因。上面的例子向我们展示了使用promises的一些真正的基础知识。现在让我们看一些更高级的功能。首先,链接进程一个接一个地发生都很好,但是如果你想在一大堆Promises全部完成之后运行一些代码呢?
+上面的例子向我们展示了使用 promises 的一些真正的基础知识。现在让我们看一些更高级的功能。首先,链接进程一个接一个地发生都很好,但是如果你想在一大堆 Promises 全部完成之后运行一些代码呢?
-你可以使用巧妙命名的Promise.all()静态方法完成此操作。这将一个promises数组作为输入参数,并返回一个新的Promise对象,只有当数组中的所有promise都满足时才会满足。它看起来像这样:
+你可以使用巧妙命名的Promise.all()静态方法完成此操作。这将一个 promises 数组作为输入参数,并返回一个新的 Promise 对象,只有当数组中的所有 promise 都满足时才会满足。它看起来像这样:
Promise.all([a, b, c]).then(values => { ... @@ -288,7 +288,7 @@运行代码以响应多
如果它们都实现,那么数组中的结果将作为参数传递给
-.then()
块中的执行器函数。如果传递给Promise.all()
的任何一个 promise 拒绝,整个块将拒绝。这非常有用。想象一下,我们正在获取信息以在内容上动态填充页面上的UI功能。在许多情况下,接收所有数据然后才显示完整内容,而不是显示部分信息。
+这非常有用。想象一下,我们正在获取信息以在内容上动态填充页面上的 UI 功能。在许多情况下,接收所有数据然后才显示完整内容,而不是显示部分信息。
让我们构建另一个示例来展示这一点。
@@ -297,10 +297,10 @@运行代码以响应多
下载我们页面模板(page template)的新副本,并再次在结束</ body>标记之前放置一个<script>元素。
下载我们的源文件(coffee.jpg, tea.jpg和 description.txt),或者随意替换成你自己的文件。
+下载我们的源文件 (coffee.jpg, tea.jpg和 description.txt),或者随意替换成你自己的文件。
在我们的脚本中,我们将首先定义一个函数,该函数返回我们要发送给Promise.all()
的promise。如果我们只想运行Promise.all()
块以响应三个fetch()
操作完成,这将很容易。我们可以这样做:
在我们的脚本中,我们将首先定义一个函数,该函数返回我们要发送给Promise.all()
的 promise。如果我们只想运行Promise.all()
块以响应三个fetch()
操作完成,这将很容易。我们可以这样做:
let a = fetch(url1); let b = fetch(url2); @@ -310,7 +310,7 @@-运行代码以响应多 ... });
当promise是fullfilled时,传递到履行处理程序的values
将包含三个Response对象,每个对象用于已完成的每个fetch()
操作。
当 promise 是fullfilled时,传递到履行处理程序的values
将包含三个 Response 对象,每个对象用于已完成的每个fetch()
操作。
但是,我们不想这样做。我们的代码不关心fetch()
操作何时完成。相反,我们想要的是加载的数据。这意味着当我们返回代表图像的可用blob
和可用的文本字符串时,我们想要运行Promise.all()
块。我们可以编写一个执行此操作的函数;在<script>
元素中添加以下内容:
这看起来有点复杂,所以让我们一步一步地完成它:
fetch()
函数来获取指定URL处的资源,然后将其链接到另一个 promise ,它解码(或“read”)响应body。这是前一个示例中的blob()
方法。fetch()
函数来获取指定 URL 处的资源,然后将其链接到另一个 promise,它解码(或“read”)响应 body。这是前一个示例中的blob()
方法。if ... else if
语句,根据我们需要解码的文件类型返回不同的promise(在这种情况下,我们可以选择blob
或text
,而且很容易扩展这个以处理其他类型)。fetch()
调用之前添加了return
关键字。它的作用是运行整个链,然后运行最终结果(即blob()
或text()
返回的promise作为我们刚刚定义的函数的返回值)。实际上,return
语句将结果从链返回到顶部。if ... else if
语句,根据我们需要解码的文件类型返回不同的 promise(在这种情况下,我们可以选择blob
或text
,而且很容易扩展这个以处理其他类型)。fetch()
调用之前添加了return
关键字。它的作用是运行整个链,然后运行最终结果(即blob()
或text()
返回的 promise 作为我们刚刚定义的函数的返回值)。实际上,return
语句将结果从链返回到顶部。在块结束时,我们链接一个.catch()
调用,以处理任何可能出现在数组中传递给.all()
的任何promise的错误情况。如果任何promise被拒绝,catch
块将告诉你哪个promise有问题。 .all()
块(见下文)仍然可以实现,但不会显示有问题的资源。如果你想要.all
拒绝,你必须将.catch()
块链接到那里的末尾。
在块结束时,我们链接一个.catch()
调用,以处理任何可能出现在数组中传递给.all()
的任何 promise 的错误情况。如果任何 promise 被拒绝,catch
块将告诉你哪个 promise 有问题。 .all()
块(见下文)仍然可以实现,但不会显示有问题的资源。如果你想要.all
拒绝,你必须将.catch()
块链接到那里的末尾。
函数体内部的代码是async(异步)和基于promise的,因此实际上整个函数就像一个promise ––方便啊!
+函数体内部的代码是 async(异步)和基于 promise 的,因此实际上整个函数就像一个 promise ––方便啊!
接下来,我们调用我们的函数三次以开始获取和解码图像和文本的过程,并将每个返回的promises存储在变量中。在以前的代码下面添加以下内容:
+接下来,我们调用我们的函数三次以开始获取和解码图像和文本的过程,并将每个返回的 promises 存储在变量中。在以前的代码下面添加以下内容:
let coffee = fetchAndDecode('coffee.jpg', 'blob'); let tea = fetchAndDecode('tea.jpg', 'blob'); let description = fetchAndDecode('description.txt', 'text');
接下来,我们将定义一个Promise.all()
块,仅当上面存储的所有三个promise都已成功完成时才运行一些代码。首先,在.then()
调用中添加一个带有空执行程序的块,如下所示:
接下来,我们将定义一个Promise.all()
块,仅当上面存储的所有三个 promise 都已成功完成时才运行一些代码。首先,在.then()
调用中添加一个带有空执行程序的块,如下所示:
Promise.all([coffee, tea, description]).then(values => { });-
你可以看到它需要一个包含promises作为参数的数组。执行者只有在所有三个promises的状态成为resolved时才会运行;当发生这种情况时,它将被传入一个数组,其中包含来自各个promise(即解码的响应主体)的结果,类似于 [coffee-results, tea-results, description-results].
+你可以看到它需要一个包含 promises 作为参数的数组。执行者只有在所有三个 promises 的状态成为resolved时才会运行;当发生这种情况时,它将被传入一个数组,其中包含来自各个 promise(即解码的响应主体)的结果,类似于 [coffee-results, tea-results, description-results].
最后,在执行程序中添加以下内容。这里我们使用一些相当简单的同步代码将结果存储在单独的变量中(从blob创建对象URL),然后在页面上显示图像和文本。
+最后,在执行程序中添加以下内容。这里我们使用一些相当简单的同步代码将结果存储在单独的变量中(从 blob 创建对象 URL),然后在页面上显示图像和文本。
console.log(values); // Store each value returned from the promises in separate variables; create object URLs from the blobs @@ -384,7 +384,7 @@运行代码以响应多 document.body.appendChild(para);
保存并刷新,你应该看到所有UI组件都已加载,尽管不是特别有吸引力!
+保存并刷新,你应该看到所有 UI 组件都已加载,尽管不是特别有吸引力!
注意: 如果你正在改进这段代码,你可能想要遍历一个项目列表来显示,获取和解码每个项目,然后循环遍历Promise.all()
内部的结果,运行一个不同的函数来显示每个项目取决于什么代码的类型是。这将使它适用于任何数量的项目,而不仅仅是三个。
此外,你可以确定要获取的文件类型,而无需显式类型属性。例如,你可以使用response.headers.get("content-type")
检查响应的{{HTTPHeader("Content-Type")}} HTTP标头,然后做出相应的反应。
此外,你可以确定要获取的文件类型,而无需显式类型属性。例如,你可以使用response.headers.get("content-type")
检查响应的{{HTTPHeader("Content-Type")}} HTTP 标头,然后做出相应的反应。
在promise完成后,你可能希望运行最后一段代码,无论它是否已实现(fullfilled)或被拒绝(rejected)。此前,你必须在.then()
和.catch()
回调中包含相同的代码,例如:
在 promise 完成后,你可能希望运行最后一段代码,无论它是否已实现(fullfilled)或被拒绝(rejected)。此前,你必须在.then()
和.catch()
回调中包含相同的代码,例如:
myPromise .then(response => { @@ -414,7 +414,7 @@-在promise fullf runFinalCode(); });
在现代浏览器中,.finally()
方法可用,它可以链接到常规promise链的末尾,允许你减少代码重复并更优雅地执行操作。上面的代码现在可以写成如下:
在现代浏览器中,.finally()
方法可用,它可以链接到常规 promise 链的末尾,允许你减少代码重复并更优雅地执行操作。上面的代码现在可以写成如下:
myPromise .then(response => { @@ -452,20 +452,20 @@在promise fullf
这会将一条简单的消息记录到控制台,告诉我们每次获取尝试的时间。
--注意:finally()允许你在异步代码中编写异步等价物try/ catch / finally。
+注意:finally() 允许你在异步代码中编写异步等价物 try/ catch / finally。
构建自定义promise
+构建自定义 promise
-好消息是,在某种程度上,你已经建立了自己的promise。当你使用
+.then()
块链接多个promise时,或者将它们组合起来创建自定义函数时,你已经在创建自己的基于异步声明的自定义函数。例如,从前面的示例中获取我们的fetchAndDecode()
函数。好消息是,在某种程度上,你已经建立了自己的 promise。当你使用
-.then()
块链接多个 promise 时,或者将它们组合起来创建自定义函数时,你已经在创建自己的基于异步声明的自定义函数。例如,从前面的示例中获取我们的fetchAndDecode()
函数。将不同的基于promise的API组合在一起以创建自定义函数是迄今为止你使用promises进行自定义事务的最常见方式,并展示了基于相同原则的大多数现代API的灵活性和强大功能。然而,还有另一种方式。
+将不同的基于 promise 的 API 组合在一起以创建自定义函数是迄今为止你使用 promises 进行自定义事务的最常见方式,并展示了基于相同原则的大多数现代 API 的灵活性和强大功能。然而,还有另一种方式。
-使用Promise()构造函数
+使用 Promise() 构造函数
-可以使用
+Promise()
构造函数构建自己的promise。当你需要使用现有的旧项目代码、库或框架以及基于现代promise的代码时,这会派上用场。比如,当你遇到没有使用promise的旧式异步API的代码时,你可以用promise来重构这段异步代码。可以使用
-Promise()
构造函数构建自己的 promise。当你需要使用现有的旧项目代码、库或框架以及基于现代 promise 的代码时,这会派上用场。比如,当你遇到没有使用 promise 的旧式异步 API 的代码时,你可以用 promise 来重构这段异步代码。让我们看一个简单的示例来帮助你入门 —— 这里我们用 promise 包装一了个
+setTimeout(),
它会在两秒后运行一个函数,该函数将用字符串“Success!”,解析当前promise(调用链接的resolve()
)。让我们看一个简单的示例来帮助你入门 —— 这里我们用 promise 包装一了个
setTimeout(),
它会在两秒后运行一个函数,该函数将用字符串“Success!”,解析当前 promise(调用链接的resolve()
)。let timeoutPromise = new Promise((resolve, reject) => { setTimeout(function(){ @@ -473,9 +473,9 @@-使用Promise()构造函数
}, 2000); });+
resolve()
和reject()
是用来实现和拒绝新创建的promise的函数。此处,promise 成功运行通过显示字符串“Success!”。-
resolve()
和reject()
是用来实现和拒绝新创建的 promise 的函数。此处,promise 成功运行通过显示字符串“Success!”。因此,当你调用此promise时,可以将
+.then()
块链接到它的末尾,它将传递给.then()
块一串“Success!”。在下面的代码中,我们显示出该消息:因此,当你调用此 promise 时,可以将
.then()
块链接到它的末尾,它将传递给.then()
块一串“Success!”。在下面的代码中,我们显示出该消息:timeoutPromise .then((message) => { @@ -489,15 +489,15 @@-使用Promise()构造函数
尝试 running this live 以查看结果 (可参考 source code).
-上面的例子不是很灵活 - promise只能实现一个字符串,并且它没有指定任何类型的
+reject()
条件(诚然,setTimeout()
实际上没有失败条件,所以对这个简单的例子并不重要)。上面的例子不是很灵活 - promise 只能实现一个字符串,并且它没有指定任何类型的
reject()
条件(诚然,setTimeout()
实际上没有失败条件,所以对这个简单的例子并不重要)。-注意: 为什么要
resolve()
,而不是fullfill()
?我们现在给你的答案有些复杂。拒绝一个自定义promise
+拒绝一个自定义 promise
-我们可以创建一个
+reject()
方法拒绝promise - 就像resolve()
一样,这需要一个值,但在这种情况下,它是拒绝的原因,即将传递给.catch()
的错误块。我们可以创建一个
reject()
方法拒绝 promise - 就像resolve()
一样,这需要一个值,但在这种情况下,它是拒绝的原因,即将传递给.catch()
的错误块。让我们扩展前面的例子,使其具有一些
@@ -517,17 +517,17 @@reject()
条件,并允许在成功时传递不同的消息。拒绝一个自定义promise
}); };在这里,我们将两个方法传递给一个自定义函数 - 一个用来做某事的消息,以及在做这件事之前要经过的时间间隔。在函数内部,我们返回一个新的
+Promise
对象 - 调用该函数将返回我们想要使用的promise。在这里,我们将两个方法传递给一个自定义函数 - 一个用来做某事的消息,以及在做这件事之前要经过的时间间隔。在函数内部,我们返回一个新的
-Promise
对象 - 调用该函数将返回我们想要使用的 promise。在
+Promise
构造函数中,我们在if ... else结构中进行了一些检查:在
Promise
构造函数中,我们在 if ... else 结构中进行了一些检查:-
-- 首先,我们检查消息是否适合被警告。如果它是一个空字符串或根本不是字符串,我们会使用合适的错误消息拒绝该promise。
-- 接下来,我们检查间隔是否是适当的间隔值。如果是负数或不是数字,我们会使用合适的错误消息拒绝promise。
-- 最后,如果参数看起来都正常,我们使用
+setTimeout()
在指定的时间间隔过后,使用指定的消息解析promise。- 首先,我们检查消息是否适合被警告。如果它是一个空字符串或根本不是字符串,我们会使用合适的错误消息拒绝该 promise。
+- 接下来,我们检查间隔是否是适当的间隔值。如果是负数或不是数字,我们会使用合适的错误消息拒绝 promise。
+- 最后,如果参数看起来都正常,我们使用
setTimeout()
在指定的时间间隔过后,使用指定的消息解析 promise。由于
+timeoutPromise()
函数返回一个Promise
,我们可以将.then()
,.catch()
等链接到它上面以利用它的功能。现在让我们使用它 - 将以前的timeoutPromise用法替换为以下值:由于
timeoutPromise()
函数返回一个Promise
,我们可以将.then()
,.catch()
等链接到它上面以利用它的功能。现在让我们使用它 - 将以前的 timeoutPromise 用法替换为以下值:timeoutPromise('Hello there!', 1000) .then(message => { @@ -537,17 +537,17 @@-拒绝一个自定义promise
console.log('Error: ' + e); });当你按原样保存并运行代码时,一秒钟后你将收到消息提醒。现在尝试将消息设置为空字符串或将间隔设置为负数,例如,你将能够通过相应的错误消息查看被拒绝的promise!你还可以尝试使用已解决的消息执行其他操作,而不仅仅是提醒它。
+当你按原样保存并运行代码时,一秒钟后你将收到消息提醒。现在尝试将消息设置为空字符串或将间隔设置为负数,例如,你将能够通过相应的错误消息查看被拒绝的 promise!你还可以尝试使用已解决的消息执行其他操作,而不仅仅是提醒它。
-注意: 你可以在GitHub上找到我们的这个示例版本custom-promise2.html(另请参阅source code)。
+注意: 你可以在 GitHub 上找到我们的这个示例版本custom-promise2.html(另请参阅source code)。
一个更真实的例子
-上面的例子是故意做得简单,以使概念易于理解,但它并不是实际上完全异步。异步性质基本上是使用
+setTimeout()
伪造的,尽管它仍然表明promises对于创建具有合理的操作流程,良好的错误处理等的自定义函数很有用上面的例子是故意做得简单,以使概念易于理解,但它并不是实际上完全异步。异步性质基本上是使用
-setTimeout()
伪造的,尽管它仍然表明 promises 对于创建具有合理的操作流程,良好的错误处理等的自定义函数很有用我们想邀请你学习的一个例子是Jake Archibald's idb library,它真正地显示了
+Promise()
构造函数的有用异步应用程序。这采用了 IndexedDB API,它是一种旧式的基于回调的API,用于在客户端存储和检索数据,并允许你将其与promises一起使用。如果你查看main library file,你将看到我们在上面讨论过的相同类型的技术。以下块将许多IndexedDB方法使用的基本请求模型转换为使用promise:我们想邀请你学习的一个例子是Jake Archibald's idb library,它真正地显示了
Promise()
构造函数的有用异步应用程序。这采用了 IndexedDB API,它是一种旧式的基于回调的 API,用于在客户端存储和检索数据,并允许你将其与 promises 一起使用。如果你查看main library file,你将看到我们在上面讨论过的相同类型的技术。以下块将许多 IndexedDB 方法使用的基本请求模型转换为使用 promise:function promisifyRequest(request) { return new Promise(function(resolve, reject) { @@ -565,18 +565,18 @@一个更真实的例子
request
的success
event触发时,onsuccess
处理程序将使用请求的result
实现(fullfill)promise。request
的error
event触发时,onerror
处理程序拒绝带有请求error
的promiserequest
的error
event触发时,onerror
处理程序拒绝带有请求error
的 promise当我们不知道函数的返回值或返回需要多长时间时,Promises是构建异步应用程序的好方法。它们使得在没有深度嵌套回调的情况下更容易表达和推理异步操作序列,并且它们支持类似于同步try ... catch
语句的错误处理方式。
当我们不知道函数的返回值或返回需要多长时间时,Promises 是构建异步应用程序的好方法。它们使得在没有深度嵌套回调的情况下更容易表达和推理异步操作序列,并且它们支持类似于同步try ... catch
语句的错误处理方式。
Promise适用于所有现代浏览器的最新版本;promise有兼容问题的唯一情况是Opera Mini和IE11及更早版本。
+Promise 适用于所有现代浏览器的最新版本;promise 有兼容问题的唯一情况是 Opera Mini 和 IE11 及更早版本。
-本文中,我们没有涉及的所有promise的功能,只是最有趣和最有用的功能。当你开始了解有关promise的更多信息时,你会遇到更多功能和技巧。
+本文中,我们没有涉及的所有 promise 的功能,只是最有趣和最有用的功能。当你开始了解有关 promise 的更多信息时,你会遇到更多功能和技巧。
-大多数现代Web API都是基于promise的,因此你需要了解promise才能充分利用它们。这些API包括WebRTC,Web Audio API,Media Capture and Streams等等。随着时间的推移,Promises将变得越来越重要,因此学习使用和理解它们是学习现代JavaScript的重要一步。
+大多数现代 Web API 都是基于 promise 的,因此你需要了解 promise 才能充分利用它们。这些 API 包括WebRTC,Web Audio API,Media Capture and Streams等等。随着时间的推移,Promises 将变得越来越重要,因此学习使用和理解它们是学习现代 JavaScript 的重要一步。
参见
@@ -592,9 +592,9 @@我们将构建的传统函数将被命名为 displayMessage()
,它向用户展示一个传统的消息盒子于web页面的顶部。它充当浏览器内建的 alert() 函数更有用的替代品。你已经看过了这个,但是我们回复一下我们的记忆——在你的浏览器的 JavaScript控制台中,在任意一个页面里尝试以下代码
我们将构建的传统函数将被命名为 displayMessage()
,它向用户展示一个传统的消息盒子于 web 页面的顶部。它充当浏览器内建的 alert() 函数更有用的替代品。你已经看过了这个,但是我们回复一下我们的记忆——在你的浏览器的 JavaScript 控制台中,在任意一个页面里尝试以下代码
alert('This is a message');@@ -39,7 +39,7 @@
这个alert()
函数不是很好的:您可以alert()
出这条信息,但是您不能很容易的表达其他内容,例如颜色,图标或者是其他东西。接下来我们将会构建一个更有趣的函数。
笔记: 这个例子能够在现代浏览器上很好的工作,但是这个风格在老的浏览器上并没那么有趣。我们建议你实现这个例子时在现代浏览器上,例如Firefox,Opera或者Chrome浏览器。
+笔记: 这个例子能够在现代浏览器上很好的工作,但是这个风格在老的浏览器上并没那么有趣。我们建议你实现这个例子时在现代浏览器上,例如 Firefox,Opera 或者 Chrome 浏览器。
首先,让我们来组织一个基本的函数。
注:对于函数命名约定,应遵循与变量命名约定相同的规则。 这很好,尽你所能理解它们之间的区别 - 函数名称后带有括号,而变量则没有。
+注:对于函数命名约定,应遵循与变量命名约定相同的规则。这很好,尽你所能理解它们之间的区别 - 函数名称后带有括号,而变量则没有。
<script>
元素中:
function displayMessage() { @@ -80,21 +80,21 @@基本函数
天哪,这么多代码!好吧,一行一行的解释给你听。
-第一行代码使用了一个DOM(文档对象模型)的内置方法 {{domxref("document.querySelector()")}} 来选择{{htmlelement("html")}} 元素并且把它存放在一个叫
+html
的常量中, 这样方便我们接下来使用这个元素:第一行代码使用了一个 DOM(文档对象模型)的内置方法 {{domxref("document.querySelector()")}} 来选择{{htmlelement("html")}} 元素并且把它存放在一个叫
html
的常量中,这样方便我们接下来使用这个元素:const html = document.querySelector('html');-下段代码使用了另一个名字叫做 {{domxref("Document.createElement()")}} 的DOM方法,用来创建 {{htmlelement("div")}} 元素并且把该新建元素的引用(实际上是新建对象的地址)放在一个叫做
+panel
的常量中。 这个元素将成为我们的消息框的外部容器。下段代码使用了另一个名字叫做 {{domxref("Document.createElement()")}} 的 DOM 方法,用来创建 {{htmlelement("div")}} 元素并且把该新建元素的引用(实际上是新建对象的地址)放在一个叫做
-panel
的常量中。 这个元素将成为我们的消息框的外部容器。然后我们又使用了一个叫做 {{domxref("Element.setAttribute()")}} 的DOM方法给panel元素添加了一个值为
+msgBox
的class
类属性。 这样做方便我们来给这个元素添加样式 — 查看CSS代码你就知道我们使用.msgBox
类选择器来给消息框和消息内容设置样式。然后我们又使用了一个叫做 {{domxref("Element.setAttribute()")}} 的 DOM 方法给 panel 元素添加了一个值为
-msgBox
的class
类属性。 这样做方便我们来给这个元素添加样式 — 查看 CSS 代码你就知道我们使用.msgBox
类选择器来给消息框和消息内容设置样式。最后,我们还使用了一个叫做 {{domxref("Node.appendChild()")}} 的DOM方法,给
+html
常量(我们之前定义好的)追加了我们设置好样式的panel元素 。该方法追加了元素的同时也把panel<div>
元素指定为<html>
的子元素 。这样做是因为我们创建了一个元素之后这个元素并不会莫名其妙的出现在我们的页面上(浏览器只知道我们创建了一个元素,但是不知道把这个元素怎么呈现出来) — 因此,我们给这个元素了一个定位,就是显示在html里面!最后,我们还使用了一个叫做 {{domxref("Node.appendChild()")}} 的 DOM 方法,给
html
常量(我们之前定义好的)追加了我们设置好样式的 panel 元素 。该方法追加了元素的同时也把 panel<div>
元素指定为<html>
的子元素 。这样做是因为我们创建了一个元素之后这个元素并不会莫名其妙的出现在我们的页面上(浏览器只知道我们创建了一个元素,但是不知道把这个元素怎么呈现出来) — 因此,我们给这个元素了一个定位,就是显示在 html 里面!const panel = document.createElement('div'); panel.setAttribute('class', 'msgBox'); html.appendChild(panel);-下面这两段使用了我们之前使用过的方法
+createElement()
和appendChild()
— 创建了一个 {{htmlelement("p")}} 元素和一个{{htmlelement("button")}}元素 — 并且把他们追加到了panel<div>
之下。我们使用元素的 {{domxref("Node.textContent")}}(Node泛指一个元素并不是说是某个元素是叫Node) 属性— 表示一个元素的文本属性 — 给一个p元素赋值, 同样按钮也有这个属性,该属性就是按钮显示的‘X’。这个按钮的功能就是关闭消息提示框。下面这两段使用了我们之前使用过的方法
createElement()
和appendChild()
— 创建了一个 {{htmlelement("p")}} 元素和一个{{htmlelement("button")}}元素 — 并且把他们追加到了 panel<div>
之下。我们使用元素的 {{domxref("Node.textContent")}}(Node 泛指一个元素并不是说是某个元素是叫 Node)属性— 表示一个元素的文本属性 — 给一个 p 元素赋值,同样按钮也有这个属性,该属性就是按钮显示的‘X’。这个按钮的功能就是关闭消息提示框。const msg = document.createElement('p'); msg.textContent = 'This is a message box'; @@ -104,45 +104,45 @@-基本函数
closeBtn.textContent = 'x'; panel.appendChild(closeBtn);最后我们使用一个叫做 {{domxref("GlobalEventHandlers.onclick")}} 的事件句柄给按钮添加了一个点击事件, 点击事件后定义了一个匿名函数,功能是将消息提示框从父容器中删除 — 达到了关闭的效果。
+最后我们使用一个叫做 {{domxref("GlobalEventHandlers.onclick")}} 的事件句柄给按钮添加了一个点击事件,点击事件后定义了一个匿名函数,功能是将消息提示框从父容器中删除 — 达到了关闭的效果。
-简单来说,这个
+onclick
句柄是一个按钮的属性 (事实上,页面上的任何元素) 当按钮被点击的时候能够执行一些代码。 你可以在之后的介绍事件的章节了解详情。我们给onclick
句柄绑定了一个匿名函数, 函数中代码在元素被点击的时候运行。函数里面的这行代码使用了 {{domxref("Node.removeChild()")}} DOM 方法指定了我们想要移除的HTML的子元素 — 在这里指panel<div>
.简单来说,这个
-onclick
句柄是一个按钮的属性 (事实上,页面上的任何元素) 当按钮被点击的时候能够执行一些代码。 你可以在之后的介绍事件的章节了解详情。我们给onclick
句柄绑定了一个匿名函数,函数中代码在元素被点击的时候运行。函数里面的这行代码使用了 {{domxref("Node.removeChild()")}} DOM 方法指定了我们想要移除的 HTML 的子元素 — 在这里指 panel<div>
.PS:我来解释下是什么意思,panel是消息框,panel.parentNode就是指panel的上一级,就是整个DOM,然后再来用这个父亲来干掉这个儿子,儿子不能自己干掉自己,所以要这么做。
+PS:我来解释下是什么意思,panel 是消息框,panel.parentNode 就是指 panel 的上一级,就是整个 DOM,然后再来用这个父亲来干掉这个儿子,儿子不能自己干掉自己,所以要这么做。
closeBtn.onclick = function() { panel.parentNode.removeChild(panel); }-大体上, 这一整块的代码我就不解释了就是一个div,一个段落,一个按钮, 把这个加在页面上:
+大体上,这一整块的代码我就不解释了就是一个 div,一个段落,一个按钮,把这个加在页面上:
<div class="msgBox"> <p>This is a message box</p> <button>x</button> </div>-啊,看完了这么多代码,是不是很累? — 不用担心,你现在没有必要完全知道这些代码的细节! 这里我们只关心函数的结构和使用方式, 下面的例子将展示一些有意思的东西。
+啊,看完了这么多代码,是不是很累? — 不用担心,你现在没有必要完全知道这些代码的细节!这里我们只关心函数的结构和使用方式, 下面的例子将展示一些有意思的东西。
调用函数
-相信你已经迫不及待的在你的
+<script>
标签中写好了一个函数, 但仅仅是定义而已,这玩意不会做任何事情。相信你已经迫不及待的在你的
<script>
标签中写好了一个函数,但仅仅是定义而已,这玩意不会做任何事情。-
- 把下面这行代码加在写好的函数下面来调用函数(当然,不一定要放在函数下面来调用,在C语言中确实是还要先定义后使用,但是我们现在用的是JavaScript,这玩意很强大,不管你是先定义后调用还是先调用后定义都行,但是别忘了定义): +
- 把下面这行代码加在写好的函数下面来调用函数(当然,不一定要放在函数下面来调用,在 C 语言中确实是还要先定义后使用,但是我们现在用的是 JavaScript,这玩意很强大,不管你是先定义后调用还是先调用后定义都行,但是别忘了定义):
+ 这行代码调用了你写的函数,当浏览器解析到这行代码时会立即执行函数内的代码。当你保存好你的代码以后在浏览器中刷新,你会马上看到一个小小的提示框弹出来,但是只弹出了一次。毕竟我们只调用了一次函数是不?displayMessage();- 这行代码调用了你写的函数, 当浏览器解析到这行代码时会立即执行函数内的代码。当你保存好你的代码以后在浏览器中刷新, 你会马上看到一个小小的提示框弹出来, 但是只弹出了一次。毕竟我们只调用了一次函数是不?
现在打开浏览器开发工具, 找到JavaScript控制台把上面这一句再输入一遍然后回车, 你会看到又弹出了一次!有点意思... — 现在我们有了一个能够重复调用的函数,只要你高兴可以随时调用它。
+现在打开浏览器开发工具,找到 JavaScript 控制台把上面这一句再输入一遍然后回车,你会看到又弹出了一次!有点意思... — 现在我们有了一个能够重复调用的函数,只要你高兴可以随时调用它。
-但是,这玩意有什么用呢?在真实的应用当中这样的消息提示框一般用来提示一些什么新的东西, 或者是出现了一个什么错误, 或者当用户删除配置文件的时候("你确定要这样做?"), 或者用户添加一个新的联系人之后提示操作成功..等等。 在这个例子里面, 当用户点击这个按钮的时候这个提示框会出现。
+但是,这玩意有什么用呢?在真实的应用当中这样的消息提示框一般用来提示一些什么新的东西,或者是出现了一个什么错误,或者当用户删除配置文件的时候 ("你确定要这样做?"), 或者用户添加一个新的联系人之后提示操作成功..等等。在这个例子里面,当用户点击这个按钮的时候这个提示框会出现。
const btn = document.querySelector('button');
btn.onclick = displayMessage;-
跟关闭按钮类似closeBtn.onclick...
, 当按钮被点击的时候我们运行了点代码。 但不同的是, 之前等号的右边是一个匿名函数,看起来是这样的:btn.onclick = function(){...}
, 我们现在是直接使用函数名称来调用。跟关闭按钮类似closeBtn.onclick...
, 当按钮被点击的时候我们运行了点代码。 但不同的是,之前等号的右边是一个匿名函数,看起来是这样的:btn.onclick = function(){...}
, 我们现在是直接使用函数名称来调用。
btn.onclick = displayMessage();-
保存刷新, 你会发现按钮都还没点击提示框就出来了! 在函数名后面的这个括号叫做“函数调用运算符”(function invocation operator)。你只有在想直接调用函数的地方才这么写。 同样要重视的是, 匿名函数里面的代码也不是直接运行的, 只要代码在函数作用域内。
+保存刷新,你会发现按钮都还没点击提示框就出来了! 在函数名后面的这个括号叫做“函数调用运算符”(function invocation operator)。你只有在想直接调用函数的地方才这么写。 同样要重视的是,匿名函数里面的代码也不是直接运行的,只要代码在函数作用域内。
-如果你做了这个函数括号的实验, 在继续之前把代码恢复到之前的状态。
+如果你做了这个函数括号的实验,在继续之前把代码恢复到之前的状态。
就现在看来,我们的函数还不是特别有用 — 我们想要的不仅仅是每点击一次展示一个默认的消息。我们来改造下我们的函数,给它添加几个参数, 允许我们以不同的方式调用这个函数。
+就现在看来,我们的函数还不是特别有用 — 我们想要的不仅仅是每点击一次展示一个默认的消息。我们来改造下我们的函数,给它添加几个参数,允许我们以不同的方式调用这个函数。
function displayMessage(msgText, msgType) {当我们调用函数的时候,我们可以在括号里添加两个变量,来指定显示在消息框里面的消息,和消息的类型。
msg.textContent = 'This is a message box';-
改成这样:
+改成这样:
msg.textContent = msgText;
btn.onclick = displayMessage;-
改成这样:
+改成这样:
btn.onclick = function() { displayMessage('Woo, this is a different message!'); };如果我们要在点击事件里面绑定这个新函数,我们不能直接使用(
btn.onclick = displayMessage('Woo, this is a different message!');
)前面已经讲过— 我们要把它放在一个匿名函数里面,不然函数会直接调用,而不是按钮点击之后才会调用,这不是我们想要的结果。刚才我们只使用了我们定义的第一个参数msgText
,对于第二个参数msgType
,这个就涉及了稍微多一点的东西— 我们要设置一些依赖于这个 msgType
参数的东西, 我们的函数将会显示不同的图标和不同的背景颜色。
刚才我们只使用了我们定义的第一个参数msgText
,对于第二个参数msgType
,这个就涉及了稍微多一点的东西— 我们要设置一些依赖于这个 msgType
参数的东西,我们的函数将会显示不同的图标和不同的背景颜色。
icons
的文件夹下,和你的HTML文件在同一个目录下。
+ icons
的文件夹下,和你的 HTML 文件在同一个目录下。
- .msgBox
的宽度:
+ .msgBox
的宽度:
width: 200px;改成:
width: 242px;
.msgBox p { ... }
里面添加几条新规则:
+ .msgBox p { ... }
里面添加几条新规则:
padding-left: 82px; background-position: 25px center; background-repeat: no-repeat;
displayMessage()
让它能够显示图标. 在你的函数结束符之前}
添加下面这几行代码:
+ displayMessage()
让它能够显示图标。在你的函数结束符之前}
添加下面这几行代码:
if (msgType === 'warning') { msg.style.backgroundImage = 'url(icons/warning.png)'; panel.style.backgroundColor = 'red'; @@ -215,11 +215,11 @@- 来解释下, 如果第二个参数一个更加复杂的参数
} else { msg.style.paddingLeft = '20px'; }
msgType
的值为 'warning'
, 我们的消息框将显示一个警告图标和一个红色的背景. 如果这个参数的值是 'chat'
, 将显示聊天图标和水蓝色的背景. 如果 msgType
没有指定任何值 (或者不是'warning'
和'chat'
), 然后这个 else { ... }
代码块将会被执行, 代码的意思是给消息段落设置了一个简单的左内边距并且没有图标, 也没有背景颜色。这么做是为了当没有提供 msgType
参数的时候给函数一个默认行为, 意思是这是一个可选参数(你没发现?其实我们已经用过了!就在这里btn.onclick = function() { displayMessage('Woo, this is a different message!'); };
只是当时我们没有写这个else
段,也就是啥操作也没做)!displayMessage()
像这样:
+ 来解释下,如果第二个参数 msgType
的值为 'warning'
, 我们的消息框将显示一个警告图标和一个红色的背景。如果这个参数的值是 'chat'
, 将显示聊天图标和水蓝色的背景。如果 msgType
没有指定任何值 (或者不是'warning'
和'chat'
), 然后这个 else { ... }
代码块将会被执行,代码的意思是给消息段落设置了一个简单的左内边距并且没有图标,也没有背景颜色。这么做是为了当没有提供 msgType
参数的时候给函数一个默认行为,意思是这是一个可选参数(你没发现?其实我们已经用过了!就在这里btn.onclick = function() { displayMessage('Woo, this is a different message!'); };
只是当时我们没有写这个else
段,也就是啥操作也没做)!displayMessage()
像这样:
displayMessage('Woo, this is a different message!');-
或者这样:
+或者这样:
displayMessage('Your inbox is almost full — delete some mails', 'warning'); displayMessage('Brian: Hi there, how are you today?','chat');@@ -227,7 +227,7 @@
注意: 如果你写这个例子遇到了困难, 在这里查看免费的代码 完整版本的代码 (或者在线运行的完整代码), 也可以向我们寻求帮助。
+注意: 如果你写这个例子遇到了困难,在这里查看免费的代码 完整版本的代码 (或者在线运行的完整代码), 也可以向我们寻求帮助。
恭喜你,终于到了这里(等你好久了)! 这篇文章介绍了如何写一个自定义函数, 要把这个新技能在真实项目中使用上你可能还要花点功夫。 下一篇文章中我们将会介绍函数的另一个相关概念 — 返回值。
+恭喜你,终于到了这里(等你好久了)! 这篇文章介绍了如何写一个自定义函数,要把这个新技能在真实项目中使用上你可能还要花点功夫。 下一篇文章中我们将会介绍函数的另一个相关概念 — 返回值。
在任何的编程语言中,代码需要依靠不同的输入作出决定并且采取行动。例如,在游戏中,如果玩家的生命值变成了0,那么游戏就结束了。在天气应用中,如果在早晨运行,就显示一张日出的图片;如果在晚上,就显示星星和月亮的图片。在这篇文章中,我们将探索在JavaScript中所谓的条件语句是怎样工作的。
+在任何的编程语言中,代码需要依靠不同的输入作出决定并且采取行动。例如,在游戏中,如果玩家的生命值变成了 0,那么游戏就结束了。在天气应用中,如果在早晨运行,就显示一张日出的图片;如果在晚上,就显示星星和月亮的图片。在这篇文章中,我们将探索在 JavaScript 中所谓的条件语句是怎样工作的。
预备知识: | -基本的计算机知识,对HTML和CSS有基本的了解,JavaScript的第一步。 | +基本的计算机知识,对 HTML 和 CSS 有基本的了解,JavaScript 的第一步。 |
---|---|---|
目标: | -了解怎样在JavaScript中使用条件语句的结构。 | +了解怎样在 JavaScript 中使用条件语句的结构。 |
人类(以及其他的动物)无时无刻不在做决定,这些决定都影响着他们的生活,从小事(“我应该吃一片还是两片饼干”)到重要的大事(“我应该留在我的祖国,在我父亲的农场工作;还是应该去美国学习天体物理学”)。
-条件语句结构允许我们来描述在JavaScript中这样的选择,从不得不作出的选择(例如:“一片还是两片”)到产生的结果或这些选择(也许是“吃一片饼干”可能会“仍然感觉饿”,或者是“吃两片饼干”可能会“感觉饱了,但妈妈会因为我吃掉了所有的饼干而骂我”。)
+条件语句结构允许我们来描述在 JavaScript 中这样的选择,从不得不作出的选择(例如:“一片还是两片”)到产生的结果或这些选择(也许是“吃一片饼干”可能会“仍然感觉饿”,或者是“吃两片饼干”可能会“感觉饱了,但妈妈会因为我吃掉了所有的饼干而骂我”。)
@@ -36,7 +36,7 @@基本的if…else语法看起来像下面的 {{glossary("伪代码")}}:
+基本的 if…else 语法看起来像下面的 {{glossary("伪代码")}}:
if (condition) { code to run if condition is true @@ -48,15 +48,15 @@基本的的 if…else 语法
-
- 关键字 if,并且后面跟随括号。
-- 要测试的条件,放到括号里(通常是“这个值大于另一个值吗”或者“这个值存在吗”)。这个条件会利用比较运算符(我们会在最后的模块中讨论)进行比较,并且返回true或者false。
-- 一组花括号,在里面我们有一些代码——可以是任何我们喜欢的代码,并且只会在条件语句返回true的时候运行。
-- 关键字else。
-- 另一组花括号,在里面我们有一些代码——可以是任何我们喜欢的代码,并且当条件语句返回值不是true的话,它才会运行。
+- 要测试的条件,放到括号里(通常是“这个值大于另一个值吗”或者“这个值存在吗”)。这个条件会利用比较运算符(我们会在最后的模块中讨论)进行比较,并且返回 true 或者 false。
+- 一组花括号,在里面我们有一些代码——可以是任何我们喜欢的代码,并且只会在条件语句返回 true 的时候运行。
+- 关键字 else。
+- 另一组花括号,在里面我们有一些代码——可以是任何我们喜欢的代码,并且当条件语句返回值不是 true 的话,它才会运行。
这段代码真的非常易懂——它说“如果(if)条件(condition)返回true,运行代码A,否则(else)运行代码B”
+这段代码真的非常易懂——它说“如果(if)条件(condition)返回 true,运行代码 A,否则(else)运行代码 B”
-注意:你不一定需要else和第二个花括号——下面的代码也是符合语法规则的:
+注意:你不一定需要 else 和第二个花括号——下面的代码也是符合语法规则的:
if (condition) { code to run if condition is true @@ -64,7 +64,7 @@-基本的的 if…else 语法
run some other code不过,这里你需要注意——在这种情况下,第二段代码不被条件语句控制,所以它总会运行,不管条件返回的是true还是false。这不一定是一件坏事,但这可能不是你想要的——你经常只想要运行一段代码或者另一段,而不是两个都运行。
+不过,这里你需要注意——在这种情况下,第二段代码不被条件语句控制,所以它总会运行,不管条件返回的是 true 还是 false。这不一定是一件坏事,但这可能不是你想要的——你经常只想要运行一段代码或者另一段,而不是两个都运行。
最后,有时候你可能会看到 if…else 语句没有写花括号,像下面的速记风格:
@@ -75,7 +75,7 @@基本的的 if…else 语法
一个真实的例子
-为了更好的理解这种语法,让我们考虑一个真实的例子。想像一个孩子被他的父母要求帮助他们做家务。父母可能会说“嗨,宝贝儿,如果你帮我去购物,我会给你额外的零花钱,这样你就能买得起你想要的玩具了。”在JavaScript中,我们可以这样表示:
+为了更好的理解这种语法,让我们考虑一个真实的例子。想像一个孩子被他的父母要求帮助他们做家务。父母可能会说“嗨,宝贝儿,如果你帮我去购物,我会给你额外的零花钱,这样你就能买得起你想要的玩具了。”在 JavaScript 中,我们可以这样表示:
var shoppingDone = false; @@ -88,7 +88,7 @@一个真实的例子
这段代码显示的结果是变量
shoppingDone
总是返回false
, 意味着对我们的穷孩子来说很失望。如果孩子去购物的话,就需要依靠我们提供机制来使父母把变量shoppingDone
变成true
。-Note: 你可以看到在Github上这个例子的完整版本(也可以在线运行)
+Note: 你可以看到在Github 上这个例子的完整版本(也可以在线运行)
else if
@@ -135,9 +135,9 @@else if
- 这里我们有 HTML {{htmlelement("select")}} 元素让我们选择不同的天气,以及一个简单的段落。
-- 在 JavaScript 中, 我们同时存储了对 {{htmlelement("select")}} 和 {{htmlelement("p")}} 的引用, 并对
+<select>
添加了一个事件监听器,因此,当它的值改变时,setWeather()
函数被执行。- 在 JavaScript 中,我们同时存储了对 {{htmlelement("select")}} 和 {{htmlelement("p")}} 的引用,并对
<select>
添加了一个事件监听器,因此,当它的值改变时,setWeather()
函数被执行。- 当函数运行时,我们首先新建了一个
-choice
变量去存储当前被选的<select>
中的值。接着我们用条件判断语句根据choice
的值选择性的展示段落中的文本。注意else if() {...}
段中的条件是怎么被判断的,除了第一个,它是在if() {...}中被判断的。
- 最后一个
+else {...}
中的选择通常被叫做 “最后招数” — 在所有的条件都不为 true 时其中的代码会被执行。在这个例子中,如果用户没有选择任何一个选项,它会将段落中的文本清空,例如当用户决定重新选择最开始出现的"--Make a choice--"选项时,就会有这样的效果。- 最后一个
else {...}
中的选择通常被叫做“最后招数” — 在所有的条件都不为 true 时其中的代码会被执行。在这个例子中,如果用户没有选择任何一个选项,它会将段落中的文本清空,例如当用户决定重新选择最开始出现的"--Make a choice--"选项时,就会有这样的效果。@@ -158,7 +158,7 @@-关于比较运算符
Note: 如果你想复习这些内容,可以回顾之前链接上的材料。
我们想特别提到测试布尔值(true / false),和一个通用模式,你会频繁遇到它,任何不是
+false
,undefined
,null
,0
,NaN
的值,或一个空字符串('')在作为条件语句进行测试时实际返回true,因此您可以简单地使用变量名称来测试它是否为真,甚至是否存在(即它不是未定义的)。例如:我们想特别提到测试布尔值(true / false),和一个通用模式,你会频繁遇到它,任何不是
false
,undefined
,null
,0
,NaN
的值,或一个空字符串('')在作为条件语句进行测试时实际返回 true,因此您可以简单地使用变量名称来测试它是否为真,甚至是否存在(即它不是未定义的)。例如:var cheese = 'Cheddar'; @@ -178,9 +178,9 @@-关于比较运算符
var childsAllowance = 5; }嵌套if ... else
+嵌套 if ... else
-将另一个if ... else 语句放在另一个中 - 嵌套它是完全可行的。例如,我们可以更新我们的天气预报应用程序,以显示更多的选择,具体取决于温度:
+将另一个 if ... else 语句放在另一个中 - 嵌套它是完全可行的。例如,我们可以更新我们的天气预报应用程序,以显示更多的选择,具体取决于温度:
if (choice === 'sunny') { if (temperature < 86) { @@ -190,19 +190,19 @@-嵌套if ... else
} }即使代码全部一起工作,每个if ... else语句完全独立于另一个。
+即使代码全部一起工作,每个 if ... else 语句完全独立于另一个。
逻辑运算符:&& , || 和 !
-如果要测试多个条件,而不需要编写嵌套if ... else语句,逻辑运算符可以帮助您。当在条件下使用时,前两个执行以下操作:
+如果要测试多个条件,而不需要编写嵌套 if ... else 语句,逻辑运算符可以帮助您。当在条件下使用时,前两个执行以下操作:
&&
— 逻辑与; 使得并列两个或者更多的表达式成为可能,只有当这些表达式每一个都返回true
时,整个表达式才会返回true.
||
— 逻辑或; 当两个或者更多表达式当中的任何一个返回 true
则整个表达式将会返回 true
.举一个逻辑 && 的例子, 刚才的那段代码片段可以写成下面这样:
+举一个逻辑 && 的例子,刚才的那段代码片段可以写成下面这样:
if (choice === 'sunny' && temperature < 86) { para.textContent = 'It is ' + temperature + ' degrees outside — nice and sunny. Let\'s go out to the beach, or the park, and get an ice cream.'; @@ -220,7 +220,7 @@逻辑运算符:&& , || 和 !
-最后一种类型的逻辑运算符, 逻辑非
+!
运算符表示, 可以用于对一个表达式取否. 让我们把 非运算符 结合上一个例子里的 或表达式 看看:最后一种类型的逻辑运算符, 逻辑非
!
运算符表示,可以用于对一个表达式取否。让我们把 非运算符 结合上一个例子里的 或表达式 看看:if (!(iceCreamVanOutside || houseStatus === 'on fire')) { console.log('Probably should just stay in then.'); @@ -230,29 +230,29 @@逻辑运算符:&& , || 和 !
在这一段代码中,如果逻辑或所在的语句返回true
,则非运算符会将其取否,于是整个表达式的返回值将会是false
。 -您可以在任何结构中随意合并很多个逻辑表达式。接下来的例子将会只在或运算符两边的语句同时返回true时才会执行代码,这也就意味着整个与运算符语句将会返回true:
+您可以在任何结构中随意合并很多个逻辑表达式。接下来的例子将会只在或运算符两边的语句同时返回 true 时才会执行代码,这也就意味着整个与运算符语句将会返回 true:
if ((x === 5 || y > 3 || z <= 10) && (loggedIn || userName === 'Steve')) { // run the code }-在条件语句中运用或逻辑运算符最常见的错误是尝试声明变量后,仅检查该变量一次的情况下赋予很多个都会返回true的值,不同的值之间用
+||
(或)运算符分隔。比如:在条件语句中运用或逻辑运算符最常见的错误是尝试声明变量后,仅检查该变量一次的情况下赋予很多个都会返回 true 的值,不同的值之间用
||
(或) 运算符分隔。比如:if (x === 5 || 7 || 10 || 20) { // run my code }-在这个例子里
+if(...)
里的条件总为真,因为 7 (或者其它非零的数) 的值总是为真. 这个条件实际意思是 "如果x等于5, 或者7为真 — 它总是成立的". 这不是我们想要的逻辑,为了 让它正常工作你必须指定每个或表达式两边都是完整的检查:在这个例子里
if(...)
里的条件总为真,因为 7 (或者其它非零的数) 的值总是为真。这个条件实际意思是 "如果 x 等于 5, 或者 7 为真 — 它总是成立的". 这不是我们想要的逻辑,为了 让它正常工作你必须指定每个或表达式两边都是完整的检查:if (x === 5 || x === 7 || x === 10 ||x === 20) { // run my code }-switch语句
+switch 语句
-+
if...else
语句能够很好地实现条件代码,但是它们不是没有缺点。 它们主要适用于您只有几个选择的情况,每个都需要相当数量的代码来运行,和/或 的条件很复杂的情况(例如多个逻辑运算符)。 对于只想将变量设置一系列为特定值的选项或根据条件打印特定语句的情况,语法可能会很麻烦,特别是如果您有大量选择。-
if...else
语句能够很好地实现条件代码,但是它们不是没有缺点。它们主要适用于您只有几个选择的情况,每个都需要相当数量的代码来运行,和/或 的条件很复杂的情况(例如多个逻辑运算符)。对于只想将变量设置一系列为特定值的选项或根据条件打印特定语句的情况,语法可能会很麻烦,特别是如果您有大量选择。+
switch
语句在这里是您的朋友 - 他们以单个表达式/值作为输入,然后查看多个选项,直到找到与该值相匹配的选项,执行与之相关的代码。 这里有一些伪代码,可以给你一点灵感:
switch
语句在这里是您的朋友 - 他们以单个表达式/值作为输入,然后查看多个选项,直到找到与该值相匹配的选项,执行与之相关的代码。这里有一些伪代码,可以给你一点灵感:switch (expression) { case choice1: @@ -269,25 +269,25 @@-switch语句
actually, just run this code }这里我们得到:
+这里我们得到:
-
- 关键字
-switch
, 后跟一组括号.- 括号内的表达式或值.
+- 关键字
+switch
, 后跟一组括号。- 括号内的表达式或值。
- 关键字
-case
, 后跟一个选项的表达式/值,后面跟一个冒号.- 如果选择与表达式匹配,则运行一些代码.
-- 一个
-break
语句, 分号结尾. 如果先前的选择与表达式/值匹配,则浏览器在此停止执行代码块,并执行switch语句之后的代码.- 你可以添加任意的 case 选项(选项3-5).
-- 关键字
+default
, 后面跟随和case
完全相同的代码模式 (选项 3–5), except thatdefault
之后不需要再有选项, 并且您不需要break
语句, 因为之后没有任何运行代码. 如果之前没有选项匹配,则运行default
选项.- 如果选择与表达式匹配,则运行一些代码。
+- 一个
+break
语句,分号结尾。如果先前的选择与表达式/值匹配,则浏览器在此停止执行代码块,并执行switch语句之后的代码.- 你可以添加任意的 case 选项(选项 3-5).
+- 关键字
default
, 后面跟随和case
完全相同的代码模式 (选项 3–5), except thatdefault
之后不需要再有选项, 并且您不需要break
语句, 因为之后没有任何运行代码. 如果之前没有选项匹配,则运行default
选项。--Note:
+default
部分不是必须的 - 如果表达式不可能存在未知值,则可以安全地省略它。 如果有机会,您需要包括它来处理未知的情况。Note:
default
部分不是必须的 - 如果表达式不可能存在未知值,则可以安全地省略它。如果有机会,您需要包括它来处理未知的情况。switch语句示例
+switch 语句示例
-我们来看一个真实的例子 - 我们将重写天气预报应用程序,以改用switch语句:
+我们来看一个真实的例子 - 我们将重写天气预报应用程序,以改用 switch 语句:
<label for="weather">Select the weather type today: </label> <select id="weather"> @@ -394,7 +394,7 @@主动学习:一个简单的日
我们需要你在
onchange
处理函数中写一个条件语句,就在// ADD CONDITIONAL HERE
任务的下面 。这应该:-
@@ -516,7 +516,7 @@- 查看所选月份(存储在
+choice
变量中,这将是<select>
值更改后的元素值,例如“1月”)。- 查看所选月份(存储在
choice
变量中,这将是<select>
值更改后的元素值,例如“1 月”)。- 设置一个被调用
days
为等于所选月份天数的变量。为此,您必须查看一年中每个月的天数。为了这个例子的目的,你可以忽略闰年。Playable code
主动学习:更多颜色选择!
-在这个例子中,您将要采取我们前面看到的三元运算符示例,并将三元运算符转换为一个switch语句,这将允许我们对简单的网站应用更多的选择。看看
+<select>
- 这次你会看到它不是两个主题选项,而是五个。您需要在// ADD SWITCH STATEMENT
注释下面添加一个switch语句:在这个例子中,您将要采取我们前面看到的三元运算符示例,并将三元运算符转换为一个 switch 语句,这将允许我们对简单的网站应用更多的选择。看看
<select>
- 这次你会看到它不是两个主题选项,而是五个。您需要在// ADD SWITCH STATEMENT
注释下面添加一个 switch 语句:
choice
变量作为其输入表达式。这就是现在您真正需要了解的JavaScript中的条件结构!我相信你会理解这些概念,并轻松地通过这些例子; 如果有什么不明白的,请随时阅读文章,或者联系我们寻求帮助。
+这就是现在您真正需要了解的 JavaScript 中的条件结构!我相信你会理解这些概念,并轻松地通过这些例子; 如果有什么不明白的,请随时阅读文章,或者联系我们寻求帮助。
前提: | -基本电脑知识, 对HTML和CSS的基本了解,及 JavaScript first steps. | +前提: | +基本电脑知识,对 HTML 和 CSS 的基本了解,及 JavaScript first steps. | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
目标: | +目标: | 了解事件的基本理论,它们怎么在浏览器上运行的,以及在不同的编程环境下事件有何不同。 |
前提条件: | -基本的电脑知识,对HTML与CSS有基本的了解,及已阅读: JavaScript first steps(JS的入门)。 | +前提条件: | +基本的电脑知识,对 HTML 与 CSS 有基本的了解,及已阅读: JavaScript first steps(JS 的入门)。 |
---|---|---|---|
目标: | +目标: | 了解 Javascript 函数背后的基本概念。 |
在 JavaScript中, 你将发现函数无处不在 。事实上, 到目前为止,我们一直在使用函数,只是我们还没很好的讨论它们。然而现在是时候了,让我们开始聊聊函数,并探索它们的语法。
+在 JavaScript 中,你将发现函数无处不在。事实上,到目前为止,我们一直在使用函数,只是我们还没很好的讨论它们。然而现在是时候了,让我们开始聊聊函数,并探索它们的语法。
-几乎任何时候,只要你使用一个带有一对圆括号()的JavaScript结构,并且你不是在使用一个常见的比如for for循环,while或do…while循环,或者if语句这样的内置语言结构时,那么您就正在使用函数。
+几乎任何时候,只要你使用一个带有一对圆括号()的 JavaScript 结构,并且你不是在使用一个常见的比如 for for 循环,while 或 do…while 循环,或者 if 语句这样的内置语言结构时,那么您就正在使用函数。
@@ -74,13 +74,13 @@提示:如果需要,你可以随意将这些代码输入浏览器控制台以便于你熟悉其功能。
-JavaScript有许多内置的函数,可以让您做很多有用的事情,而无需自己编写所有的代码。事实上, 许多你调用(运行或者执行的专业词语)浏览器内置函数时调用的代码并不是使用JavaScript来编写——大多数调用浏览器后台的函数的代码,是使用像C++这样更低级的系统语言编写的,而不是像JavaScript这样的web编程语言。
+JavaScript 有许多内置的函数,可以让您做很多有用的事情,而无需自己编写所有的代码。事实上,许多你调用(运行或者执行的专业词语)浏览器内置函数时调用的代码并不是使用 JavaScript 来编写——大多数调用浏览器后台的函数的代码,是使用像 C++这样更低级的系统语言编写的,而不是像 JavaScript 这样的 web 编程语言。
-请记住,这些内置浏览器函数不是核心JavaScript语言的一部分——被定义为浏览器API的一部分,它建立在默认语言之上,以提供更多的功能(请参阅本课程的早期部分以获得更多的描述)。我们将在以后的模块中更详细地使用浏览器API。
+请记住,这些内置浏览器函数不是核心 JavaScript 语言的一部分——被定义为浏览器 API 的一部分,它建立在默认语言之上,以提供更多的功能(请参阅本课程的早期部分以获得更多的描述)。我们将在以后的模块中更详细地使用浏览器 API。
程序员把函数称为对象方法(method)的一部分。你还不必了解JavaScript中已建构的对象在更深层次上是如何运作的——你可以等到下一小节,我们会教给你有关对象运作方式的一切。在我们继续前进之前,我们需要澄清一些有关方法和函数概念之间可能存在的误会——当你在网络上浏览相关信息的时候,你很可能会碰上这两个术语。
+程序员把函数称为对象方法(method)的一部分。你还不必了解 JavaScript 中已建构的对象在更深层次上是如何运作的——你可以等到下一小节,我们会教给你有关对象运作方式的一切。在我们继续前进之前,我们需要澄清一些有关方法和函数概念之间可能存在的误会——当你在网络上浏览相关信息的时候,你很可能会碰上这两个术语。
到目前为止我们所使用的内置代码同属于这两种形式:函数和方法。你可以在这里查看内置函数,内置对象以及其相关方法的完整列表。
@@ -92,7 +92,7 @@您在过去的课程中还看到很多定制功能 - 在代码中定义的功能,而不是在浏览器中。每当您看到一个自定义名称后面都带有括号,那么您使用的是自定义函数. 在我们的循环文章中的random-canvas-circles.html示例(另见完整的源代码)中,我们包括一个如下所示的自定义函数:draw()
您在过去的课程中还看到很多定制功能 - 在代码中定义的功能,而不是在浏览器中。每当您看到一个自定义名称后面都带有括号,那么您使用的是自定义函数。在我们的循环文章中的random-canvas-circles.html示例(另见完整的源代码)中,我们包括一个如下所示的自定义函数:draw()
function draw() { ctx.clearRect(0,0,WIDTH,HEIGHT); @@ -104,7 +104,7 @@-自定义函数
} }
该函数在<canvas>
元素中绘制100个随机圆。每次我们想要这样做,我们可以使用这个函数来调用这个功能
该函数在<canvas>
元素中绘制 100 个随机圆。每次我们想要这样做,我们可以使用这个函数来调用这个功能
draw();@@ -114,13 +114,13 @@
我们需要这个函数,因为浏览器的内置Math.random()函数只生成一个0到1之间的随机十进制数。我们想要一个0到一个指定数字之间的随机整数。
+我们需要这个函数,因为浏览器的内置Math.random()函数只生成一个 0 到 1 之间的随机十进制数。我们想要一个 0 到一个指定数字之间的随机整数。
现在你可能很清楚这一点,但仅仅为了防止……,要在函数定义之后,实际使用它,你必须运行或调用它。这是通过将函数名包含在代码的某个地方,后跟圆括号来完成的。
+现在你可能很清楚这一点,但仅仅为了防止……,要在函数定义之后,实际使用它,你必须运行或调用它。这是通过将函数名包含在代码的某个地方,后跟圆括号来完成的。
function myFunction() { alert('hello'); @@ -143,7 +143,7 @@-匿名函数
alert('hello'); }
这个函数叫做匿名函数 — 它没有函数名! 它也不会自己做任何事情。 你通常将匿名函数与事件处理程序一起使用, 例如,如果单击相关按钮,以下操作将在函数内运行代码:
+这个函数叫做匿名函数 — 它没有函数名!它也不会自己做任何事情。你通常将匿名函数与事件处理程序一起使用,例如,如果单击相关按钮,以下操作将在函数内运行代码:
var myButton = document.querySelector('button'); @@ -200,7 +200,7 @@-函数参数
Note: 参数有时称为参数(arguments),属性(properties)或甚至属性(attributes)
-例如,浏览器的内置Math.random()函数不需要任何参数。当被调用时,它总是返回0到1之间的随机数:
+例如,浏览器的内置Math.random()函数不需要任何参数。当被调用时,它总是返回 0 到 1 之间的随机数:
var myNumber = Math.random();@@ -227,15 +227,15 @@函数参数
函数作用域和冲突
-我们来谈一谈 {{glossary("scope")}}即作用域 — 处理函数时一个非常重要的概念。当你创建一个函数时,函数内定义的变量和其他东西都在它们自己的单独的范围内, 意味着它们被锁在自己独立的隔间中, 不能被函数外的代码访问。
+我们来谈一谈 {{glossary("scope")}}即作用域 — 处理函数时一个非常重要的概念。当你创建一个函数时,函数内定义的变量和其他东西都在它们自己的单独的范围内,意味着它们被锁在自己独立的隔间中,不能被函数外的代码访问。
-所有函数的最外层被称为全局作用域。 在全局作用域内定义的值可以在任意地方访问。
+所有函数的最外层被称为全局作用域。在全局作用域内定义的值可以在任意地方访问。
-JavaScript由于各种原因而建立,但主要是由于安全性和组织性。有时您不希望变量可以在代码中的任何地方访问 - 您从其他地方调用的外部脚本可能会开始搞乱您的代码并导致问题,因为它们恰好与代码的其他部分使用了相同的变量名称,造成冲突。这可能是恶意的,或者是偶然的。
+JavaScript 由于各种原因而建立,但主要是由于安全性和组织性。有时您不希望变量可以在代码中的任何地方访问 - 您从其他地方调用的外部脚本可能会开始搞乱您的代码并导致问题,因为它们恰好与代码的其他部分使用了相同的变量名称,造成冲突。这可能是恶意的,或者是偶然的。
-例如,假设您有一个HTML文件,它调用两个外部JavaScript文件,并且它们都有一个使用相同名称定义的变量和函数:
+例如,假设您有一个 HTML 文件,它调用两个外部 JavaScript 文件,并且它们都有一个使用相同名称定义的变量和函数:
<!-- Excerpt from my HTML --> <script src="first.js"></script> @@ -270,14 +270,14 @@-函数作用域和冲突
动物园管理员就像全局作用域 - 他或她有钥匙访问每个园子,重新投喂食物,照顾生病的动物等。
-主动学习: 和 scope 玩耍
+主动学习:和 scope 玩耍
我们来看一个真正的例子来展示范围
- 首先,制作我们的function-scope.html示例的本地副本。它包含两个函数
a()
和b()
,和三个变量——x
,y
和z
——其中两个在函数中被定义,另一个被定义在全局作用域内。它还包含一个名为output()
的函数,它接收一个参数,并将其输出到页面的一个段落中。- 在浏览器和文本编辑器中打开示例。
-- 在浏览器开发工具中打开JavaScript控制台。在JavaScript控制台中,输入以下命令:
+- 在浏览器开发工具中打开 JavaScript 控制台。在 JavaScript 控制台中,输入以下命令:
output(x);@@ -289,7 +289,7 @@主动学习: 和 scope 玩耍
output(y); output(z);-这两个都应该返回错误沿“ ReferenceError:y未定义 ”。这是为什么?由于函数作用域 -
+y和
z
被锁定在函数a()
和b()
函数中,所以output()
从全局作用域调用时无法访问它们。这两个都应该返回错误沿“ ReferenceError:y 未定义 ”。这是为什么?由于函数作用域 -
y和
z
被锁定在函数a()
和b()
函数中,所以output()
从全局作用域调用时无法访问它们。5.但是,从另一个函数里面调用什么呢?尝试编辑
@@ -303,7 +303,7 @@a()
,b()
所以他们看起来像这样:主动学习: 和 scope 玩耍
output(z); }保存代码并重新加载到浏览器中,然后尝试从JavaScript控制台调用
+a()
和b()
函数:保存代码并重新加载到浏览器中,然后尝试从 JavaScript 控制台调用
a()
和b()
函数:a(); b();@@ -322,12 +322,12 @@主动学习: 和 scope 玩耍
output(x); }
再次保存并重新加载,并在JavaScript控制台中再次尝试:
+再次保存并重新加载,并在 JavaScript 控制台中再次尝试:
a(); b();-
函数 a()
和b()
都应该输出x---1的值。这些没有问题,因为即使output()
的调用与x
的定义不在同一个作用域内,但x
是一个全局变量,所以在所有代码中都可用。
函数 a()
和b()
都应该输出 x---1 的值。这些没有问题,因为即使output()
的调用与x
的定义不在同一个作用域内,但x
是一个全局变量,所以在所有代码中都可用。
7.最后,尝试更新您的代码,如下所示:
@@ -341,7 +341,7 @@再次保存并重新加载,并在JavaScript控制台中再次尝试:
+再次保存并重新加载,并在 JavaScript 控制台中再次尝试:
a(); b();@@ -384,7 +384,7 @@
要确保函数调取的数值处在有效的作用域内。上面的例子中会产生一个错误提示,ReferenceError:myValue is not define
,因为尽管myValue
变量与函数调用指令处在同一个作用域中, 但它却没有在函数内被定义 —— 实际代码在调用函数时就开始运行了。为了使代码正确运作,你必须将值作为参数传递给函数,如下所示:
要确保函数调取的数值处在有效的作用域内。上面的例子中会产生一个错误提示,ReferenceError:myValue is not define
,因为尽管myValue
变量与函数调用指令处在同一个作用域中,但它却没有在函数内被定义 —— 实际代码在调用函数时就开始运行了。为了使代码正确运作,你必须将值作为参数传递给函数,如下所示:
function myBigFunction() { var myValue = 1; diff --git a/files/zh-cn/learn/javascript/building_blocks/index.html b/files/zh-cn/learn/javascript/building_blocks/index.html index 1d5ed299e946d2..206cfe75845a01 100644 --- a/files/zh-cn/learn/javascript/building_blocks/index.html +++ b/files/zh-cn/learn/javascript/building_blocks/index.html @@ -1,5 +1,5 @@ --- -title: 创建JavaScript代码块 +title: 创建 JavaScript 代码块 slug: learn/JavaScript/Building_blocks tags: - JavaScript @@ -18,11 +18,11 @@ ---{{LearnSidebar}}-在这个模块中, 我们将继续介绍JavaScript的关键基本特性,在这一章中我们将关注条件控制语句、循环语句、函数模块、事件等通用代码块。你可能在之前的的课程中见过这些模块,但仅仅是见过—在这篇模块中我们将明确讨论这些模块.
+在这个模块中,我们将继续介绍 JavaScript 的关键基本特性,在这一章中我们将关注条件控制语句、循环语句、函数模块、事件等通用代码块。你可能在之前的的课程中见过这些模块,但仅仅是见过—在这篇模块中我们将明确讨论这些模块。
预备知识
-在开始这部分模块之前, 你应该熟悉基本的HTML和CSS, 并且已经看完我们之前的模块:JavaScript 第一步。
+在开始这部分模块之前,你应该熟悉基本的 HTML 和 CSS, 并且已经看完我们之前的模块:JavaScript 第一步。
注: 如果你在使用无法创建自己文件的电脑/平板/其他设备,你可以试试在线编辑器,例如 JSBin 或 Glitch.
@@ -32,11 +32,11 @@指南
- 在代码中做决定 — 条件
-- 在任何程序语言中,程序需要根据不同的输入数据作出相应的选择并执行相关的操作。例如,在游戏中,如果玩家的生命值是0,那么游戏就结束了。在天气应用中,如果在早上打开应用,则显示一个太阳升起的图片,如果在晚上打开,则显示星星和月亮。在这篇文章里我们将探索如何在JS中使用条件结构。
+- 在任何程序语言中,程序需要根据不同的输入数据作出相应的选择并执行相关的操作。例如,在游戏中,如果玩家的生命值是 0,那么游戏就结束了。在天气应用中,如果在早上打开应用,则显示一个太阳升起的图片,如果在晚上打开,则显示星星和月亮。在这篇文章里我们将探索如何在 JS 中使用条件结构。
- 循环语句
-- 有时候你需要在一个行中重复执行某一个任务。例如,查看一整列的名字。在程序中,循环能非常好的处理好这个问题。在本章中我们将介绍JavaScript的循环语句。
+- 有时候你需要在一个行中重复执行某一个任务。例如,查看一整列的名字。在程序中,循环能非常好的处理好这个问题。在本章中我们将介绍 JavaScript 的循环语句。
- 函数 — 可重用的代码块
-- 在编码中的另一个基本概念是函数(functions)。 函数 允许你在定义的区块内存储一段代码用来执行一个单独的任务,然后调用该段代码时,你需要使用一个简短的命令,而不用重复编写多次该段代码。在这篇文章中我们将探讨函数的基本概念,如语法、如何调用定义的函数、作用域和参数。
+- 在编码中的另一个基本概念是函数 (functions)。 函数 允许你在定义的区块内存储一段代码用来执行一个单独的任务,然后调用该段代码时,你需要使用一个简短的命令,而不用重复编写多次该段代码。在这篇文章中我们将探讨函数的基本概念,如语法、如何调用定义的函数、作用域和参数。
- 打造自己的函数
- 本文结合前几篇文章中所涉及的基本理论,提供了一个实践经验。在这里你会得到一些实践,并且编写自己的自定义函数。随后,我们也将进一步解释一些与函数相关的有用的细节。
- 函数返回值
@@ -47,9 +47,9 @@指南
评估
-下面的评估将测试您对JavaScript基础知识的理解。
+下面的评估将测试您对 JavaScript 基础知识的理解。
diff --git a/files/zh-cn/learn/javascript/building_blocks/looping_code/index.html b/files/zh-cn/learn/javascript/building_blocks/looping_code/index.html index c45dbb287d28bc..c60dd90b71d81b 100644 --- a/files/zh-cn/learn/javascript/building_blocks/looping_code/index.html +++ b/files/zh-cn/learn/javascript/building_blocks/looping_code/index.html @@ -16,24 +16,24 @@
- 图片画廊
-- 现在我们已经学习了构建JavaScript的基本代码块,我们会通过构建一个在很多网站上相当常见的项目——一个由JavaScript驱动的相册,来测试你循环、函数、条件语句和事件方面的知识。
+- 现在我们已经学习了构建 JavaScript 的基本代码块,我们会通过构建一个在很多网站上相当常见的项目——一个由 JavaScript 驱动的相册,来测试你循环、函数、条件语句和事件方面的知识。
{{PreviousMenuNext("Learn/JavaScript/Building_blocks/conditionals","Learn/JavaScript/Building_blocks/Functions", "Learn/JavaScript/Building_blocks")}}-编程语言可以很迅速方便地帮我们完成一些重复性的任务,从多个基本计算到几乎完成了很多类似工作的其他情况。现在我们来看看处理这种需求的JavaScript中可用的循环结构。
+编程语言可以很迅速方便地帮我们完成一些重复性的任务,从多个基本计算到几乎完成了很多类似工作的其他情况。现在我们来看看处理这种需求的 JavaScript 中可用的循环结构。
- 前提条件: -基本的电脑知识,对HTML与CSS有基本的了解,及已阅读: JavaScript first steps(JS的入门). +前提条件: +基本的电脑知识,对 HTML 与 CSS 有基本的了解,及已阅读: JavaScript first steps(JS 的入门). - 目标: -学习如何在JS里面使用循环语句. +目标: +学习如何在 JS 里面使用循环语句。 来一起循环
-循环,循环,循环. 就与这些:popular breakfast cereals, roller coasters and musical production一样,类似存在于编程中.编程中的循环也是一直重复着去做一件事 - 此处循环便是编程中的术语.
+循环,循环,循环。就与这些:popular breakfast cereals, roller coasters and musical production一样,类似存在于编程中。编程中的循环也是一直重复着去做一件事 - 此处循环便是编程中的术语。
让我们来想一下下图,这位农夫考虑为他的家庭做一周的食物计划,他或许就需要执行一段循环:
@@ -43,9 +43,9 @@来一起循环
一段循环通常需要一个或多个条件:
-
- 一个开始条件,它被初始化为一个特定的值 - 这是循环的起点("开始:我没有食物”,上面)。
-- 一个结束条件,这是循环停止的标准 - 通常计数器达到一定值。 以上所说的“我有足够的食物”吗? 假设他需要10份食物来养活他的家人。
-- 一个迭代器,这通常在每个连续循环上递增少量的计数器,直到达到退出条件。 我们以前没有明确说明,但是我们可以考虑一下农民能够每小时收集2份食物。 每小时后,他收集的食物量增加了两倍,他检查他是否有足够的食物。 如果他已经达到10分(退出条件),他可以停止收集回家。
+- 一个开始条件,它被初始化为一个特定的值 - 这是循环的起点 ("开始:我没有食物”,上面)。
+- 一个结束条件,这是循环停止的标准 - 通常计数器达到一定值。以上所说的“我有足够的食物”吗?假设他需要 10 份食物来养活他的家人。
+- 一个迭代器,这通常在每个连续循环上递增少量的计数器,直到达到退出条件。我们以前没有明确说明,但是我们可以考虑一下农民能够每小时收集 2 份食物。每小时后,他收集的食物量增加了两倍,他检查他是否有足够的食物。如果他已经达到 10 分(退出条件),他可以停止收集回家。
在 {{glossary("伪代码")}} 中,这看起来就像下面这样:
@@ -60,15 +60,15 @@来一起循环
} } -所以需要的食物量定为10,农民目前的数量为0。在循环的每次迭代中,我们检查农民的食物量是否等于他需要的量。 如果是这样,我们可以退出循环。 如果没有,农民花一个小时收集两部分食物,循环再次运行。
+所以需要的食物量定为 10,农民目前的数量为 0。在循环的每次迭代中,我们检查农民的食物量是否等于他需要的量。如果是这样,我们可以退出循环。如果没有,农民花一个小时收集两部分食物,循环再次运行。
为何?
-在这一点上,您可能会了解循环中的高级概念,但您可能会认为“好的,但是,这有助于我编写更好的JavaScript代码?” 正如我们前面所说,循环与所做的事情都是一样的,这对于快速完成重复任务是非常有用的。
+在这一点上,您可能会了解循环中的高级概念,但您可能会认为“好的,但是,这有助于我编写更好的 JavaScript 代码?”正如我们前面所说,循环与所做的事情都是一样的,这对于快速完成重复任务是非常有用的。
-通常,循环的每个连续迭代的代码将略有不同,这意味着您可以完成相同但略有不同的任务的全部负载 - 如果您有很多不同的计算要做, 做不同的一个,不一样的一个又一个!
+通常,循环的每个连续迭代的代码将略有不同,这意味着您可以完成相同但略有不同的任务的全部负载 - 如果您有很多不同的计算要做,做不同的一个,不一样的一个又一个!
-让我们来看一个例子来完美地说明为什么循环是一件好事。 假设我们想在{{htmlelement("canvas")}}元素上绘制100个随机圆(按更新按钮一次又一次地运行示例以查看不同的随机集):
+让我们来看一个例子来完美地说明为什么循环是一件好事。假设我们想在{{htmlelement("canvas")}}元素上绘制 100 个随机圆(按更新按钮一次又一次地运行示例以查看不同的随机集):
-Hidden code
@@ -142,7 +142,7 @@Hidden code
{{ EmbedLiveSample('Hidden_code', '100%', 400, "", "", "hide-codepen-jsfiddle") }}
-您现在不需要理解所有代码,但我们来看看实际绘制100个圆的那部分代码:
+您现在不需要理解所有代码,但我们来看看实际绘制 100 个圆的那部分代码:
for (var i = 0; i < 100; i++) { ctx.beginPath(); @@ -161,7 +161,7 @@-Hidden code
-
您应该有一个基本的想法 - 我们使用一个循环来运行这个代码的100次迭代,其中每一个在页面上的随机位置绘制一个圆。 无论我们绘制100个圆,1000还是10,000,所需的代码量将是相同的。 只有一个数字必须改变。
+您应该有一个基本的想法 - 我们使用一个循环来运行这个代码的 100 次迭代,其中每一个在页面上的随机位置绘制一个圆。无论我们绘制 100 个圆,1000 还是 10,000,所需的代码量将是相同的。只有一个数字必须改变。
如果我们在这里没有使用循环,我们必须为我们想要绘制的每个圆重复以下代码:
@@ -170,11 +170,11 @@Hidden code
ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); ctx.fill();这将非常无聊而且很难维持高速。 循环真的相当好用。
+这将非常无聊而且很难维持高速。循环真的相当好用。
循环的标准
-我们开始探索一些特定的循环结构。 第一个,你会经常使用到它,for循环 - 以下为for循环的语法:
+我们开始探索一些特定的循环结构。第一个,你会经常使用到它,for 循环 - 以下为 for 循环的语法:
for (initializer; exit-condition; final-expression) { // code to run @@ -187,8 +187,8 @@循环的标准
- 在括号内,我们有三个项目,以分号分隔:
- 一个初始化器 - 这通常是一个设置为一个数字的变量,它被递增来计算循环运行的次数。它也有时被称为计数变量。
-- 一个退出条件 -如前面提到的,这个定义循环何时停止循环。这通常是一个表现为比较运算符的表达式,用于查看退出条件是否已满足的测试。
-- 一个最终条件 -这总是被判断(或运行),每个循环已经通过一个完整的迭代消失时间。它通常用于增加(或在某些情况下递减)计数器变量,使其更接近退出条件值。
+- 一个退出条件 - 如前面提到的,这个定义循环何时停止循环。这通常是一个表现为比较运算符的表达式,用于查看退出条件是否已满足的测试。
+- 一个最终条件 - 这总是被判断(或运行),每个循环已经通过一个完整的迭代消失时间。它通常用于增加(或在某些情况下递减)计数器变量,使其更接近退出条件值。
- 一些包含代码块的花括号 - 每次循环迭代时都会运行这个代码。
@@ -245,30 +245,30 @@Hidden code 2
{{ EmbedLiveSample('Hidden_code_2', '100%', 60, "", "", "hide-codepen-jsfiddle") }}
--注: 您可以在GitHub上找到这段示例代码。 (也可以在线运行)。
+注: 您可以在 GitHub 上找到这段示例代码。 (也可以在线运行)。
这显示了一个循环用于迭代数组中的项目,并与每个项目进行一些操作 - JavaScript中非常常见的模式。 这里:
+这显示了一个循环用于迭代数组中的项目,并与每个项目进行一些操作 - JavaScript 中非常常见的模式。这里:
-
- 迭代器
-i
从0开始(var i = 0
)。- 循环将会一直运行直到它不再小于猫数组的长度。 这很重要 - 退出条件显示循环仍然运行的条件。 所以在这种情况下,
-<cats.length
仍然是真的,循环仍然运行。- 在循环中,我们将当前的循环项(
cats[i]
是cats[当前下标的任何东西]
)以及逗号和空格连接到info
变量的末尾。 所以: +- 迭代器
+i
从 0 开始(var i = 0
)。- 循环将会一直运行直到它不再小于猫数组的长度。这很重要 - 退出条件显示循环仍然运行的条件。所以在这种情况下,
+<cats.length
仍然是真的,循环仍然运行。- 在循环中,我们将当前的循环项(
cats[i]
是cats[当前下标的任何东西]
)以及逗号和空格连接到info
变量的末尾。所以:
- 在第一次运行中,
i = 0
,所以cats[0] +','将
被连接到info("Bill")
上。- 在第二次运行中,
-i = 1
,所以cats[1] +','
将被连接到info("Jeff")
上。- 等等。 每次循环运行后,1将被添加到i(i ++),然后进程将再次启动。
+- 等等。每次循环运行后,1 将被添加到 i(i ++),然后进程将再次启动。
- 当等于
cats.length
时,循环将停止,浏览器将移动到循环下面的下一个代码位。-注: 我们将退出条件设为
+< cats.length
,而不是<= cats.length
是因为计算机从0开始,而不是1 - 开始时i
是0,并且逐步增加到i= 4
(最后一个数组的索引)。cats.length
返回5,因为数组中有5个项目,但是我们不希望达到i = 5
,因为这将返回未定义的最后一个项目(没有索引为5的数组项目)。 所以我们想要比cats.length
(i <
)少1,而不是cats.length
(i <=
)。注: 我们将退出条件设为
< cats.length
,而不是<= cats.length
是因为计算机从 0 开始,而不是 1 - 开始时i
是 0,并且逐步增加到 i= 4
(最后一个数组的索引)。cats.length
返回 5,因为数组中有 5 个项目,但是我们不希望达到i = 5
,因为这将返回未定义的最后一个项目(没有索引为 5 的数组项目)。所以我们想要比cats.length
(i <
)少 1,而不是cats.length
(i <=
)。-注: 退出条件的一个常见错误是使它们使用“等于”(
+===
)而不是说“小于或等于”(<=
)。 如果我们想要运行我的循环到i = 5
,退出条件将需要是i <= cats.length
。如果我们设置为i === cats.length
,循环将不会运行,因为在第一次循环迭代时 i 不等于5,所以循环会立即停止。注: 退出条件的一个常见错误是使它们使用“等于”(
===
) 而不是说“小于或等于”(<=
)。如果我们想要运行我的循环到i = 5
,退出条件将需要是i <= cats.length
。如果我们设置为i === cats.length
,循环将不会运行,因为在第一次循环迭代时 i 不等于 5,所以循环会立即停止。我们留下的一个小问题是最后的输出句子形式不是很好:
@@ -277,7 +277,7 @@Hidden code 2
My cats are called Bill, Jeff, Pete, Biggles, Jasmin,
-理想情况下,我们想改变最后循环迭代中的连接,以便在句子末尾没有逗号。 嗯,没问题 - 我们可以很高兴地在我们的for循环中插入一个条件来处理这种特殊情况:
+理想情况下,我们想改变最后循环迭代中的连接,以便在句子末尾没有逗号。嗯,没问题 - 我们可以很高兴地在我们的 for 循环中插入一个条件来处理这种特殊情况:
for (var i = 0; i < cats.length; i++) { if (i === cats.length - 1) { @@ -288,20 +288,20 @@Hidden code 2
}-注: 您可以在GitHub上找到这个例子。(也可以在线运行)
+注: 您可以在 GitHub 上找到这个例子。(也可以在线运行)
--重要: 使用
+for
- 与所有循环一样,您必须确保初始化程序被迭代,以便最终达到退出条件。 如果没有,循环将永不停止,浏览器将强制它停止,否则会崩溃。 这被称为无限循环。重要: 使用
for
- 与所有循环一样,您必须确保初始化程序被迭代,以便最终达到退出条件。如果没有,循环将永不停止,浏览器将强制它停止,否则会崩溃。这被称为无限循环。使用break退出循环
+使用 break 退出循环
-如果要在所有迭代完成之前退出循环,可以使用break语句。 当我们查看switch语句时,我们已经在上一篇文章中遇到过这样的情况 - 当switch语句中符合输入表达式的情况满足时,break语句立即退出switch语句并移动到代码之后。
+如果要在所有迭代完成之前退出循环,可以使用 break 语句。当我们查看 switch 语句时,我们已经在上一篇文章中遇到过这样的情况 - 当 switch 语句中符合输入表达式的情况满足时,break 语句立即退出 switch 语句并移动到代码之后。
-与循环相同 - break语句将立即退出循环,并使浏览器移动到跟随它的任何代码。
+与循环相同 - break 语句将立即退出循环,并使浏览器移动到跟随它的任何代码。
-说我们想搜索一系列联系人和电话号码,只返回我们想要找的号码? 首先,一些简单的HTML - 一个文本{{htmlelement("input")}},允许我们输入一个名称来搜索,一个{{htmlelement("button")}}元素来提交搜索,以及一个{{htmlelement ("p")}}元素显示结果:
+说我们想搜索一系列联系人和电话号码,只返回我们想要找的号码?首先,一些简单的 HTML - 一个文本{{htmlelement("input")}},允许我们输入一个名称来搜索,一个{{htmlelement("button")}}元素来提交搜索,以及一个{{htmlelement ("p")}}元素显示结果:
<label for="search">Search by contact name: </label> @@ -310,7 +310,7 @@-使用break退出循环
<p></p>然后是JavaScript:
+然后是 JavaScript:
const contacts = ['Chris:2232322', 'Sarah:3453456', 'Bill:7654322', 'Mary:9998769', 'Dianne:9384975']; const para = document.querySelector('p'); @@ -385,25 +385,25 @@Hidden code 3
- 首先我们有一些变量定义 - 我们有一个联系信息数组,每个项目是一个字符串,包含一个以冒号分隔的名称和电话号码。
- 接下来,我们将一个事件监听器附加到按钮(
btn
)上,这样当按下它时,运行一些代码来执行搜索并返回结果。- 我们将输入的值输入到一个名为
-searchName
的变量中,然后清空文本输入并重新对准它,准备进行下一个搜索。- 现在有趣的部分,for循环: +
- 现在有趣的部分,for 循环:
-
- 我们的计数器开始时为在0,直到计数器不再小于
+contacts.length
,并在循环的每次迭代之后将i
递增1。- 我们的计数器开始时为在 0,直到计数器不再小于
contacts.length
,并在循环的每次迭代之后将i
递增 1。- 在循环中,我们首先将当前联系人(
-contacts [i]
)拆分为冒号字符,并将生成的两个值存储在名为splitContact
的数组中。- 然后,我们使用条件语句来测试
+splitContact [0]
(联系人姓名)是否等于输入的searchName
。 如果是,我们在段落中输入一个字符串来报告联系人的号码,并使用break来结束循环。- 然后,我们使用条件语句来测试
splitContact [0]
(联系人姓名)是否等于输入的searchName
。如果是,我们在段落中输入一个字符串来报告联系人的号码,并使用 break 来结束循环。- 在
(contacts.length-1)
迭代后,如果联系人姓名与输入的搜索不符,则段落文本设置为“未找到联系人”,循环继续迭代。--注:您可以在GitHub上找到这个例子或在线运行。
+注:您可以在 GitHub 上找到这个例子或在线运行。
使用continue跳过迭代
+使用 continue 跳过迭代
-continue语句以类似的方式工作,而不是完全跳出循环,而是跳过当前循环而执行下一个循环。 我们来看另外一个例子,它把一个数字作为一个输入,并且只返回开平方之后为整数的数字(整数)。
+continue 语句以类似的方式工作,而不是完全跳出循环,而是跳过当前循环而执行下一个循环。我们来看另外一个例子,它把一个数字作为一个输入,并且只返回开平方之后为整数的数字(整数)。
-HTML与最后一个例子基本相同 - 一个简单的文本输入和一个输出段落。 JavaScript也是一样的,虽然循环本身有点不同:
+HTML 与最后一个例子基本相同 - 一个简单的文本输入和一个输出段落。JavaScript 也是一样的,虽然循环本身有点不同:
var num = input.value; @@ -467,21 +467,21 @@Hidden code 4
{{ EmbedLiveSample('Hidden_code_4', '100%', 100, "", "", "hide-codepen-jsfiddle") }}
-
- 在这种情况下,输入应为数字(
+num
)。 for循环给定一个从1开始的计数器(在这种情况下,我们对0不感兴趣),一个退出条件,当计数器大于输入num
时循环将停止,并且迭代器的计数器将每次增加1。- 在这种情况下,输入应为数字(
num
)。for 循环给定一个从 1 开始的计数器(在这种情况下,我们对 0 不感兴趣),一个退出条件,当计数器大于输入num
时循环将停止,并且迭代器的计数器将每次增加 1。- 在循环中,我们使用
-Math.sqrt(i)
找到每个数字的平方根,然后测试平方根是否是一个整数,通过判断当它被向下取整时,它是否与自身相同(这是Math.floor(...)
对传递的数字的作用)。- 如果平方根和四舍五入的平方根不相等(
-!==
),则表示平方根不是整数,因此我们对此不感兴趣。 在这种情况下,我们使用continue语句跳过当前循环而执行下一个循环迭代,而不在任何地方记录该数字。- 如果平方根是一个整数,我们完全跳过if块,所以continue语句不被执行; 相反,我们将当前i值加上一个空格连接到段落内容的末尾。
+- 如果平方根和四舍五入的平方根不相等(
+!==
),则表示平方根不是整数,因此我们对此不感兴趣。在这种情况下,我们使用 continue 语句跳过当前循环而执行下一个循环迭代,而不在任何地方记录该数字。- 如果平方根是一个整数,我们完全跳过 if 块,所以 continue 语句不被执行; 相反,我们将当前 i 值加上一个空格连接到段落内容的末尾。
--注:您可以在GitHub上查看完整代码,或者在线运行。
+注:您可以在 GitHub 上查看完整代码,或者在线运行。
while语句和do ... while语句
+while 语句和 do ... while 语句
-+
for
不是JavaScript中唯一可用的循环类型。 实际上还有很多其他的,而现在你不需要理解所有这些,所以值得看几个人的结构,这样你就可以在稍微不同的方式识别出相同的功能。-
for
不是 JavaScript 中唯一可用的循环类型。实际上还有很多其他的,而现在你不需要理解所有这些,所以值得看几个人的结构,这样你就可以在稍微不同的方式识别出相同的功能。首先,我们来看看while循环。 这个循环的语法如下所示:
+首先,我们来看看 while 循环。这个循环的语法如下所示:
initializer while (exit-condition) { @@ -490,11 +490,11 @@-while语句和do ... while语句
final-expression }除了在循环之前设置初始化器变量,并且在运行代码之后,循环中包含final-expression,而不是这两个项目被包含在括号中,这与以前的for循环非常类似。 退出条件包含在括号内,前面是while关键字而不是for。
+除了在循环之前设置初始化器变量,并且在运行代码之后,循环中包含 final-expression,而不是这两个项目被包含在括号中,这与以前的 for 循环非常类似。退出条件包含在括号内,前面是 while 关键字而不是 for。
-同样的三个项目仍然存在,它们仍然以与for循环中相同的顺序定义 - 这是有道理的,因为您必须先定义一个初始化器,然后才能检查它是否已到达退出条件; 在循环中的代码运行(迭代已经完成)之后,运行最后的条件,这只有在尚未达到退出条件时才会发生。
+同样的三个项目仍然存在,它们仍然以与 for 循环中相同的顺序定义 - 这是有道理的,因为您必须先定义一个初始化器,然后才能检查它是否已到达退出条件; 在循环中的代码运行(迭代已经完成)之后,运行最后的条件,这只有在尚未达到退出条件时才会发生。
-我们再来看看我们的猫列表示例,但是重写了一个while循环:
+我们再来看看我们的猫列表示例,但是重写了一个 while 循环:
var i = 0; @@ -512,7 +512,7 @@while语句和do ... while语句
Note: This still works just the same as expected — have a look at it running live on GitHub (also view the full source code).
do...while循环非常类似但在while后提供了终止条件:
+do...while循环非常类似但在 while 后提供了终止条件:
initializer do { @@ -521,11 +521,11 @@-while语句和do ... while语句
final-expression } while (exit-condition)在这种情况下,在循环开始之前,初始化程序先重新开始。 do关键字直接在包含要运行的代码的花括号和终止条件之前。
+在这种情况下,在循环开始之前,初始化程序先重新开始。do 关键字直接在包含要运行的代码的花括号和终止条件之前。
-这里的区别在于退出条件是一切都包含在括号中,而后面是一个while关键字。 在do ... while循环中,花括号中的代码总是在检查之前运行一次,以查看是否应该再次执行(在while和for中,检查首先出现,因此代码可能永远不会执行)。
+这里的区别在于退出条件是一切都包含在括号中,而后面是一个 while 关键字。在 do ... while 循环中,花括号中的代码总是在检查之前运行一次,以查看是否应该再次执行(在 while 和 for 中,检查首先出现,因此代码可能永远不会执行)。
-我们再次重写我们的猫列表示例,以使用do...while循环:
+我们再次重写我们的猫列表示例,以使用 do...while 循环:
var i = 0; @@ -540,19 +540,19 @@while语句和do ... while语句
} while (i < cats.length);-Note: 再一次,它正如我们期望的那样工作 — 看一看它在Github在线运行 (或者查看完整源代码).
+Note: 再一次,它正如我们期望的那样工作 — 看一看它在Github 在线运行 (或者查看完整源代码).
-Important: 使用 while 和 do...while — 所有循环都一样 — 你必须保证初始变量是迭代的,那么它才会逐渐地达到退出条件. 不然, 它将会永远循环下去, 要么浏览器会强制终止它,要么它自己会崩溃. 这称为无限循环.
+Important: 使用 while 和 do...while — 所有循环都一样 — 你必须保证初始变量是迭代的,那么它才会逐渐地达到退出条件。不然,它将会永远循环下去,要么浏览器会强制终止它,要么它自己会崩溃。这称为无限循环。
主动学习:启动倒计时!
-在这个练习中,我们希望你打印出一个简单的启动倒计时到输出框,从10到关闭。 具体来说,我们希望你:
+在这个练习中,我们希望你打印出一个简单的启动倒计时到输出框,从 10 到关闭。具体来说,我们希望你:
-
- 从10下降到0.我们为您提供了一个初始化器 - var i = 10;
+- 从 10 下降到 0.我们为您提供了一个初始化器 - var i = 10;
- 对于每次迭代,创建一个新的段落并将其附加到输出<div>,我们使用
var output = document.querySelector('.output');
。在评论中,我们为您提供了需要在循环中某处使用的三条代码行:-
- @@ -562,15 +562,15 @@
var para = document.createElement('p');
—新建一个段落。主动学习:启动倒计时!
- 不同的迭代数字需要将不同的文本放在该迭代的段落中(您需要一个条件语句和多个
-para.textContent = lines
):-
- 如果数字是10,打印“Countdown 10”到段落。
-- 如果数字为0,请打印“Blast off!” 到段落。
+- 如果数字是 10,打印“Countdown 10”到段落。
+- 如果数字为 0,请打印“Blast off!”到段落。
- 对于任何其他数字,只打印段落的数字。
- 记住要包括一个迭代器! 然而,在这个例子中,我们在每次迭代之后都下降,而不是上升,所以你不想要
+i++
- 你如何向下迭代?- 记住要包括一个迭代器!然而,在这个例子中,我们在每次迭代之后都下降,而不是上升,所以你不想要
i++
- 你如何向下迭代?如果您犯了错误,您可以随时使用“重置”按钮重置该示例。 如果你真的卡住了,请按“显示解决方案”来查看解决方案。
+如果您犯了错误,您可以随时使用“重置”按钮重置该示例。如果你真的卡住了,请按“显示解决方案”来查看解决方案。
Active learning
@@ -627,12 +627,12 @@Active learning
主动学习:填写来宾列表
-在本练习中,我们希望您获取存储在数组中的名称列表,并将其放入来宾列表中。 但这不是那么容易 - 我们不想让菲尔和洛拉进来,因为他们是贪婪和粗鲁的,总是吃所有的食物! 我们有两个名单,一个是客人承认的,一个是客人拒绝的。
+在本练习中,我们希望您获取存储在数组中的名称列表,并将其放入来宾列表中。但这不是那么容易 - 我们不想让菲尔和洛拉进来,因为他们是贪婪和粗鲁的,总是吃所有的食物!我们有两个名单,一个是客人承认的,一个是客人拒绝的。
具体来说,我们希望你:
-
-- 编写一个循环,它将从0迭代到people数组的长度。 你需要从一个初始化器
+var i = 0
开始,但是你需要什么退出条件?- 编写一个循环,它将从 0 迭代到 people 数组的长度。你需要从一个初始化器
var i = 0
开始,但是你需要什么退出条件?- 在每个循环迭代期间,使用条件语句检查当前数组项是否等于“Phil”或“Lola”:
- 如果是,则将数组项连接到拒绝段落的
@@ -649,9 +649,9 @@textContent
的末尾,后跟逗号和空格。主动学习:填写来宾列表
admitted.textContent +=
- 将连接某些内容到一行的结尾的行的开始。额外的奖金问题 - 成功完成上述任务后,您将留下两个名称列表,用逗号分隔,但它们将不整齐 - 每个结尾处都会有一个逗号。 你可以制定出如何在每种情况下编写最后一个逗号的行,并添加一个完整的停止? 看看有用的字符串方法文章的帮助。
+额外的奖金问题 - 成功完成上述任务后,您将留下两个名称列表,用逗号分隔,但它们将不整齐 - 每个结尾处都会有一个逗号。你可以制定出如何在每种情况下编写最后一个逗号的行,并添加一个完整的停止?看看有用的字符串方法文章的帮助。
-如果您犯了错误,您可以随时使用“重置”按钮重置该示例。 如果你真的卡住了,请按“显示解决方案”来查看解决方案。
+如果您犯了错误,您可以随时使用“重置”按钮重置该示例。如果你真的卡住了,请按“显示解决方案”来查看解决方案。
Active learning 2
@@ -712,7 +712,7 @@Active learning 2
应该使用哪种循环类型?
-对于基本用途,for,while和do ... while循环大部分可互换。 他们都可以用来解决相同的问题,你使用哪一个将在很大程度上取决于你的个人偏好 - 哪一个你最容易记住或最直观的。 我们再来看看他们。
+对于基本用途,for,while 和 do ... while 循环大部分可互换。他们都可以用来解决相同的问题,你使用哪一个将在很大程度上取决于你的个人偏好 - 哪一个你最容易记住或最直观的。我们再来看看他们。
首先是
@@ -746,7 +746,7 @@for
:应该使用哪种循环类型?
结论 -本文向您展示了背后的基本概念,以及JavaScript中循环代码时可用的不同选项。 你现在应该明白为什么循环是一个处理重复代码的好机制,并且在你自己的例子中使用它们!
+本文向您展示了背后的基本概念,以及 JavaScript 中循环代码时可用的不同选项。你现在应该明白为什么循环是一个处理重复代码的好机制,并且在你自己的例子中使用它们!
如果您有什么不明白的地方,可以再通读一遍,或者联系我们寻求帮助。
diff --git a/files/zh-cn/learn/javascript/building_blocks/return_values/index.html b/files/zh-cn/learn/javascript/building_blocks/return_values/index.html index 6f30c98cce12bd..fa558e3f5e4cf1 100644 --- a/files/zh-cn/learn/javascript/building_blocks/return_values/index.html +++ b/files/zh-cn/learn/javascript/building_blocks/return_values/index.html @@ -11,26 +11,26 @@{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Build_your_own_function","Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}-函数返回值-是本章中最后一个基础概念,让我们一起来瞧瞧.。有些函数在执行完毕后不会返回一个有用的值,但有些会, 重要的是理解返回的是什么,怎样使用这些值在你的代码中,我们将在下面讨论这些。
+函数返回值 - 是本章中最后一个基础概念,让我们一起来瞧瞧.。有些函数在执行完毕后不会返回一个有用的值,但有些会,重要的是理解返回的是什么,怎样使用这些值在你的代码中,我们将在下面讨论这些。
-
- 前提: +前提: - 基础的计算机知识, 懂得基础的HTML 和CSS, JavaScript 第一步学习, 函数- 可重用的代码块.
+基础的计算机知识,懂得基础的 HTML 和 CSS, JavaScript 第一步学习,函数- 可重用的代码块。
- 目标: +目标: 理解什么函数的返回值 , 和如何使用它们 什么是返回值?
+什么是返回值?
-返回值意如其名,是指函数执行完毕后返回的值。你已经多次遇见过返回值,尽管你可能没有明确的考虑过他们。让我们一起回看一些熟悉的代码:
+返回值意如其名,是指函数执行完毕后返回的值。你已经多次遇见过返回值,尽管你可能没有明确的考虑过他们。让我们一起回看一些熟悉的代码:
var myText = 'I am a string'; var newString = myText.replace('string', 'sausage'); @@ -41,15 +41,15 @@什么是返回值?
在第一篇函数文章中,我们确切地看到了这一块代码。我们对
-myText
字符串调用 replace() 功能,并通过这两个参数的字符串查找,和子串替换它。当这个函数完成(完成运行)后,它返回一个值,这个值是一个新的字符串,它具有替换的功能。在上面的代码中,我们保存这个返回值,以作为newString
变量的内容。如果你看看替换功能MDN参考页面,你会看到一个返回值。知道和理解函数返回的值是非常有用的,因此我们尽可能地包含这些信息。
+如果你看看替换功能 MDN 参考页面,你会看到一个返回值。知道和理解函数返回的值是非常有用的,因此我们尽可能地包含这些信息。
-一些函数没有返回值就像(在我们的参考页中,返回值在这种情况下被列出为空值
+void
或未定义值undefined
。).例如, 我们在前面文章中创建的 displayMessage() function , 由于调用的函数的结果,没有返回特定的值。它只是让一个提示框出现在屏幕的某个地方——就是这样!一些函数没有返回值就像 (在我们的参考页中,返回值在这种情况下被列出为空值
void
或未定义值undefined
。).例如,我们在前面文章中创建的 displayMessage() function , 由于调用的函数的结果,没有返回特定的值。它只是让一个提示框出现在屏幕的某个地方——就是这样!通常,返回值是用在函数在计算某种中间步骤。你想得到最终结果,其中包含一些值。那些值需要通过一个函数计算得到,然后返回结果可用于计算的下一个阶段。
在自定义的函数中使用返回值
-要从自定义函数返回值,您需要使用…等待它… return 关键字。 我们最近在random-canvas-circles.html示例中看到了这一点。 我们的
+draw()
函数绘制100随机圆在HTML的{{htmlelement("canvas")}}:要从自定义函数返回值,您需要使用…等待它… return 关键字。我们最近在random-canvas-circles.html示例中看到了这一点。我们的
draw()
函数绘制 100 随机圆在 HTML 的{{htmlelement("canvas")}}:function draw() { ctx.clearRect(0,0,WIDTH,HEIGHT); @@ -61,7 +61,7 @@-在自定义的函数中使用 } }
在每个循环迭代,
+random()
函数调用了三次,分别生成当前圆的x坐标,一个随机值Y坐标和半径。random()
函数接受一个参数-一个整数,返回0到这个整数之间的随机数。看起来像这样:在每个循环迭代,
random()
函数调用了三次,分别生成当前圆的 x 坐标,一个随机值 Y 坐标和半径。random()
函数接受一个参数 - 一个整数,返回 0 到这个整数之间的随机数。看起来像这样:function randomNumber(number) { return Math.floor(Math.random()*number); @@ -80,7 +80,7 @@在自定义的函数中使用
ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);-这三次
+random()
调用分别返回值500, 200和35,实际上这一行这样运行:这三次
random()
调用分别返回值 500, 200 和 35,实际上这一行这样运行:ctx.arc(500, 200, 35, 0, 2 * Math.PI);@@ -91,8 +91,8 @@主动学习:我们自
让我们着手编写具有我们自己的返回值的函数。
-
- 首先,从GitHub的function-library.html文件复制一份本地副本。这是一个简单的HTML页面包含一个 {{htmlelement("input")}} 文本域和一个段落。 还有一个 {{htmlelement("script")}} 元素,我们在两个变量中存储了对两个HTML元素的引用。这个小页面允许你在文本框中输入一个数字,并在下面的段落中显示不同的数字。
-- 让我们添加一些有用的函数。在现有的两行JavaScript下面,添加以下函数定义: +
- 首先,从 GitHub 的function-library.html文件复制一份本地副本。这是一个简单的 HTML 页面包含一个 {{htmlelement("input")}} 文本域和一个段落。还有一个 {{htmlelement("script")}} 元素,我们在两个变量中存储了对两个 HTML 元素的引用。这个小页面允许你在文本框中输入一个数字,并在下面的段落中显示不同的数字。
+- 让我们添加一些有用的函数。在现有的两行 JavaScript 下面,添加以下函数定义:
+function squared(num) { return num * num; } @@ -109,7 +109,7 @@-主动学习:我们自 } return num; }
squared()
和cubed()
功能是相当明显的-他们的平方或立方的数作为一个参数返回。factorial()函数返回给定数字的阶乘。squared()
和cubed()
功能是相当明显的 - 他们的平方或立方的数作为一个参数返回。factorial() 函数返回给定数字的阶乘。- 接下来,我们将包括一种打印输入到文本输入中的数字的信息的方法。在现有函数下面输入以下事件处理程序:
input.onchange = function() { var num = input.value; @@ -122,17 +122,17 @@-主动学习:我们自 } }
这里我们创建一个
+onchange
事件处理程序,当文本框上面的change事件被触发的之后,事件处理程序就会运行 - 就是说,一个新的值被输入到文本框并且被提交(就比如,输入一个值,然后按Tab)。当这个匿名函数运行时,输入框中的值将被存储在num
变量中。这里我们创建一个
-onchange
事件处理程序,当文本框上面的 change 事件被触发的之后,事件处理程序就会运行 - 就是说,一个新的值被输入到文本框并且被提交(就比如,输入一个值,然后按 Tab)。当这个匿名函数运行时,输入框中的值将被存储在num
变量中。接下来,我们进行条件测试——如果输入的值不是数字,则在段落中打印错误消息。if语句判断isNaN(num)表达式是否返回true。我们用
+isNaN()
函数测试num
的值是否不是一个数字-如果不是数字,就返回true
,否则返回false
。接下来,我们进行条件测试——如果输入的值不是数字,则在段落中打印错误消息。if 语句判断isNaN(num)表达式是否返回 true。我们用
-isNaN()
函数测试num
的值是否不是一个数字 - 如果不是数字,就返回true
,否则返回false
。如果测试返回false,则数值是一个数字,所以我们在段落元素中打印出一个句子,说明数字的平方、立方体和阶乘是什么。这句话叫squared(),cubed(),和factorial()函数来获得所需的值。
+如果测试返回 false,则数值是一个数字,所以我们在段落元素中打印出一个句子,说明数字的平方、立方体和阶乘是什么。这句话叫 squared(),cubed(),和 factorial() 函数来获得所需的值。
- 保存您的代码,将其加载到浏览器中,然后尝试.
-Note:如果你有麻烦让例子工作,对比GitHub的已完成版检查你的代码(或看它在线运行),或寻求我们的帮助。
+Note:如果你有麻烦让例子工作,对比GitHub 的已完成版检查你的代码(或看它在线运行),或寻求我们的帮助。
在这一点上,我们希望您编写一个自己的几个函数,并将它们添加到库中。这个数的平方根或立方根,或一个圆的周长和半径是多少?
@@ -141,12 +141,12 @@主动学习:我们自
- 查看另一个将错误处理写入函数的示例。它是否提供了任何必要的参数通常是一个好主意,另一方面对可选参数提供默认值。这样,你的程序就不太可能出错了。
-- 关于创建函数库思想的思考。随着你深入到你的编程生涯,你将开始一次又一次地做同样的事情。这是一个好主意,开始保持你自己的实用工具库,你经常使用-你可以把它们复制到你的新代码,甚至只是把它应用到任何你需要的HTML页面。
+- 关于创建函数库思想的思考。随着你深入到你的编程生涯,你将开始一次又一次地做同样的事情。这是一个好主意,开始保持你自己的实用工具库,你经常使用 - 你可以把它们复制到你的新代码,甚至只是把它应用到任何你需要的 HTML 页面。
结论
-因此,我们让它-功能是有趣的,非常有用的,虽然有很多要谈论他们的语法和功能,相当容易理解的正确的文章学习。
+因此,我们让它 - 功能是有趣的,非常有用的,虽然有很多要谈论他们的语法和功能,相当容易理解的正确的文章学习。
如果您有什么不明白的地方,可以再通读一遍,或者联系我们寻求帮助。
@@ -154,7 +154,7 @@参见
- Functions in-depth — 详细介绍更多高级功能相关信息的指南。
-- Callback functions in JavaScript — 一个常见的JavaScript模式是把一个函数传递给另一个函数作为参数,然后在第一个函数中调用它。这有点超出了这门课的范围,但值得学习很久。
+- Callback functions in JavaScript — 一个常见的 JavaScript 模式是把一个函数传递给另一个函数作为参数,然后在第一个函数中调用它。这有点超出了这门课的范围,但值得学习很久。
{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Build_your_own_function","Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}
diff --git a/files/zh-cn/learn/javascript/client-side_web_apis/client-side_storage/index.html b/files/zh-cn/learn/javascript/client-side_web_apis/client-side_storage/index.html index 14325fa3c3ce9c..4f482e85b6a092 100644 --- a/files/zh-cn/learn/javascript/client-side_web_apis/client-side_storage/index.html +++ b/files/zh-cn/learn/javascript/client-side_web_apis/client-side_storage/index.html @@ -16,7 +16,7 @@ -现代web浏览器提供了很多在用户电脑web客户端存放数据的方法 — 只要用户的允许 — 可以在它需要的时候被重新获得。这样能让你存留的数据长时间保存, 保存站点和文档在离线情况下使用, 保留你对其站点的个性化配置等等。本篇文章只解释它们工作的一些很基础的部分。
+现代 web 浏览器提供了很多在用户电脑 web 客户端存放数据的方法 — 只要用户的允许 — 可以在它需要的时候被重新获得。这样能让你存留的数据长时间保存,保存站点和文档在离线情况下使用,保留你对其站点的个性化配置等等。本篇文章只解释它们工作的一些很基础的部分。
@@ -31,23 +31,23 @@
-客户端存储?
+客户端存储?
-在其他的MDN学习中我们已经讨论过 静态网站(static sites) 和动态网站( dynamic sites)的区别。 大多数现代的web站点是动态的— 它们在服务端使用各种类型的数据库来存储数据(服务端存储), 之后通过运行服务端( server-side) 代码来重新获取需要的数据,把其数据插入到静态页面的模板中,并且生成出HTML渲染到用户浏览上。
+在其他的 MDN 学习中我们已经讨论过 静态网站(static sites) 和动态网站( dynamic sites)的区别。 大多数现代的 web 站点是动态的— 它们在服务端使用各种类型的数据库来存储数据 (服务端存储), 之后通过运行服务端( server-side)代码来重新获取需要的数据,把其数据插入到静态页面的模板中,并且生成出 HTML 渲染到用户浏览上。
客户端存储以相同的原理工作,但是在使用上有一些不同。它是由 JavaScript APIs 组成的因此允许你在客户端存储数据 (比如在用户的机器上),而且可以在需要的时候重新取得需要的数据。这有很多明显的用处,比如:
- 个性化网站偏好(比如显示一个用户选择的窗口小部件,颜色主题,或者字体)。
-- 保存之前的站点行为 (比如从先前的session中获取购物车中的内容, 记住用户是否之前已经登陆过)。
+- 保存之前的站点行为 (比如从先前的 session 中获取购物车中的内容, 记住用户是否之前已经登陆过)。
- 本地化保存数据和静态资源可以使一个站点更快(至少让资源变少)的下载, 甚至可以在网络失去链接的时候变得暂时可用。
-- 保存web已经生产的文档可以在离线状态下访问。
+- 保存 web 已经生产的文档可以在离线状态下访问。
通常客户端和服务端存储是结合在一起使用的。例如,你可以从数据库中下载一个由网络游戏或音乐播放器应用程序使用的音乐文件,将它们存储在客户端数据库中,并按需要播放它们。用户只需下载音乐文件一次——在随后的访问中,它们将从数据库中检索。
-注意:使用客户端存储 API 可以存储的数据量是有限的(可能是每个API单独的和累积的总量);具体的数量限制取决于浏览器,也可能基于用户设置。有关更多信息,获取更多信息,请参考浏览器存储限制和清理标准。
+注意:使用客户端存储 API 可以存储的数据量是有限的(可能是每个 API 单独的和累积的总量);具体的数量限制取决于浏览器,也可能基于用户设置。有关更多信息,获取更多信息,请参考浏览器存储限制和清理标准。
传统方法:cookies
@@ -57,11 +57,11 @@传统方法:cookies
-由于这些原因,我们不会在本文中教你如何使用cookie。毕竟它过时、存在各种安全问题,而且无法存储复杂数据,而且有更好的、更现代的方法可以在用户的计算机上存储种类更广泛的数据。
+
- cookie的唯一优势是它们得到了非常旧的浏览器的支持,所以如果您的项目需要支持已经过时的浏览器(比如 Internet Explorer 8 或更早的浏览器),cookie可能仍然有用,但是对于大多数项目(很明显不包括本站)来说,您不需要再使用它们了。其实cookie也没什么好说的,document.cookie
一把梭就完事了。由于这些原因,我们不会在本文中教你如何使用 cookie。毕竟它过时、存在各种安全问题,而且无法存储复杂数据,而且有更好的、更现代的方法可以在用户的计算机上存储种类更广泛的数据。
+ cookie 的唯一优势是它们得到了非常旧的浏览器的支持,所以如果您的项目需要支持已经过时的浏览器(比如 Internet Explorer 8 或更早的浏览器),cookie 可能仍然有用,但是对于大多数项目(很明显不包括本站)来说,您不需要再使用它们了。其实 cookie 也没什么好说的,document.cookie
一把梭就完事了。-为什么仍然有新创建的站点使用 cookies?这主要是因为开发人员的习惯,使用了仍然使用cookies的旧库,以及存在许多web站点,提供了过时的参考和培训材料来学习如何存储数据。
+为什么仍然有新创建的站点使用 cookies?这主要是因为开发人员的习惯,使用了仍然使用 cookies 的旧库,以及存在许多 web 站点,提供了过时的参考和培训材料来学习如何存储数据。
新流派:Web Storage 和 IndexedDB
@@ -77,7 +77,7 @@新流派:Web Storage 和 Index
未来:Cache API
-一些现代浏览器支持新的 {{domxref("Cache")}} API。这个API是为存储特定HTTP请求的响应文件而设计的,它对于像存储离线网站文件这样的事情非常有用,这样网站就可以在没有网络连接的情况下使用。缓存通常与 Service Worker API 组合使用,尽管不一定非要这么做。
+一些现代浏览器支持新的 {{domxref("Cache")}} API。这个 API 是为存储特定 HTTP 请求的响应文件而设计的,它对于像存储离线网站文件这样的事情非常有用,这样网站就可以在没有网络连接的情况下使用。缓存通常与 Service Worker API 组合使用,尽管不一定非要这么做。
Cache 和 Service Workers 的使用是一个高级主题,我们不会在本文中详细讨论它,尽管我们将在下面的 离线文件存储 一节中展示一个简单的例子。存储简单数据 — web storage
@@ -96,15 +96,15 @@基本语法
打开你浏览器开发者工具的 JavaScript 控制台。
- -
你所有的 web storage 数据都包含在浏览器内两个类似于对象的结构中: {{domxref("Window.sessionStorage", "sessionStorage")}} 和 {{domxref("Window.localStorage", "localStorage")}}。 第一种方法,只要浏览器开着,数据就会一直保存 (关闭浏览器时数据会丢失) ,而第二种会一直保存数据,甚至到浏览器关闭又开启后也是这样。我们将在本文中使用第二种方法,因为它通常更有用。
+你所有的 web storage 数据都包含在浏览器内两个类似于对象的结构中: {{domxref("Window.sessionStorage", "sessionStorage")}} 和 {{domxref("Window.localStorage", "localStorage")}}。第一种方法,只要浏览器开着,数据就会一直保存 (关闭浏览器时数据会丢失) ,而第二种会一直保存数据,甚至到浏览器关闭又开启后也是这样。我们将在本文中使用第二种方法,因为它通常更有用。
- -
{{domxref("Storage.setItem()")}} 方法允许您在存储中保存一个数据项——它接受两个参数:数据项的名字及其值。试着把它输入到你的JavaScript控制台(如果你愿意的话,可以把它的值改为你自己的名字!)
+{{domxref("Storage.setItem()")}} 方法允许您在存储中保存一个数据项——它接受两个参数:数据项的名字及其值。试着把它输入到你的 JavaScript 控制台(如果你愿意的话,可以把它的值改为你自己的名字!)
localStorage.setItem('name','Chris');- -
{{domxref("Storage.getItem()")}} 方法接受一个参数——你想要检索的数据项的名称——并返回数据项的值。现在将这些代码输入到你的JavaScript控制台:
+{{domxref("Storage.getItem()")}} 方法接受一个参数——你想要检索的数据项的名称——并返回数据项的值。现在将这些代码输入到你的 JavaScript 控制台:
var myName = localStorage.getItem('name'); myName@@ -112,7 +112,7 @@基本语法
在输入第二行时,您应该会看到
myName
变量现在包含name
数据项的值。- -
-{{domxref("Storage.removeItem()")}} 方法接受一个参数——你想要删除的数据项的名称——并从 web storage 中删除该数据项。在您的JavaScript控制台中输入以下几行:
+{{domxref("Storage.removeItem()")}} 方法接受一个参数——你想要删除的数据项的名称——并从 web storage 中删除该数据项。在您的 JavaScript 控制台中输入以下几行:
localStorage.removeItem('name'); var myName = localStorage.getItem('name'); @@ -122,9 +122,9 @@基本语法
数据会一直存在!
+数据会一直存在!
-web storage 的一个关键特性是,数据在不同页面加载时都存在(甚至是当浏览器关闭后,对localStorage的而言)。让我们来看看这个:
+web storage 的一个关键特性是,数据在不同页面加载时都存在(甚至是当浏览器关闭后,对 localStorage 的而言)。让我们来看看这个:
-
- @@ -154,13 +154,13 @@
数据会一直存在!
为每个域名分离储存
-每个域都有一个单独的数据存储区(每个单独的网址都在浏览器中加载). 你 会看到,如果你加载两个网站(例如google.com和amazon.com)并尝试将某个项目存储在一个网站上,该数据项将无法从另一个网站获取。
+每个域都有一个单独的数据存储区 (每个单独的网址都在浏览器中加载). 你 会看到,如果你加载两个网站(例如 google.com 和 amazon.com)并尝试将某个项目存储在一个网站上,该数据项将无法从另一个网站获取。
这是有道理的 - 你可以想象如果网站能够查看彼此的数据,就会出现安全问题!
更复杂的例子
-让我们通过编写一个简单的工作示例来应用这些新发现的知识,让你了解如何使用网络存储。我们的示例将允许你输入一个名称,然后该页面将刷新,以提供个性化问候。这种状态也会页面/浏览器重新加载期间保持,因为这个名称存储在Web Storage 中。
+让我们通过编写一个简单的工作示例来应用这些新发现的知识,让你了解如何使用网络存储。我们的示例将允许你输入一个名称,然后该页面将刷新,以提供个性化问候。这种状态也会页面/浏览器重新加载期间保持,因为这个名称存储在 Web Storage 中。
你可以在 personal-greeting.html 中找到示例文件 —— 这包含一个具有标题,内容和页脚,以及用于输入您的姓名的表单的简单网站。
@@ -173,10 +173,10 @@更复杂的例子
首先,在您的计算机上的新目录中创建一个 personal-greeting.html 文件的副本。
- -
接下来,请注意我们的HTML如何引用一个名为
+index.js
的 JavaScript 文件(请参见第40行)。我们需要创建它并将 JavaScript 代码写入其中。在与HTML文件相同的目录中创建一个index.js
文件。接下来,请注意我们的 HTML 如何引用一个名为
index.js
的 JavaScript 文件(请参见第 40 行)。我们需要创建它并将 JavaScript 代码写入其中。在与 HTML 文件相同的目录中创建一个index.js
文件。- -
我们首先创建对所有需要在此示例中操作的HTML功能的引用 - 我们将它们全部创建为常量,因为这些引用在应用程序的生命周期中不需要更改。将以下几行添加到你的 JavaScript 文件中:
+我们首先创建对所有需要在此示例中操作的 HTML 功能的引用 - 我们将它们全部创建为常量,因为这些引用在应用程序的生命周期中不需要更改。将以下几行添加到你的 JavaScript 文件中:
// 创建所需的常量 const rememberDiv = document.querySelector('.remember'); @@ -222,7 +222,7 @@更复杂的例子
});- -
现在是时候定义
+nameDisplayCheck()
函数本身了。在这里,我们通过使用localStorage.getItem('name')
作为测试条件来检查name 数据项是否已经存储在Web Storage 中。如果它已被存储,则该调用的返回值为true
; 如果没有,它会是false
。如果是true
,我们会显示个性化问候语,显示表格的“forget”部分,并隐藏表格的“Say hello”部分。如果是false
,我们会显示一个通用问候语,并做相反的事。再次将下面的代码添到底部:现在是时候定义
nameDisplayCheck()
函数本身了。在这里,我们通过使用localStorage.getItem('name')
作为测试条件来检查 name 数据项是否已经存储在 Web Storage 中。如果它已被存储,则该调用的返回值为true
; 如果没有,它会是false
。如果是true
,我们会显示个性化问候语,显示表格的“forget”部分,并隐藏表格的“Say hello”部分。如果是false
,我们会显示一个通用问候语,并做相反的事。再次将下面的代码添到底部:// define the nameDisplayCheck() function function nameDisplayCheck() { @@ -252,7 +252,7 @@更复杂的例子
你的例子完成了 - 做得好!现在剩下的就是保存你的代码并在浏览器中测试你的HTML页面。你可以在这里看到我们的完成版本并在线运行。
+你的例子完成了 - 做得好!现在剩下的就是保存你的代码并在浏览器中测试你的 HTML 页面。你可以在这里看到我们的完成版本并在线运行。
注意: 在 Using the Web Storage API 中还有一个稍微复杂点儿的示例。
@@ -264,27 +264,27 @@更复杂的例子
存储复杂数据 — IndexedDB
-IndexedDB API(有时简称 IDB )是可以在浏览器中访问的一个完整的数据库系统,在这里,你可以存储复杂的关系数据。其种类不限于像字符串和数字这样的简单值。你可以在一个IndexedDB中存储视频,图像和许多其他的内容。
+IndexedDB API(有时简称 IDB)是可以在浏览器中访问的一个完整的数据库系统,在这里,你可以存储复杂的关系数据。其种类不限于像字符串和数字这样的简单值。你可以在一个 IndexedDB 中存储视频,图像和许多其他的内容。
-但是,这确实是有代价的:使用IndexedDB要比Web Storage API复杂得多。在本节中,我们仅仅只能浅尝辄止地一提它的能力,不过我们会给你足够基础知识以帮助你开始。
+但是,这确实是有代价的:使用 IndexedDB 要比 Web Storage API 复杂得多。在本节中,我们仅仅只能浅尝辄止地一提它的能力,不过我们会给你足够基础知识以帮助你开始。
通过一个笔记存储示例演示
-在这里,我们将向您介绍一个示例,该示例允许您在浏览器中存储笔记并随时查看和删除它们,在我们进行时,我们将解释IDB的最基本部分并让您自己构建注释。
+在这里,我们将向您介绍一个示例,该示例允许您在浏览器中存储笔记并随时查看和删除它们,在我们进行时,我们将解释 IDB 的最基本部分并让您自己构建注释。
这个应用看起来像这样:
-每个笔记都有一个标题和一些正文,每个都可以单独编辑。我们将在下面通过的JavaScript代码提供详细的注释,以帮助您了解正在发生的事情。
+每个笔记都有一个标题和一些正文,每个都可以单独编辑。我们将在下面通过的 JavaScript 代码提供详细的注释,以帮助您了解正在发生的事情。
开始
1、首先,将
-index.html
,style.css
, 和index-start.js
文件的本地副本放入本地计算机上的新目录中。2、浏览这些文件。 您将看到HTML非常简单:具有页眉和页脚的网站,以及包含显示注释的位置的主内容区域,以及用于在数据库中输入新注释的表单。 CSS提供了一些简单的样式,使其更清晰。 JavaScript文件包含五个声明的常量,其中包含对将显示注释的 {{htmlelement("ul")}} 元素的引用,标题和正文 {{htmlelement("input")}} 元素,{{htmlelement("form")}}本身,以及{{htmlelement("button")}}。
+2、浏览这些文件。 您将看到 HTML 非常简单:具有页眉和页脚的网站,以及包含显示注释的位置的主内容区域,以及用于在数据库中输入新注释的表单。 CSS 提供了一些简单的样式,使其更清晰。 JavaScript 文件包含五个声明的常量,其中包含对将显示注释的 {{htmlelement("ul")}} 元素的引用,标题和正文 {{htmlelement("input")}} 元素,{{htmlelement("form")}}本身,以及{{htmlelement("button")}}。
-3、将您的JavaScript文件重命名为
+index.js
。 您现在可以开始向其添加代码了。3、将您的 JavaScript 文件重命名为
index.js
。 您现在可以开始向其添加代码了。数据库初始设置
@@ -292,7 +292,7 @@数据库初始设置
- -
在常量声明下,加入这几行:
+在常量声明下,加入这几行:
// Create an instance of a db object for us to store the open database in let db;@@ -306,7 +306,7 @@数据库初始设置
}; -我们将把所有的后续代码写在这个
+window.onload
事件处理函数内,这个函数将在window的{{event("load")}}事件被触发时调用,为了确保我们没有在应用完整加载前试图使用IndexedDB功能(如果我们不这么做,它会失败)。我们将把所有的后续代码写在这个
window.onload
事件处理函数内,这个函数将在 window 的{{event("load")}}事件被触发时调用,为了确保我们没有在应用完整加载前试图使用 IndexedDB 功能(如果我们不这么做,它会失败)。在
@@ -315,9 +315,9 @@window.onload
处理程序内,添加以下内容:数据库初始设置
// (see onupgradeneeded below) let request = window.indexedDB.open('notes', 1); -此行创建一个
+request
变量,目的是打开notes
数据库的1
版本。如果notes
数据库不存在,则后续代码将为您创建。您将在IndexedDB中经常看到此请求模式。数据库操作需要时间。您不希望在等待结果时挂起浏览器,因此数据库操作是异步的,这意味着它们不会立即发生,而是在将来的某个时刻发生,并且在完成后会收到通知。此行创建一个
-request
变量,目的是打开notes
数据库的1
版本。如果notes
数据库不存在,则后续代码将为您创建。您将在 IndexedDB 中经常看到此请求模式。数据库操作需要时间。您不希望在等待结果时挂起浏览器,因此数据库操作是异步的,这意味着它们不会立即发生,而是在将来的某个时刻发生,并且在完成后会收到通知。要在IndexedDB中处理此问题,您需要创建一个请求对象(可以随意命名 - 命名为
+request
,可以表明它的用途)。然后,在请求完成或者失败时,使用事件处理程序来运行代码,您将在下面看到这些代码。要在 IndexedDB 中处理此问题,您需要创建一个请求对象(可以随意命名 - 命名为
request
,可以表明它的用途)。然后,在请求完成或者失败时,使用事件处理程序来运行代码,您将在下面看到这些代码。注意:版本号很重要。如果要升级数据库(例如:更改表结构),则必须使用增加的版本号或者
@@ -343,9 +343,9 @@onupgradeneeded
处理程序内指定的不同模式(请参阅下文)等再次运行代码。在这个简单教程中,我们不讨论数据库升级。数据库初始设置
displayData(); }; -如果系统返回:请求失败,
+request.onerror
将会运行。这将允许你对这个问题做出响应。在我们的简单示例中,只是将消息打印到JavaScript控制台。如果系统返回:请求失败,
-request.onerror
将会运行。这将允许你对这个问题做出响应。在我们的简单示例中,只是将消息打印到 JavaScript 控制台。如果系统返回:请求成功,表明成功打开数据库 ,
+request.onsuccess
将会运行。如果是这种情况,则表示已打开数据库的对象在request.result
属性中变为可用,从而允许我们操作数据库。我们将它存储在db
我们之前创建的变量中供以后使用。我们还运行一个名为displayData()
的自定义函数,它把数据库中的数据显示在<ul>
。我们现在运行它,以便在页面加载时显示数据库中已有的注释。您将在稍后看到此定义。如果系统返回:请求成功,表明成功打开数据库,
@@ -510,8 +510,8 @@request.onsuccess
将会运行。如果是这种情况,则表示已打开数据库的对象在request.result
属性中变为可用,从而允许我们操作数据库。我们将它存储在db
我们之前创建的变量中供以后使用。我们还运行一个名为displayData()
的自定义函数,它把数据库中的数据显示在<ul>
。我们现在运行它,以便在页面加载时显示数据库中已有的注释。您将在稍后看到此定义。显示数据
- 首先,我们清空
<ul>
元素的内容,然后填充更新的内容。如果您不这样做,那么每次更新时都会添加大量重复内容。- 接下来,我们
notes
使用IDBDatabase.transaction()
和IDBTransaction.objectStore()
我们一样得到对象存储的引用addData()
,除了这里我们将它们链接在一行中。- 下一步是使用
-IDBObjectStore.openCursor()
方法打开对游标的请求 - 这是一个可用于迭代对象存储中的记录的构造。我们将一个onsuccess
处理程序链接到该行的末尾以使代码更简洁 - 当成功返回游标时,运行处理程序。- 我们
-IDBCursor
使用let 获取对游标本身(对象)的引用cursor = e.target.result
。- 接下来,我们检查光标是否包含来自数据存储区(
+if(cursor){ ... }
)的记录- 如果是这样,我们创建一个DOM片段,用记录中的数据填充它,然后将其插入页面(<ul>
元素内部)。我们还包括一个删除按钮,当单击该按钮时,将通过运行该deleteItem()
功能删除该注释,我们将在下一节中查看。- 我们
+IDBCursor
使用 let 获取对游标本身(对象)的引用cursor = e.target.result
。- 接下来,我们检查光标是否包含来自数据存储区(
if(cursor){ ... }
)的记录 - 如果是这样,我们创建一个 DOM 片段,用记录中的数据填充它,然后将其插入页面(<ul>
元素内部)。我们还包括一个删除按钮,当单击该按钮时,将通过运行该deleteItem()
功能删除该注释,我们将在下一节中查看。- 在
if
块结束时,我们使用该IDBCursor.continue()
方法将光标前进到数据存储区中的下一条记录,然后if
再次运行块的内容。如果有另一个要迭代的记录,这会导致它被插入到页面中,然后continue()
再次运行,依此类推。- 当没有更多记录要迭代时,
@@ -549,9 +549,9 @@cursor
将返回undefined
,因此else
块将运行而不是if
块。此块检查是否有任何注释被插入<ul>
- 如果没有,它会插入一条消息,说没有存储注释。删除一条笔记
}-
- 第一部分可以使用一些解释 - 我们检索要删除
-Number(e.target.parentNode.getAttribute('data-note-id'))
的记录的ID - 回想一下记录的ID是在第一次显示时保存在data-note-id
属性中的<li>
。但是,我们需要通过全局内置的Number()对象传递属性,因为它当前是一个字符串,否则将无法被数据库识别。- 然后,我们使用我们之前看到的相同模式获取对对象存储的引用,并使用该
-IDBObjectStore.delete()
方法从数据库中删除记录,并将ID传递给它。- 当数据库事务完成后,我们
+<li>
从DOM中删除注释,然后再次检查以查看它是否<ul>
为空,并根据需要插入注释。- 第一部分可以使用一些解释 - 我们检索要删除
+Number(e.target.parentNode.getAttribute('data-note-id'))
的记录的 ID - 回想一下记录的 ID 是在第一次显示时保存在data-note-id
属性中的<li>
。但是,我们需要通过全局内置的Number()对象传递属性,因为它当前是一个字符串,否则将无法被数据库识别。- 然后,我们使用我们之前看到的相同模式获取对对象存储的引用,并使用该
+IDBObjectStore.delete()
方法从数据库中删除记录,并将 ID 传递给它。- 当数据库事务完成后,我们
<li>
从 DOM 中删除注释,然后再次检查以查看它是否<ul>
为空,并根据需要插入注释。就是这样了!你的例子现在应该有效。
@@ -560,15 +560,15 @@删除一条笔记
通过 IndexedDB 存储复杂数据
-如上所述,IndexedDB可用于存储不仅仅是简单的文本字符串。您可以存储任何您想要的东西,包括复杂的对象,如视频或图像blob。并且它比任何其他类型的数据更难实现。
+如上所述,IndexedDB 可用于存储不仅仅是简单的文本字符串。您可以存储任何您想要的东西,包括复杂的对象,如视频或图像 blob。并且它比任何其他类型的数据更难实现。
-为了演示如何操作,我们编写了另一个名为IndexedDB视频存储的示例(请参阅此处也可以在此处运行)。首次运行示例时,它会从网络下载所有视频,将它们存储在IndexedDB数据库中,然后在UI内部
+<video>
元素中显示视频。第二次运行它时,它会在数据库中找到视频并从那里获取它们而不是显示它们 - 这使得后续加载更快,占用空间更少。为了演示如何操作,我们编写了另一个名为IndexedDB 视频存储的示例(请参阅此处也可以在此处运行)。首次运行示例时,它会从网络下载所有视频,将它们存储在 IndexedDB 数据库中,然后在 UI 内部
<video>
元素中显示视频。第二次运行它时,它会在数据库中找到视频并从那里获取它们而不是显示它们 - 这使得后续加载更快,占用空间更少。让我们来看看这个例子中最有趣的部分。我们不会全部看 - 它的很多内容与上一个示例类似,代码注释得很好。
- -
对于这个简单的例子,我们已经存储了视频的名称以获取数组opf对象:
+对于这个简单的例子,我们已经存储了视频的名称以获取数组 opf 对象:
const videos = [ { 'name' : 'crystal' }, @@ -582,7 +582,7 @@通过 IndexedDB 存储复杂数据
首先,一旦数据库成功打开,我们就运行一个
-init()
函数。这会遍历不同的视频名称,尝试加载由videos
数据库中的每个名称标识的记录。如果在数据库中找到每个视频(通过查看
+request.result
评估是否容易检查true
- 如果记录不存在,那么undefined
),视频文件(存储为blob)和视频名称将直接传递给displayVideo()
函数以放置它们在用户界面中。如果没有,视频名称将传递给fetchVideoFromNetwork()
函数...你猜对了 - 从网络中获取视频。如果在数据库中找到每个视频(通过查看
request.result
评估是否容易检查true
- 如果记录不存在,那么undefined
),视频文件(存储为 blob)和视频名称将直接传递给displayVideo()
函数以放置它们在用户界面中。如果没有,视频名称将传递给fetchVideoFromNetwork()
函数...你猜对了 - 从网络中获取视频。function init() { // Loop through the video names one by one @@ -605,11 +605,11 @@通过 IndexedDB 存储复杂数据 }
- -
以下片段是从内部
+fetchVideoFromNetwork()
获取的 - 这里我们使用两个单独的WindowOrWorkerGlobalScope.fetch()
请求获取视频的MP4和WebM版本。然后,我们使用该Body.blob()
方法将每个响应的主体提取为blob,为我们提供可以在以后存储和显示的视频的对象表示。以下片段是从内部
-fetchVideoFromNetwork()
获取的 - 这里我们使用两个单独的WindowOrWorkerGlobalScope.fetch()
请求获取视频的 MP4 和 WebM 版本。然后,我们使用该Body.blob()
方法将每个响应的主体提取为 blob,为我们提供可以在以后存储和显示的视频的对象表示。我们在这里遇到了一个问题 - 这两个请求都是异步的,但我们只想在两个promises都满足时尝试显示或存储视频。幸运的是,有一种处理这种问题的内置方法 -
+Promise.all()
。这需要一个参数 - 引用您要检查放置在数组中的履行的所有单个承诺 - 并且本身是基于承诺的。我们在这里遇到了一个问题 - 这两个请求都是异步的,但我们只想在两个 promises 都满足时尝试显示或存储视频。幸运的是,有一种处理这种问题的内置方法 -
-Promise.all()
。这需要一个参数 - 引用您要检查放置在数组中的履行的所有单个承诺 - 并且本身是基于承诺的。当所有这些承诺都履行完毕时,
+all()
承诺将通过包含所有个人履行价值的数组来实现。在all()
块中,您可以看到我们displayVideo()
之前调用函数,就像在UI中显示视频一样,然后我们也调用storeVideo()
函数将这些视频存储在数据库中。当所有这些承诺都履行完毕时,
all()
承诺将通过包含所有个人履行价值的数组来实现。在all()
块中,您可以看到我们displayVideo()
之前调用函数,就像在 UI 中显示视频一样,然后我们也调用storeVideo()
函数将这些视频存储在数据库中。let mp4Blob = fetch('videos/' + video.name + '.mp4').then(response => response.blob() @@ -647,7 +647,7 @@通过 IndexedDB 存储复杂数据 };
- -
-最后但并非最不重要的是,我们
+displayVideo()
创建了在UI中插入视频然后将它们附加到页面所需的DOM元素。最有趣的部分如下所示 - 要在<video>
元素中实际显示我们的视频blob ,我们需要使用该URL.createObjectURL()
方法创建对象URL(指向存储在内存中的视频blob的内部URL)。完成后,我们可以将对象URL设置为<source>
元素src
属性的值,并且它可以正常工作。最后但并非最不重要的是,我们
displayVideo()
创建了在 UI 中插入视频然后将它们附加到页面所需的 DOM 元素。最有趣的部分如下所示 - 要在<video>
元素中实际显示我们的视频 blob ,我们需要使用该URL.createObjectURL()
方法创建对象 URL(指向存储在内存中的视频 blob 的内部 URL)。完成后,我们可以将对象 URL 设置为<source>
元素src
属性的值,并且它可以正常工作。function displayVideo(mp4Blob, webmBlob, title) { // Create object URLs out of the blobs @@ -672,31 +672,31 @@通过 IndexedDB 存储复杂数据
离线文件存储
-上面的示例已经说明了如何创建一个将大型资产存储在IndexedDB数据库中的应用程序,从而无需多次下载它们。这已经是对用户体验的一个很大的改进,但仍然有一件事 - 每次访问网站时仍然需要下载主要的HTML,CSS和JavaScript文件,这意味着当没有网络连接时,它将无法工作。
+上面的示例已经说明了如何创建一个将大型资产存储在 IndexedDB 数据库中的应用程序,从而无需多次下载它们。这已经是对用户体验的一个很大的改进,但仍然有一件事 - 每次访问网站时仍然需要下载主要的 HTML,CSS 和 JavaScript 文件,这意味着当没有网络连接时,它将无法工作。
-这就是服务工作者和密切相关的Cache API的用武之地。
+这就是服务工作者和密切相关的Cache API 的用武之地。
-服务工作者是一个JavaScript文件,简单地说,它是在浏览器访问时针对特定来源(网站或某个域的网站的一部分)进行注册的。注册后,它可以控制该来源的可用页面。它通过坐在加载的页面和网络之间以及拦截针对该来源的网络请求来实现这一点。
+服务工作者是一个 JavaScript 文件,简单地说,它是在浏览器访问时针对特定来源(网站或某个域的网站的一部分)进行注册的。注册后,它可以控制该来源的可用页面。它通过坐在加载的页面和网络之间以及拦截针对该来源的网络请求来实现这一点。
当它拦截一个请求时,它可以做任何你想做的事情(参见用例思路),但经典的例子是离线保存网络响应,然后提供响应请求而不是来自网络的响应。实际上,它允许您使网站完全脱机工作。
-Cache API是另一种客户端存储机制,略有不同 - 它旨在保存HTTP响应,因此与服务工作者一起工作得非常好。
+Cache API 是另一种客户端存储机制,略有不同 - 它旨在保存 HTTP 响应,因此与服务工作者一起工作得非常好。
-注意:现在大多数现代浏览器都支持服务工作者和缓存。在撰写本文时,Safari仍在忙着实施它,但它应该很快就会存在。
+注意:现在大多数现代浏览器都支持服务工作者和缓存。在撰写本文时,Safari 仍在忙着实施它,但它应该很快就会存在。
一个 service worker 例子
-让我们看一个例子,让你对这可能是什么样子有所了解。我们已经创建了另一个版本的视频存储示例,我们在上一节中看到了 - 这个功能完全相同,只是它还通过服务工作者将Cache,CSS和JavaScript保存在Cache API中,允许示例脱机运行!
+让我们看一个例子,让你对这可能是什么样子有所了解。我们已经创建了另一个版本的视频存储示例,我们在上一节中看到了 - 这个功能完全相同,只是它还通过服务工作者将 Cache,CSS 和 JavaScript 保存在 Cache API 中,允许示例脱机运行!
-请参阅IndexedDB视频存储,其中服务工作者正在运行,并且还可以查看源代码。
+请参阅IndexedDB 视频存储,其中服务工作者正在运行,并且还可以查看源代码。
注册服务工作者
-首先要注意的是,在主JavaScript文件中放置了一些额外的代码(请参阅index.js)。首先,我们进行特征检测测试,以查看
+serviceWorker
该Navigator
对象中是否有该成员。如果返回true,那么我们知道至少支持服务工作者的基础知识。在这里,我们使用该ServiceWorkerContainer.register()
方法将sw.js
文件中包含的服务工作者注册到它所驻留的源,因此它可以控制与它或子目录相同的目录中的页面。当其承诺履行时,服务人员被视为已注册。首先要注意的是,在主 JavaScript 文件中放置了一些额外的代码(请参阅index.js)。首先,我们进行特征检测测试,以查看
serviceWorker
该Navigator
对象中是否有该成员。如果返回 true,那么我们知道至少支持服务工作者的基础知识。在这里,我们使用该ServiceWorkerContainer.register()
方法将sw.js
文件中包含的服务工作者注册到它所驻留的源,因此它可以控制与它或子目录相同的目录中的页面。当其承诺履行时,服务人员被视为已注册。// Register service worker to control making site work offline @@ -707,7 +707,7 @@注册服务工作者
}-注意:
+sw.js
文件的给定路径是相对于站点源的,而不是包含代码的JavaScript文件。服务人员在https://mdn.github.io/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/sw.js
。原点是https://mdn.github.io
,因此给定的路径必须是/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/sw.js
。如果您想在自己的服务器上托管此示例,则必须相应地更改此示例。这是相当令人困惑的,但出于安全原因,它必须以这种方式工作。注意:
sw.js
文件的给定路径是相对于站点源的,而不是包含代码的 JavaScript 文件。服务人员在https://mdn.github.io/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/sw.js
。原点是https://mdn.github.io
,因此给定的路径必须是/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/sw.js
。如果您想在自己的服务器上托管此示例,则必须相应地更改此示例。这是相当令人困惑的,但出于安全原因,它必须以这种方式工作。安装 service worker
@@ -716,9 +716,9 @@安装 service worker
让我们看一下sw.js文件(服务工作者)中的一个例子。您将看到安装侦听器已注册
-self
。此self
关键字是一种从服务工作文件内部引用服务工作者的全局范围的方法。在
+install
处理程序内部, 我们使用ExtendableEvent.waitUntil()
事件对象上可用的方法来表示浏览器不应该完成服务工作者的安装,直到其中的promise成功完成。在
-install
处理程序内部, 我们使用ExtendableEvent.waitUntil()
事件对象上可用的方法来表示浏览器不应该完成服务工作者的安装,直到其中的 promise 成功完成。这是我们在运行中看到Cache API的地方。我们使用该
+CacheStorage.open()
方法打开一个可以存储响应的新缓存对象(类似于IndexedDB对象存储)。此承诺通过Cache
表示video-store
缓存的对象来实现。然后,我们使用该Cache.addAll()
方法获取一系列资产并将其响应添加到缓存中。这是我们在运行中看到 Cache API 的地方。我们使用该
CacheStorage.open()
方法打开一个可以存储响应的新缓存对象(类似于 IndexedDB 对象存储)。此承诺通过Cache
表示video-store
缓存的对象来实现。然后,我们使用该Cache.addAll()
方法获取一系列资产并将其响应添加到缓存中。self.addEventListener('install', function(e) { e.waitUntil( @@ -737,13 +737,13 @@-安装 service worker
响应未来的请求
-在我们的HTML页面上注册并安装了服务工作者,并且所有相关资产都添加到我们的缓存中,我们几乎准备好了。还有一件事要做,写一些代码来响应进一步的网络请求。
+在我们的 HTML 页面上注册并安装了服务工作者,并且所有相关资产都添加到我们的缓存中,我们几乎准备好了。还有一件事要做,写一些代码来响应进一步的网络请求。
这就是第二位代码的
-sw.js
作用。我们向服务工作者全局范围添加另一个侦听器,该范围在fetch
引发事件时运行处理函数。只要浏览器在服务工作者注册的目录中请求资产,就会发生这种情况。在处理程序内部,我们首先记录所请求资产的URL。然后,我们使用该
+FetchEvent.respondWith()
方法为请求提供自定义响应。在处理程序内部,我们首先记录所请求资产的 URL。然后,我们使用该
-FetchEvent.respondWith()
方法为请求提供自定义响应。在这个块中,我们
+CacheStorage.match()
用来检查是否可以在任何缓存中找到匹配的请求(即匹配URL)。如果未找到匹配,或者undefined
如果未找到匹配,则此承诺将满足匹配的响应。在这个块中,我们
CacheStorage.match()
用来检查是否可以在任何缓存中找到匹配的请求(即匹配 URL)。如果未找到匹配,或者undefined
如果未找到匹配,则此承诺将满足匹配的响应。如果找到匹配项,我们只需将其作为自定义响应返回。如果没有,我们从网络中获取()响应并返回该响应。
@@ -756,7 +756,7 @@响应未来的请求
); });这就是我们简单的服务工作者。您可以使用它们进行更多的负载 - 有关详细信息,请参阅服务工作者手册。感谢Paul Kinlan在他的文章中添加服务工作者和离线到您的Web应用程序,这启发了这个简单的例子。
+这就是我们简单的服务工作者。您可以使用它们进行更多的负载 - 有关详细信息,请参阅服务工作者手册。感谢 Paul Kinlan 在他的文章中添加服务工作者和离线到您的 Web 应用程序,这启发了这个简单的例子。
测试离线示例
@@ -764,11 +764,11 @@测试离线示例
-
- 尝试拔掉网络连接/关闭Wifi。
-- 如果您使用的是Firefox,请选择文件>脱机工作。
-- 转到devtools,然后选择Application> Service Workers,如果您使用的是Chrome ,请选中Offline选中。
+- 如果您使用的是 Firefox,请选择文件>脱机工作。
+- 转到 devtools,然后选择Application> Service Workers,如果您使用的是 Chrome ,请选中Offline选中。
如果再次刷新示例页面,您仍应该看到它加载得很好。所有内容都是脱机存储的 - 缓存中的页面资源以及IndexedDB数据库中的视频。
+如果再次刷新示例页面,您仍应该看到它加载得很好。所有内容都是脱机存储的 - 缓存中的页面资源以及 IndexedDB 数据库中的视频。
总结
@@ -788,9 +788,9 @@相关链接
在本单元中
-
- 网页端 API介绍
+- 网页端 API 介绍
- Manipulating documents
-- 从服务器获取数据(fetch)
+- 从服务器获取数据 (fetch)
- 第三方 API
- Drawing graphics
- 视频和音频 API
diff --git a/files/zh-cn/learn/javascript/client-side_web_apis/drawing_graphics/index.html b/files/zh-cn/learn/javascript/client-side_web_apis/drawing_graphics/index.html index 5bc6c7e125d426..08b4c192121ad8 100644 --- a/files/zh-cn/learn/javascript/client-side_web_apis/drawing_graphics/index.html +++ b/files/zh-cn/learn/javascript/client-side_web_apis/drawing_graphics/index.html @@ -15,13 +15,13 @@ ---{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "Learn/JavaScript/Client-side_web_APIs")}}-浏览器包含一些非常强大的图形编程工具,从可缩放矢量图形(Scalable Vector Graphics,简称 SVG)语言到用于在 HTML {{htmlelement("canvas")}} 元素上绘制图形的API(参阅 Canvas API 和 WebGL)。本文对 {{htmlelement("canvas")}} 进行介绍,并提供更多的学习资源。
+浏览器包含一些非常强大的图形编程工具,从可缩放矢量图形(Scalable Vector Graphics,简称 SVG)语言到用于在 HTML {{htmlelement("canvas")}} 元素上绘制图形的 API(参阅 Canvas API 和 WebGL)。本文对 {{htmlelement("canvas")}} 进行介绍,并提供更多的学习资源。
-
预备知识: -JavaScript基础(见 JavaScript 第一步,创建 JavaScript 代码块,JavaScript 对象入门),Web API 基础知识。 +JavaScript 基础(见 JavaScript 第一步,创建 JavaScript 代码块,JavaScript 对象入门),Web API 基础知识。 目标: @@ -34,7 +34,7 @@网络图形
我们来讨论 HTML 的 多媒体和嵌入式 模块,早先的网页只有单调的文字,后来才引入了图像,起初是通过 {{htmlelement("img")}} 元素的方式,后来出现了类似于 {{cssxref("background-image")}} 的 CSS 属性和 SVG 图像等方式。
-然而,这还不够好。当你能够使用 CSS 和 JavaScript 让 SVG 矢量图动起来时,位图却依然没有相应的支持。同时 SVG 动画的可用工具也少得可怜。有效地生成动画、游戏画面、3D场景和其他的需求依然没有满足,而这些在诸如 C++ 或者 Java 等底层语言中却司空见惯。
+然而,这还不够好。当你能够使用 CSS 和 JavaScript 让 SVG 矢量图动起来时,位图却依然没有相应的支持。同时 SVG 动画的可用工具也少得可怜。有效地生成动画、游戏画面、3D 场景和其他的需求依然没有满足,而这些在诸如 C++ 或者 Java 等底层语言中却司空见惯。
当浏览器开始支持 HTML 画布元素 {{htmlelement("canvas")}} 和相关的 Canvas API(由苹果公司在 2004 年前后发明,后来其他的浏览器开始跟进)时,形势开始改善。下面你会看到,canvas 提供了许多有用的工具,特别是当捆绑了由网络平台提供的一些其他的 API 时。它们用来生成 2D 动画、游戏画面和数据分析图,以及其他类型的 app。
@@ -46,10 +46,10 @@网络图形
{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/threejs-cube/index.html", '100%', 500)}}
-由于原生的 WebGL 代码非常复杂,本文主要针对 2D 画布。然而,你也可以通过 WebGL介绍页面 找到 WebGL 原生代码的教程,来学习如何更容易地使用 WebGL 库来创建一个 3D 场景。
+由于原生的 WebGL 代码非常复杂,本文主要针对 2D 画布。然而,你也可以通过 WebGL 介绍页面 找到 WebGL 原生代码的教程,来学习如何更容易地使用 WebGL 库来创建一个 3D 场景。
-注:画布的基本功能有良好的跨浏览器支持。但存在例外:IE 8 及以下不支持 2D 画布,IE 11 及以下不支持WebGL。
+注:画布的基本功能有良好的跨浏览器支持。但存在例外:IE 8 及以下不支持 2D 画布,IE 11 及以下不支持 WebGL。
主动学习:开始使用 <canvas>
@@ -74,7 +74,7 @@创建画布并确定尺寸
- -
首先下载 0_canvas_start.html 文件, 用文本编辑器打开。
+首先下载 0_canvas_start.html 文件,用文本编辑器打开。
- -
在 {{htmlelement("body")}} 标签下面填加以下代码。
@@ -133,13 +133,13 @@获取画布
ctx.fillStyle = 'rgb(0, 0, 0)'; ctx.fillRect(0, 0, width, height);-这里我们使用画布的 {{domxref("CanvasRenderingContext2D.fillStyle", "fillStyle")}} 属性(和CSS属性 色值 一致)设置填充色,然后使用 {{domxref("CanvasRenderingContext2D.fillRect", "fillRect")}} 方法绘制一个覆盖整个区域的矩形(前两个参数是矩形左上顶点的坐标,后两个参数是矩形的长宽,现在你知道
+width
和height
的作用了吧)。这里我们使用画布的 {{domxref("CanvasRenderingContext2D.fillStyle", "fillStyle")}} 属性(和 CSS 属性 色值 一致)设置填充色,然后使用 {{domxref("CanvasRenderingContext2D.fillRect", "fillRect")}} 方法绘制一个覆盖整个区域的矩形(前两个参数是矩形左上顶点的坐标,后两个参数是矩形的长宽,现在你知道
width
和height
的作用了吧)。好的,模板已经就位,我们要开始了。
2D 画布基础
-如上文所讲,所有绘画操作都离不开 {{domxref("CanvasRenderingContext2D")}} 对象(这里叫做
+ctx
)。许多操作都需要提供坐标来指示绘图的确切位置。画布左上角的坐标是(0, 0),横坐标(x)轴向右延伸,纵坐标(y)轴向下延伸。如上文所讲,所有绘画操作都离不开 {{domxref("CanvasRenderingContext2D")}} 对象(这里叫做
@@ -151,7 +151,7 @@ctx
)。许多操作都需要提供坐标来指示绘图的确切位置。画布左上角的坐标是 (0, 0),横坐标(x)轴向右延伸,纵坐标(y)轴向下延伸。简单矩形
- -
首先,复制一份刚才创建的画布模板 (如果你没有严格按上述步骤进行,请下载 1_canvas_template.html)。
+首先,复制一份刚才创建的画布模板 (如果你没有严格按上述步骤进行,请下载 1_canvas_template.html)。
然后在 JS 代码末尾添加下面两行:
@@ -345,7 +345,7 @@文本
- {{domxref("CanvasRenderingContext2D.strokeText", "strokeText()")}}:绘制文本外边框(描边)。
-这两个函数有三个基本的参数:需要绘制的文字、文本框(顾名思义,围绕着需要绘制文字的方框)左上顶点的X、Y坐标。
+这两个函数有三个基本的参数:需要绘制的文字、文本框(顾名思义,围绕着需要绘制文字的方框)左上顶点的 X、Y 坐标。
还有一系列帮助控制文本渲染的属性:比如用于指定字体族、字号的 {{domxref("CanvasRenderingContext2D.font", "font")}},它的值和语法与 CSS 的 {{cssxref("font")}} 属性一致。
@@ -378,7 +378,7 @@在画布上绘制图片
同上,下载画布模板(1_canvas_template.html)以绘制新的示例。这里还需要在同一目录下保存一个示例图片文件:firefox.png。
-{{domxref("CanvasRenderingContext2D.drawImage", "drawImage()")}} 方法可将图片绘制在画布上。 最简单的版本需要三个参数:需要渲染的图片、图片左上角的X、Y坐标。
+{{domxref("CanvasRenderingContext2D.drawImage", "drawImage()")}} 方法可将图片绘制在画布上。 最简单的版本需要三个参数:需要渲染的图片、图片左上角的 X、Y 坐标。
将图片源嵌入画布中,代码如下:
@@ -542,7 +542,7 @@动画
我们在代码底部运行了一次
-loop()
函数,它启动了整个循环,绘制了第一帧动画。接着loop()
函数接管了requestAnimationFrame(loop)
的调用工作,即运行下一帧、再下一帧……的动画。请注意每一帧我们都整体清除画布并重新渲染所有内容。(每帧创建一个新球(25 个封顶),然后绘制每个球,更新它们的位置,检查是否撞到了其它球。)向画布中绘制的新图形不能像DOM 元素那样单独操作。你无法再画布中单独操作某一个球,因为只要绘制完毕了,它就是画布的一部分,而不是一个单独的球。你需要擦除再重画,可以将整帧擦除再重画整个画面,也可通过编程选择最小的部分进行擦除和重画。
+请注意每一帧我们都整体清除画布并重新渲染所有内容。(每帧创建一个新球(25 个封顶),然后绘制每个球,更新它们的位置,检查是否撞到了其它球。)向画布中绘制的新图形不能像 DOM 元素那样单独操作。你无法再画布中单独操作某一个球,因为只要绘制完毕了,它就是画布的一部分,而不是一个单独的球。你需要擦除再重画,可以将整帧擦除再重画整个画面,也可通过编程选择最小的部分进行擦除和重画。
优化图形动画是另一个编程主题,需要好多奇技淫巧。这超出我们的讨论范围啦。
@@ -605,7 +605,7 @@一个简单的人物动画
ctx.fillRect(-(width/2), -(height/2), width, height);- -
下一步,我们使用
+drawImage()
(9参数版本)来绘制图形,添加以下代码:下一步,我们使用
drawImage()
(9 参数版本)来绘制图形,添加以下代码:ctx.drawImage(image, (sprite*102), 0, 102, 148, 0+posX, -74, 102, 148);@@ -668,7 +668,7 @@简单的绘图应用
下面来演示一个简单的绘图应用,作为最后一个绘画示例,它将向你展示动画循环如果与用户输入(本例中为鼠标移动)结合起来。我们不会带你一步一步来实现本示例,只对代码中最有趣的部分进行探究。
-示例代码可到GitHub下载:8_canvas_drawing_app.html,也可在线试玩:
+示例代码可到 GitHub 下载:8_canvas_drawing_app.html,也可在线试玩:
{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/loops_animation/8_canvas_drawing_app.html", '100%', 600)}}
@@ -727,7 +727,7 @@使用库
由于 3D 绘图的复杂性,大多数人写代码时会使用第三方 JavaScript 库(比如 Three.js、PlayCanvas 或 Babylon.js)。大多数库的原理都基本类似,提供创建基本的、自定义性状的功能、视图定位摄影和光效、表面纹理覆盖,等等。库负责 与 WebGL 通信,你只需完成更高阶工作。
-接触任何一个库都意味着要学一套全新的API(这里是第三方的版本),但与纯 WebGL 编程都大同小异。
+接触任何一个库都意味着要学一套全新的 API(这里是第三方的版本),但与纯 WebGL 编程都大同小异。
创建魔方
@@ -775,7 +775,7 @@创建魔方
renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); -第一行创建一个新的渲染器,第二行设定渲染器在当前摄影机视角下的尺寸,第三行将渲染好的 {{htmlelement("canvas")}} 对象加入HTML的 {{htmlelement("body")}} 中。现在渲染器绘制的内容将在窗口中显示出来。
+第一行创建一个新的渲染器,第二行设定渲染器在当前摄影机视角下的尺寸,第三行将渲染好的 {{htmlelement("canvas")}} 对象加入 HTML 的 {{htmlelement("body")}} 中。现在渲染器绘制的内容将在窗口中显示出来。
下一步,在画布中创建魔方。把以下代码添加到 JS 文件中:
@@ -801,7 +801,7 @@创建魔方
@@ -856,7 +856,7 @@
- 首先,创建一个全局变量
-cube
,这样就可以在代码任意位置访问我们的魔方。- 然后,创建一个
+TextureLoader
对象,并调用load()
。 这里load()
包含两个参数(其它情况可以有更多参数):需要调用的纹理图(PNG 文件)和纹理加载成功后调用的函数。- 然后,创建一个
TextureLoader
对象,并调用load()
。这里load()
包含两个参数(其它情况可以有更多参数):需要调用的纹理图(PNG 文件)和纹理加载成功后调用的函数。- 函数内部,我们用
texture
对象的属性指明我们要在魔方的每个面渲染 2 × 2 的图片,然后创建一个BoxGeometry
对象和一个MeshLambertMaterial
对象,将两者作为Mesh
的参数来创建我们的魔方。Mesh
一般就需要两个参数:一个几何(形状)和一个素材(形状表面外观)。- 最后,将魔方添加进场景中,调用我们的
draw()
函数开始动画。另请参阅
- Canvas 教程:一个详尽的教程系列,更细致深入地讲解了 2D 画布所需的知识。必读。
- WebGL 教程:纯 WebGL 编程教程系列。
- 用 Three.js 创建一个简单的示例:Three.js 基础教程。我们还提供 PlayCanvas 和 Babylon.js 的基础教程。
-- 游戏开发:MDN web 游戏开发目录页。提供与 2D、3D画布相关的实用教程和技术,可参考“技术”和“教程”菜单项。
+- 游戏开发:MDN web 游戏开发目录页。提供与 2D、3D 画布相关的实用教程和技术,可参考“技术”和“教程”菜单项。
示例
@@ -876,6 +876,6 @@本章目录
- 从服务器获得数据
- 第三方 API
- 绘图
-- 视频API 和 音频 API
+- 视频 API 和 音频 API
- 客户端存储
diff --git a/files/zh-cn/learn/javascript/client-side_web_apis/fetching_data/index.html b/files/zh-cn/learn/javascript/client-side_web_apis/fetching_data/index.html index 9600fbc22136a8..c300840eca4789 100644 --- a/files/zh-cn/learn/javascript/client-side_web_apis/fetching_data/index.html +++ b/files/zh-cn/learn/javascript/client-side_web_apis/fetching_data/index.html @@ -22,46 +22,46 @@{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs")}}-在现代网站和应用中另一个常见的任务是从服务端获取个别数据来更新部分网页而不用加载整个页面。 这看起来是小细节却对网站性能和行为产生巨大的影响。所以我们将在这篇文章介绍概念和技术使它成为可能,例如: XMLHttpRequest 和 Fetch API.
+在现代网站和应用中另一个常见的任务是从服务端获取个别数据来更新部分网页而不用加载整个页面。 这看起来是小细节却对网站性能和行为产生巨大的影响。所以我们将在这篇文章介绍概念和技术使它成为可能,例如:XMLHttpRequest 和 Fetch API.
-
- 先决条件: -JavaScript 基础(查看 第一步, 基础要件, JavaScript对象), 和客户端API基础 +先决条件: +JavaScript 基础 (查看 第一步, 基础要件, JavaScript 对象), 和客户端 API 基础 - 目标: -学会如何从服务器获取数据并使用它更新网页内容. +目标: +学会如何从服务器获取数据并使用它更新网页内容。 这里有什么问题?
+这里有什么问题?
-最初加载页面很简单 -- 你为网站发送一个请求到服务器, 只要没有出错你将会获取资源并显示网页到你的电脑上。
+最初加载页面很简单 -- 你为网站发送一个请求到服务器,只要没有出错你将会获取资源并显示网页到你的电脑上。
这个模型的问题是当你想更新网页的任何部分,例如显示一套新的产品或者加载一个新的页面,你需要再一次加载整个页面。这是非常浪费的并且导致了差的用户体验尤其是现在的页面越来越大且越来越复杂。
-Ajax开始
+Ajax 开始
这导致了创建允许网页请求小块数据(例如 HTML, {{glossary("XML")}}, JSON, 或纯文本) 和 仅在需要时显示它们的技术,从而帮助解决上述问题。
-这是通过使用诸如 {{domxref("XMLHttpRequest")}} 之类的API或者 — 最近以来的 Fetch API 来实现. 这些技术允许网页直接处理对服务器上可用的特定资源的 HTTP 请求,并在显示之前根据需要对结果数据进行格式化。
+这是通过使用诸如 {{domxref("XMLHttpRequest")}} 之类的 API 或者 — 最近以来的 Fetch API 来实现。这些技术允许网页直接处理对服务器上可用的特定资源的 HTTP 请求,并在显示之前根据需要对结果数据进行格式化。
--注意:在早期,这种通用技术被称为Asynchronous JavaScript and XML(Ajax), 因为它倾向于使用{{domxref("XMLHttpRequest")}} 来请求XML数据。 但通常不是这种情况 (你更有可能使用
+XMLHttpRequest
或 Fetch 来请求JSON), 但结果仍然是一样的,术语“Ajax”仍然常用于描述这种技术。注意:在早期,这种通用技术被称为Asynchronous JavaScript and XML(Ajax), 因为它倾向于使用{{domxref("XMLHttpRequest")}} 来请求 XML 数据。 但通常不是这种情况 (你更有可能使用
XMLHttpRequest
或 Fetch 来请求 JSON), 但结果仍然是一样的,术语“Ajax”仍然常用于描述这种技术。Ajax模型包括使用Web API作为代理来更智能地请求数据,而不仅仅是让浏览器重新加载整个页面。让我们来思考这个意义:
+Ajax 模型包括使用 Web API 作为代理来更智能地请求数据,而不仅仅是让浏览器重新加载整个页面。让我们来思考这个意义:
-
- 去你最喜欢的信息丰富的网站之一,如亚马逊,油管,CNN等,并加载它。
-- 现在搜索一些东西,比如一个新产品。 主要内容将会改变,但大部分周围的信息,如页眉,页脚,导航菜单等都将保持不变。
+- 去你最喜欢的信息丰富的网站之一,如亚马逊,油管,CNN 等,并加载它。
+- 现在搜索一些东西,比如一个新产品。主要内容将会改变,但大部分周围的信息,如页眉,页脚,导航菜单等都将保持不变。
这是一件非常好的事情,因为:
@@ -71,28 +71,28 @@Ajax开始
- 每次更新都会下载更少的数据,这意味着更少地浪费带宽。在宽带连接的桌面上这可能不是一个大问题,但是在移动设备和发展中国家没有无处不在的快速互联网服务是一个大问题。
-为了进一步提高速度,有些网站还会在首次请求时将资产和数据存储在用户的计算机上,这意味着在后续访问中,他们将使用本地版本,而不是在首次加载页面时下载新副本。 内容仅在更新后从服务器重新加载。
+为了进一步提高速度,有些网站还会在首次请求时将资产和数据存储在用户的计算机上,这意味着在后续访问中,他们将使用本地版本,而不是在首次加载页面时下载新副本。内容仅在更新后从服务器重新加载。
本文不会涉及这种存储技术。我们稍后会在模块中讨论它。
-基本的Ajax请求
+基本的 Ajax 请求
-让我们看看使用{{domxref("XMLHttpRequest")}} 和 Fetch如何处理这样的请求. 对于这些例子,我们将从几个不同的文本文件中请求数据,并使用它们来填充内容区域。
+让我们看看使用{{domxref("XMLHttpRequest")}} 和 Fetch如何处理这样的请求。对于这些例子,我们将从几个不同的文本文件中请求数据,并使用它们来填充内容区域。
-这一系列文件将作为我们的假数据库; 在真正的应用程序中,我们更可能使用服务器端语言(如PHP,Python或Node)从数据库请求我们的数据。 不过,我们要保持简单,并专注于客户端部分。
+这一系列文件将作为我们的假数据库; 在真正的应用程序中,我们更可能使用服务器端语言(如 PHP,Python 或 Node)从数据库请求我们的数据。不过,我们要保持简单,并专注于客户端部分。
XMLHttpRequest
-+
XMLHttpRequest
(通常缩写为XHR)现在是一个相当古老的技术 - 它是在20世纪90年代后期由微软发明的,并且已经在相当长的时间内跨浏览器进行了标准化。
XMLHttpRequest
(通常缩写为 XHR)现在是一个相当古老的技术 - 它是在 20 世纪 90 年代后期由微软发明的,并且已经在相当长的时间内跨浏览器进行了标准化。-
- -
为例子做些准备, 将 ajax-start.html 和四个文本文件 — verse1.txt, verse2.txt, verse3.txt, verse4.txt — 复制到你计算机上的一个新目录. 在这个例子中,我们将通过XHR在下拉菜单中选择一首诗(您可能会认识 — "如果谷歌翻译可以翻译的话")加载另一首诗。
+为例子做些准备,将 ajax-start.html 和四个文本文件 — verse1.txt, verse2.txt, verse3.txt, verse4.txt — 复制到你计算机上的一个新目录。在这个例子中,我们将通过 XHR 在下拉菜单中选择一首诗(您可能会认识 — "如果谷歌翻译可以翻译的话")加载另一首诗。
- -
在 {{htmlelement("script")}} 的内部, 添加下面的代码. 将 {{htmlelement("select")}} 和 {{htmlelement("pre")}} 元素的引用存储到变量中, 并定义一个 {{domxref("GlobalEventHandlers.onchange","onchange")}} 事件处理函数,可以在select的值改变时, 将其值传递给
+updateDisplay()
函数作为参数。在 {{htmlelement("script")}} 的内部,添加下面的代码。将 {{htmlelement("select")}} 和 {{htmlelement("pre")}} 元素的引用存储到变量中,并定义一个 {{domxref("GlobalEventHandlers.onchange","onchange")}} 事件处理函数,可以在 select 的值改变时, 将其值传递给
updateDisplay()
函数作为参数。const verseChoose = document.querySelector('select'); const poemDisplay = document.querySelector('pre'); @@ -103,76 +103,76 @@XMLHttpRequest
};- -
定义
+updateDisplay()
函数. 首先,将下面的代码块放在之前代码块的下面 - 这是函数的空壳:定义
updateDisplay()
函数。首先,将下面的代码块放在之前代码块的下面 - 这是函数的空壳:function updateDisplay(verse) { }- -
我们将通过构造一个 指向我们要加载的文本文件的相对URL 来启动我们的函数, 因为我们稍后需要它. 任何时候 {{htmlelement("select")}} 元素的值都与所选的 {{htmlelement("option")}} 内的文本相同 (除非在值属性中指定了不同的值) — 例如 "Verse 1". 相应的诗歌文本文件是 "verse1.txt", 并与HTML文件位于同一目录中, 因此只需要文件名即可。
+我们将通过构造一个 指向我们要加载的文本文件的相对 URL 来启动我们的函数,因为我们稍后需要它。任何时候 {{htmlelement("select")}} 元素的值都与所选的 {{htmlelement("option")}} 内的文本相同 (除非在值属性中指定了不同的值) — 例如 "Verse 1". 相应的诗歌文本文件是 "verse1.txt", 并与 HTML 文件位于同一目录中,因此只需要文件名即可。
-但是,Web服务器往往是区分大小写的,文件名没有空格。 要将“Verse 1”转换为“verse1.txt”,我们需要将V转换为小写,删除空格,并在末尾添加.txt。 这可以通过 {{jsxref("String.replace", "replace()")}}, {{jsxref("String.toLowerCase", "toLowerCase()")}}, 和 简单的 string concatenation 来完成. 在
+updateDisplay()
函数中添加以下代码:但是,Web 服务器往往是区分大小写的,文件名没有空格。要将“Verse 1”转换为“verse1.txt”,我们需要将 V 转换为小写,删除空格,并在末尾添加.txt。 这可以通过 {{jsxref("String.replace", "replace()")}}, {{jsxref("String.toLowerCase", "toLowerCase()")}}, 和 简单的 string concatenation 来完成。在
updateDisplay()
函数中添加以下代码:verse = verse.replace(" ", ""); verse = verse.toLowerCase(); let url = verse + '.txt';- -
要开始创建XHR请求,您需要使用 {{domxref("XMLHttpRequest.XMLHttpRequest", "XMLHttpRequest()")}} 的构造函数创建一个新的请求对象。 你可以把这个对象叫做你喜欢的任何东西, 但是我们会把它叫做
+request
来保持简单. 在之前的代码中添加以下内容:要开始创建 XHR 请求,您需要使用 {{domxref("XMLHttpRequest.XMLHttpRequest", "XMLHttpRequest()")}} 的构造函数创建一个新的请求对象。 你可以把这个对象叫做你喜欢的任何东西,但是我们会把它叫做
request
来保持简单。在之前的代码中添加以下内容:let request = new XMLHttpRequest();- -
接下来,您需要使用 {{domxref("XMLHttpRequest.open","open()")}} 方法来指定用于从网络请求资源的 HTTP request method , 以及它的URL是什么。我们将在这里使用
+GET
方法, 并将URL设置为我们的url
变量. 在你上面的代码中添加以下代码:接下来,您需要使用 {{domxref("XMLHttpRequest.open","open()")}} 方法来指定用于从网络请求资源的 HTTP request method , 以及它的 URL 是什么。我们将在这里使用
GET
方法,并将 URL 设置为我们的url
变量。在你上面的代码中添加以下代码:request.open('GET', url);- -
接下来,我们将设置我们期待的响应类型 — 这是由请求的 {{domxref("XMLHttpRequest.responseType", "responseType")}} 属性定义的 — 作为
+text
. 这并不是绝对必要的 — XHR默认返回文本 —但如果你想在以后获取其他类型的数据,养成这样的习惯是一个好习惯. 接下来添加:接下来,我们将设置我们期待的响应类型 — 这是由请求的 {{domxref("XMLHttpRequest.responseType", "responseType")}} 属性定义的 — 作为
text
. 这并不是绝对必要的 — XHR 默认返回文本 —但如果你想在以后获取其他类型的数据,养成这样的习惯是一个好习惯。接下来添加:request.responseType = 'text';- -
从网络获取资源是一个 {{glossary("asynchronous")}} "异步" 操作, 这意味着您必须等待该操作完成(例如,资源从网络返回),然后才能对该响应执行任何操作,否则会出错,将被抛出错误。 XHR允许你使用它的 {{domxref("XMLHttpRequest.onload", "onload")}} 事件处理器来处理这个事件 — 当{{event("onload")}} 事件触发时(当响应已经返回时)这个事件会被运行。 发生这种情况时,
+response
数据将在XHR请求对象的响应属性中可用。从网络获取资源是一个 {{glossary("asynchronous")}} "异步" 操作,这意味着您必须等待该操作完成(例如,资源从网络返回),然后才能对该响应执行任何操作,否则会出错,将被抛出错误。XHR 允许你使用它的 {{domxref("XMLHttpRequest.onload", "onload")}} 事件处理器来处理这个事件 — 当{{event("onload")}} 事件触发时(当响应已经返回时)这个事件会被运行。发生这种情况时,
-response
数据将在 XHR 请求对象的响应属性中可用。在后面添加以下内容. 你会看到,在
+onload
事件处理程序中,我们将poemDisplay
( {{htmlelement("pre")}} 元素 ) 的textContent
设置为 {{domxref("XMLHttpRequest.response", "request.response")}} 属性的值。在后面添加以下内容。 你会看到,在
onload
事件处理程序中,我们将poemDisplay
( {{htmlelement("pre")}} 元素 ) 的textContent
设置为 {{domxref("XMLHttpRequest.response", "request.response")}} 属性的值。request.onload = function() { poemDisplay.textContent = request.response; };- -
以上都是XHR请求的设置 — 在我们告诉它之前,它不会真正运行,这是通过 {{domxref("XMLHttpRequest.send","send()")}} 完成的. 在你之前的代码下添加以下内容完成该函数:
+以上都是 XHR 请求的设置 — 在我们告诉它之前,它不会真正运行,这是通过 {{domxref("XMLHttpRequest.send","send()")}} 完成的。在你之前的代码下添加以下内容完成该函数:
request.send();- -
这个例子中的一个问题就是它首次加载时不会显示任何诗。 为了解决这个问题,在代码的底部添加以下两行 (正好在关闭的
+</script>
标签之上) 默认加载第1节,并确保 {{htmlelement("select")}} 元素始终显示正确的值:这个例子中的一个问题就是它首次加载时不会显示任何诗。为了解决这个问题,在代码的底部添加以下两行 (正好在关闭的
</script>
标签之上) 默认加载第 1 节,并确保 {{htmlelement("select")}} 元素始终显示正确的值:updateDisplay('Verse 1'); verseChoose.value = 'Verse 1';在server端运行例子
+在 server 端运行例子
-如果只是从本地文件运行示例,一些浏览器(包括Chrome)将不会运行XHR请求。这是因为安全限制(更多关于web安全性的限制,请参阅Website security)。
+如果只是从本地文件运行示例,一些浏览器 (包括 Chrome) 将不会运行 XHR 请求。这是因为安全限制 (更多关于 web 安全性的限制,请参阅Website security)。
-为了解决这个问题,我们需要通过在本地web服务器上运行它来测试这个示例。要了解如何实现这一点,请阅读How do you set up a local testing server?
+为了解决这个问题,我们需要通过在本地 web 服务器上运行它来测试这个示例。要了解如何实现这一点,请阅读How do you set up a local testing server?
Fetch
-Fetch API基本上是XHR的一个现代替代品——它是最近在浏览器中引入的,它使异步HTTP请求在JavaScript中更容易实现,对于开发人员和在Fetch之上构建的其他API来说都是如此。
+Fetch API 基本上是 XHR 的一个现代替代品——它是最近在浏览器中引入的,它使异步 HTTP 请求在 JavaScript 中更容易实现,对于开发人员和在 Fetch 之上构建的其他 API 来说都是如此。
-让我们将最后一个示例转换为使用Fetch !
+让我们将最后一个示例转换为使用 Fetch !
-
- -
复制您之前完成的示例目录. (如果您没有通过以前的练习,创建一个新的目录。, 然后复制 xhr-basic.html和这四个文件 — verse1.txt, verse2.txt, verse3.txt, and verse4.txt.)
+复制您之前完成的示例目录。(如果您没有通过以前的练习,创建一个新的目录。, 然后复制 xhr-basic.html和这四个文件 — verse1.txt, verse2.txt, verse3.txt, and verse4.txt.)
- -
在
+updateDisplay()
里找到 XHR 那段代码:在
updateDisplay()
里找到 XHR 那段代码:let request = new XMLHttpRequest(); request.open('GET', url); @@ -185,7 +185,7 @@Fetch
request.send();- -
像这样替换掉所有关于XHR的代码:
+像这样替换掉所有关于 XHR 的代码:
fetch(url).then(function(response) { response.text().then(function(text) { @@ -194,27 +194,27 @@Fetch
});- -
在浏览器中加载示例(通过web服务器运行),它应该与XHR版本相同,前提是您运行的是一个现代浏览器。
+在浏览器中加载示例 (通过 web 服务器运行),它应该与 XHR 版本相同,前提是您运行的是一个现代浏览器。
那么Fetch代码中发生了什么呢?
+那么 Fetch 代码中发生了什么呢?
-首先,我们调用了
+fetch()
方法,将我们要获取的资源的URL传递给它。这相当于现代版的XHR中的request.open()
,另外,您不需要任何等效的send()
方法。首先,我们调用了
-fetch()
方法,将我们要获取的资源的 URL 传递给它。这相当于现代版的 XHR 中的request.open()
,另外,您不需要任何等效的send()
方法。然后,你可以看到
+.then()
方法连接到了fetch()
末尾-这个方法是Promises
的一部分,是一个用于执行异步操作的现代JavaScript特性。fetch()
返回一个promise,它将解析从服务器发回的响应。我们使用then()
来运行一些后续代码,这是我们在其内部定义的函数。这相当于XHR版本中的onload
事件处理程序。然后,你可以看到
-.then()
方法连接到了fetch()
末尾 - 这个方法是Promises
的一部分,是一个用于执行异步操作的现代 JavaScript 特性。fetch()
返回一个 promise,它将解析从服务器发回的响应。我们使用then()
来运行一些后续代码,这是我们在其内部定义的函数。这相当于 XHR 版本中的onload
事件处理程序。当
+fetch()
promise 解析时,这个函数会自动将响应从服务器传递给参数。在函数内部,我们获取响应并运行其text()
方法。这基本上将响应作为原始文本返回,这相当于在XHR版本中的responseType = 'text'
。当
-fetch()
promise 解析时,这个函数会自动将响应从服务器传递给参数。在函数内部,我们获取响应并运行其text()
方法。这基本上将响应作为原始文本返回,这相当于在 XHR 版本中的responseType = 'text'
。你会看到
+text()
也返回了一个 promise, 所以我们连接另外一个.then()
到它上面, 在其中我们定义了一个函数来接收text()
promise解析的生文本。你会看到
-text()
也返回了一个 promise, 所以我们连接另外一个.then()
到它上面,在其中我们定义了一个函数来接收text()
promise 解析的生文本。在promise的函数内部,我们做的和在XHR版本中差不多— 设置
+<pre>
元素的文本内容为text的值。在 promise 的函数内部,我们做的和在 XHR 版本中差不多— 设置
-<pre>
元素的文本内容为 text 的值。关于promises
+关于 promises
-当你第一次见到它们的时候,promises会让你有点困惑,但现在不要太担心这个。在一段时间之后,您将会习惯它们,特别是当您了解更多关于现代JavaScript api的时候——大多数现代的JavaScript api都是基于promises的。
+当你第一次见到它们的时候,promises 会让你有点困惑,但现在不要太担心这个。在一段时间之后,您将会习惯它们,特别是当您了解更多关于现代 JavaScript api 的时候——大多数现代的 JavaScript api 都是基于 promises 的。
-让我们再看看上面的promises结构,看看我们是否能更清楚地理解它:
+让我们再看看上面的 promises 结构,看看我们是否能更清楚地理解它:
fetch(url).then(function(response) { response.text().then(function(text) { @@ -222,9 +222,9 @@-关于promises
}); });第一行是说‘’获取位于url里的资源(
+fetch(url)
)‘’和“然后当promise解析后运行指定的函数(.then(function() { ... })
)”。"解析"的意思是"在将来某一时刻完成指定的操作"。在本例中,指定的操作是从指定的URL(使用HTTP请求)获取资源,并返回对我们执行某些操作的响应。第一行是说‘’获取位于 url 里的资源 (
-fetch(url)
)‘’和“然后当 promise 解析后运行指定的函数 (.then(function() { ... })
)”。"解析"的意思是"在将来某一时刻完成指定的操作"。在本例中,指定的操作是从指定的 URL(使用 HTTP 请求) 获取资源,并返回对我们执行某些操作的响应。实际上,传递给
+then()
是一段不会立即执行的代码 — 而是当返回响应时代码会被运行。注意,你还可以选择把你的 promise 保存到一个变量里, 链接.then()
在相同的位置。下面的代码会做相同的事情。实际上,传递给
then()
是一段不会立即执行的代码 — 而是当返回响应时代码会被运行。注意,你还可以选择把你的 promise 保存到一个变量里,链接.then()
在相同的位置。下面的代码会做相同的事情。let myFetch = fetch(url); @@ -234,7 +234,7 @@-关于promises
}); });因为方法 fetch() 返回一个解析HTTP响应的promise, 你在 .then() 中定义的任何函数会被自动给与一个响应作为一个参数。你可以给这个参数取任何名字,以下的例子依然可以实现:(例子里把response参数叫做狗饼干---'dogBiscuits'=狗饼干)
+因为方法 fetch() 返回一个解析 HTTP 响应的 promise, 你在 .then() 中定义的任何函数会被自动给与一个响应作为一个参数。你可以给这个参数取任何名字,以下的例子依然可以实现:(例子里把 response 参数叫做狗饼干---'dogBiscuits'=狗饼干)
fetch(url).then(function(dogBiscuits) { dogBiscuits.text().then(function(text) { @@ -252,11 +252,11 @@-关于promises
}); }response 对象有个
+text()
方法, 获取响应主体中的原始数据a并把它转换成纯文本, 那是我们想要的格式。它也返回一个promise (解析结果文本字符串), 所以这里我们再使用.then()
, 在里面我们再定义一个操作文本字符串的函数。我们设置诗歌的<pre>
元素的textContent
属性和这个文本字符串相同, 这样就非常简单地解决了。response 对象有个
-text()
方法,获取响应主体中的原始数据 a 并把它转换成纯文本,那是我们想要的格式。它也返回一个 promise (解析结果文本字符串), 所以这里我们再使用.then()
, 在里面我们再定义一个操作文本字符串的函数。我们设置诗歌的<pre>
元素的textContent
属性和这个文本字符串相同,这样就非常简单地解决了。值得注意的是你可以直接将promise块 (
+.then()
块, 但也有其他类型) 链接到另一个的尾部, 顺着链条将每个块的结果传到下一个块。 这使得promises非常强大。值得注意的是你可以直接将 promise 块 (
-.then()
块,但也有其他类型) 链接到另一个的尾部,顺着链条将每个块的结果传到下一个块。 这使得 promises 非常强大。下面的代码块和我们原始的例子做的是相同的事, 但它是不同的写法:
+下面的代码块和我们原始的例子做的是相同的事,但它是不同的写法:
fetch(url).then(function(response) { return response.text() @@ -264,29 +264,29 @@-关于promises
poemDisplay.textContent = text; });很多开发者更喜欢这种样式, 因为它更扁平并且按理说对于更长的promise链它更容易读 — 每一个promise(承诺)接续上一个promise,而不是在上一个promise的里面(会使得整个代码笨重起来,难以理解)。以上两种写法还有一个不同的地方是我们在
+response.text()
语句之前得包含一个return
语句, 用来把这一部分的结果传向promise链的下一段。很多开发者更喜欢这种样式,因为它更扁平并且按理说对于更长的 promise 链它更容易读 — 每一个 promise(承诺)接续上一个 promise,而不是在上一个 promise 的里面 (会使得整个代码笨重起来,难以理解)。以上两种写法还有一个不同的地方是我们在
-response.text()
语句之前得包含一个return
语句,用来把这一部分的结果传向 promise 链的下一段。你应该用哪种方法呢?
+你应该用哪种方法呢?
-这完全取决于你正在干的项目是啥样。XHR已经面世非常之久,现在已经有了相当棒的跨浏览器支持。然而对于网页平台来说,Fetch和Promise是新近的产物,除了IE和Safari浏览器不支持,别的浏览器大多提供了支持。(现在Safari也即将为fetch和promise提供支持)。
+这完全取决于你正在干的项目是啥样。XHR 已经面世非常之久,现在已经有了相当棒的跨浏览器支持。然而对于网页平台来说,Fetch 和 Promise 是新近的产物,除了 IE 和 Safari 浏览器不支持,别的浏览器大多提供了支持。(现在 Safari 也即将为 fetch 和 promise 提供支持)。
-如果你的项目需要支持年代久远的浏览器,那么使用XHR可能会更爽一些。如果你的项目比较激进而且你根本不管老版的浏览器吃不吃这套,那就选择Fetch吧老铁。
+如果你的项目需要支持年代久远的浏览器,那么使用 XHR 可能会更爽一些。如果你的项目比较激进而且你根本不管老版的浏览器吃不吃这套,那就选择 Fetch 吧老铁。
-话说回来,咱倒真应该两者都学学——因为使用IE浏览器的人们在变少,Fetch会变得越来越流行(事实上IE已经没人管了,因为微软Edge浏览器的受宠),但在所有浏览器彻底支持Fetch之前,你可能还得和XHR纠缠一阵子。
+话说回来,咱倒真应该两者都学学——因为使用 IE 浏览器的人们在变少,Fetch 会变得越来越流行(事实上 IE 已经没人管了,因为微软 Edge 浏览器的受宠),但在所有浏览器彻底支持 Fetch 之前,你可能还得和 XHR 纠缠一阵子。
一个更复杂的示例
-为了使本文更详尽,我们将看一个稍微复杂一点的示例,它展示了Fetch的一些更有趣的用法。我们创建了一个名为Can Store的示例站点——它是一个虚构的超市,只出售罐头食品。你可以找到 example live on GitHub,并且 see the source code 。
+为了使本文更详尽,我们将看一个稍微复杂一点的示例,它展示了 Fetch 的一些更有趣的用法。我们创建了一个名为 Can Store 的示例站点——它是一个虚构的超市,只出售罐头食品。你可以找到 example live on GitHub,并且 see the source code 。
默认情况下,站点会显示所有产品,但您可以使用左手列中的表单控件按类别或搜索词或两者进行筛选。
-有很多复杂的代码处理按类别和搜索词过滤产品、操作字符串以便数据在UI中正确显示等等。我们不会在本文中讨论所有这些,但是您可以在代码中找到大量的注释 (see can-script.js)。
+有很多复杂的代码处理按类别和搜索词过滤产品、操作字符串以便数据在 UI 中正确显示等等。我们不会在本文中讨论所有这些,但是您可以在代码中找到大量的注释 (see can-script.js)。
-但是,我们会解释Fetch代码的含义。
+但是,我们会解释 Fetch 代码的含义。
-第一个使用Fetch的块可以在JavaScript的开头找到:
+第一个使用 Fetch 的块可以在 JavaScript 的开头找到:
fetch('products.json').then(function(response) { if(response.ok) { @@ -299,22 +299,22 @@-一个更复杂的示例
} });这看起来和我们之前看到的相似,只是第二个promise是在一个条件语句中。在条件下,我们检查返回的response是否成功 — {{domxref("response.ok")}} 属性包含一个布尔变量,如果response是成功的 (e.g. 200 meaning "OK"),则是
+true
;如果失败了,则是false
。这看起来和我们之前看到的相似,只是第二个 promise 是在一个条件语句中。在条件下,我们检查返回的 response 是否成功 — {{domxref("response.ok")}} 属性包含一个布尔变量,如果 response 是成功的 (e.g. 200 meaning "OK"),则是
-true
;如果失败了,则是false
。如果response成功,我们运行第二个promise — 然而,这次我们使用 {{domxref("Body.json","json()")}},而不是{{domxref("Body.text","text()")}}, 因为我们想要response返回的是一个结构化的JSON数据,而不是纯文本。
+如果 response 成功,我们运行第二个 promise — 然而,这次我们使用 {{domxref("Body.json","json()")}},而不是{{domxref("Body.text","text()")}}, 因为我们想要 response 返回的是一个结构化的 JSON 数据,而不是纯文本。
-如果response失败,我们将输出一个错误到控制台,指出网络请求失败,该控制台将报告响应的网络状态和描述性消息(分别包含在{{domxref("response.status")}}和{{domxref("response.statusText")}}属性中)。 当然,一个完整的web站点可以通过在用户的屏幕上显示一条消息来更优雅地处理这个错误,也许还可以提供一些选项来补救这种情况。
+如果 response 失败,我们将输出一个错误到控制台,指出网络请求失败,该控制台将报告响应的网络状态和描述性消息 (分别包含在{{domxref("response.status")}}和{{domxref("response.statusText")}}属性中)。当然,一个完整的 web 站点可以通过在用户的屏幕上显示一条消息来更优雅地处理这个错误,也许还可以提供一些选项来补救这种情况。
您可以自己测试失败案例:
-
-- 制作示例文件的本地副本(下载并解压the can-store ZIP file)
-- 通过web服务器运行代码(如上所述,在 在server端运行例子)
+- 制作示例文件的本地副本 (下载并解压the can-store ZIP file)
+- 通过 web 服务器运行代码 (如上所述,在 在 server 端运行例子)
- 修改要获取的文件的路径,比如“produc.json'(确保你拼写的是错误的)
-- 现在在你的浏览器上加载索引文件 (通过
+localhost:8000
) 然后查看你的开发者控制台。 你将看到一条类似于“网络请求products.json失败,404:找不到文件”的消息- 现在在你的浏览器上加载索引文件 (通过
localhost:8000
) 然后查看你的开发者控制台。你将看到一条类似于“网络请求 products.json 失败,404:找不到文件”的消息第二个Fetch块可以在
+fetchBlob()
找到:第二个 Fetch 块可以在
fetchBlob()
找到:fetch(url).then(function(response) { if(response.ok) { @@ -327,37 +327,37 @@-一个更复杂的示例
} });它的工作原理和前一个差不多, 除了我们放弃{{domxref("Body.json","json()")}}而使用{{domxref("Body.blob","blob()")}} — 在本例中,我们希望以图像文件的形式返回响应,为此使用的数据格式是Blob — 这个词是“二进制大对象”的缩写,基本上可以用来表示大型文件类对象——比如图像或视频文件。
+它的工作原理和前一个差不多,除了我们放弃{{domxref("Body.json","json()")}}而使用{{domxref("Body.blob","blob()")}} — 在本例中,我们希望以图像文件的形式返回响应,为此使用的数据格式是Blob — 这个词是“二进制大对象”的缩写,基本上可以用来表示大型文件类对象——比如图像或视频文件。
-一旦我们成功地接收到我们的blob,我们就会使用它创建一个对象URL {{domxref("URL.createObjectURL()", "createObjectURL()")}}. 它返回一个指向浏览器中引用的对象的临时内部URL。这些不是很容易读懂,但是你可以通过打开Can Store看到,按Ctrl-/右键单击一个图像,然后选择“View Image(查看图像)”选项(根据您使用的浏览器可能略有不同)。 对象URL将在地址栏中可见,应该是这样的:
+一旦我们成功地接收到我们的 blob,我们就会使用它创建一个对象 URL {{domxref("URL.createObjectURL()", "createObjectURL()")}}. 它返回一个指向浏览器中引用的对象的临时内部 URL。这些不是很容易读懂,但是你可以通过打开 Can Store 看到,按 Ctrl-/右键单击一个图像,然后选择“View Image(查看图像)”选项 (根据您使用的浏览器可能略有不同)。对象 URL 将在地址栏中可见,应该是这样的:
blob:http://localhost:7800/9b75250e-5279-e249-884f-d03eb1fd84f4-挑战:一个XHR版本的Can Store
+挑战:一个 XHR 版本的 Can Store
-我们希望您能尝试将Fetch版本转换为使用XHR,作为一个有用的实践。下载一份 copy of the ZIP file, 并适当修改下JavaScript。
+我们希望您能尝试将 Fetch 版本转换为使用 XHR,作为一个有用的实践。下载一份 copy of the ZIP file, 并适当修改下 JavaScript。
一些有用的提示:
- 你可能会发现 {{domxref("XMLHttpRequest")}} 作参考材料非常有用。
- 你基本上需要使用和你在前面的文章中看到的XHR-basic.html例子相同的模式。
-- 但是,您将需要添加我们在Can Store的Fetch版本中显示的错误处理: +
- 但是,您将需要添加我们在 Can Store 的 Fetch 版本中显示的错误处理:
-
- 在
-load
事件完毕后,response被用于request.response
而不是promise的then()
。- Fetch的
-response.ok
在XHR中的最佳等效为检查 {{domxref("XMLHttpRequest.status","request.status")}} 是否等于200或者 {{domxref("XMLHttpRequest.readyState","request.readyState")}} 是否等于4。- 获取状态和状态信息的内容是一样的, 但是它们在
+request
(XHR) 对象,而不是response
对象。- 在
+load
事件完毕后,response 被用于request.response
而不是 promise 的then()
。- Fetch 的
+response.ok
在 XHR 中的最佳等效为检查 {{domxref("XMLHttpRequest.status","request.status")}} 是否等于 200 或者 {{domxref("XMLHttpRequest.readyState","request.readyState")}} 是否等于 4。- 获取状态和状态信息的内容是一样的,但是它们在
request
(XHR) 对象,而不是response
对象。-注意: 如果您在这方面有问题,请到Github将您的代码和完成的版本进行对比 ( see the source here, see also see it running live )。
+注意: 如果您在这方面有问题,请到 Github 将您的代码和完成的版本进行对比 ( see the source here, see also see it running live )。
概述
-我们这篇关于从服务器那儿抓取数据的文章就到此为止了。现在你应该对如何使用XHR和Fetch有一些了解了吧?
+我们这篇关于从服务器那儿抓取数据的文章就到此为止了。现在你应该对如何使用 XHR 和 Fetch 有一些了解了吧?
请参阅
@@ -385,11 +385,11 @@请参阅
模块大纲
-
diff --git a/files/zh-cn/learn/javascript/client-side_web_apis/index.html b/files/zh-cn/learn/javascript/client-side_web_apis/index.html index cb4c00c45f3042..78bf3ab1630eb5 100644 --- a/files/zh-cn/learn/javascript/client-side_web_apis/index.html +++ b/files/zh-cn/learn/javascript/client-side_web_apis/index.html @@ -15,11 +15,11 @@ ---- 介绍web APIs
-- 操作DOM documents
+- 介绍 web APIs
+- 操作 DOM documents
- 从服务器获取数据
-- 第三方APIs
+- 第三方 APIs
- 绘图
-- 视频音频APIs
+- 视频音频 APIs
- 客户端存储
{{LearnSidebar}}-当你给网页或者网页应用编写客户端的JavaScript时, 你很快会遇上应用程序接口(API )—— 这些编程特性可用来操控网站所基于的浏览器与操作系统的不同方面,或是操控由其他网站或服务端传来的数据。在这个单元里,我们将一同探索什么是API,以及如何使用一些在你开发中将经常遇见的API。
+当你给网页或者网页应用编写客户端的 JavaScript 时,你很快会遇上应用程序接口(API)—— 这些编程特性可用来操控网站所基于的浏览器与操作系统的不同方面,或是操控由其他网站或服务端传来的数据。在这个单元里,我们将一同探索什么是 API,以及如何使用一些在你开发中将经常遇见的 API。
预备知识
-若想深入理解这个单元的内容, 你必须能够以自己的能力较好地学完之前的几个章节 (JavaScript第一步, JavaScript基础要件, 和JavaScript对象介绍). 这几部分涉及到了许多简单的API的使用, 如果没有它们我们将很难做一些实际的事情。在这个教程中,我们会认为你懂得JavaScript的核心知识,而且我们将更深入地探索常见的网页API。
+若想深入理解这个单元的内容,你必须能够以自己的能力较好地学完之前的几个章节 (JavaScript 第一步, JavaScript基础要件, 和JavaScript对象介绍). 这几部分涉及到了许多简单的 API 的使用, 如果没有它们我们将很难做一些实际的事情。在这个教程中,我们会认为你懂得 JavaScript 的核心知识,而且我们将更深入地探索常见的网页 API。
若你知道 HTML 和 CSS 的基本知识,也会对理解这个单元的内容大有裨益。
@@ -30,18 +30,18 @@预备知识
向导
-
diff --git a/files/zh-cn/learn/javascript/client-side_web_apis/introduction/index.html b/files/zh-cn/learn/javascript/client-side_web_apis/introduction/index.html index 9b8e83ce30ad86..45ddc4c1a54966 100644 --- a/files/zh-cn/learn/javascript/client-side_web_apis/introduction/index.html +++ b/files/zh-cn/learn/javascript/client-side_web_apis/introduction/index.html @@ -1,5 +1,5 @@ --- -title: Web API简介 +title: Web API 简介 slug: Learn/JavaScript/Client-side_web_APIs/Introduction tags: - API @@ -18,22 +18,22 @@- Web API简介
-- 首先, 我们将从一个更高的角度来看这些API —它们是什么,它们怎么起作用的,你该怎么在自己的代码中使用它们以及他们是怎么构成的? 我们依旧会再来看一看这些API有哪些主要的种类和他们会有哪些用处。
+- Web API 简介
+- 首先,我们将从一个更高的角度来看这些 API —它们是什么,它们怎么起作用的,你该怎么在自己的代码中使用它们以及他们是怎么构成的?我们依旧会再来看一看这些 API 有哪些主要的种类和他们会有哪些用处。
- 操作文档
-- 当你在制作WEB页面和APP时,一个你最经常想要做的事就是通过一些方法来操作WEB文档。这其中最常见的方法就是使用文档对象模型Document Object Model (DOM),它是一系列大量使用了 {{domxref("Document")}} object的API来控制HTML和样式信息。通过这篇文章,我们来看看使用DOM方面的一些细节, 以及其他一些有趣的API能够通过一些有趣的方式改变你的环境。
+- 当你在制作 WEB 页面和 APP 时,一个你最经常想要做的事就是通过一些方法来操作 WEB 文档。这其中最常见的方法就是使用文档对象模型 Document Object Model (DOM),它是一系列大量使用了 {{domxref("Document")}} object 的 API 来控制 HTML 和样式信息。通过这篇文章,我们来看看使用 DOM 方面的一些细节, 以及其他一些有趣的 API 能够通过一些有趣的方式改变你的环境。
- 从服务器获取数据
-- 在现代网页及其APP中另外一个很常见的任务就是与服务器进行数据交互时不再刷新整个页面,这看起来微不足道,但却对一个网页的展现和交互上起到了很大的作用,在这篇文章里,我们将阐述这个概念,然后来了解实现这个功能的技术,例如 {{domxref("XMLHttpRequest")}} 和 Fetch API.(抓取API)。
+- 在现代网页及其 APP 中另外一个很常见的任务就是与服务器进行数据交互时不再刷新整个页面,这看起来微不足道,但却对一个网页的展现和交互上起到了很大的作用,在这篇文章里,我们将阐述这个概念,然后来了解实现这个功能的技术,例如 {{domxref("XMLHttpRequest")}} 和 Fetch API.(抓取 API)。
- 第三方 API
-- 到目前为止我们所涉及的API都是浏览器内置的,但并不代表所有。许多大网站如Google Maps, Twitter, Facebook, PayPal等,都提供他们的API给开发者们去使用他们的数据(比如在你的博客里展示你分享的推特内容)或者服务(如在你的网页里展示定制的谷歌地图或接入Facebook登录功能)。这篇文章介绍了浏览器API和第三方API 的差别以及一些最新的典型应用。
+- 到目前为止我们所涉及的 API 都是浏览器内置的,但并不代表所有。许多大网站如 Google Maps, Twitter, Facebook, PayPal 等,都提供他们的 API 给开发者们去使用他们的数据(比如在你的博客里展示你分享的推特内容)或者服务(如在你的网页里展示定制的谷歌地图或接入 Facebook 登录功能)。这篇文章介绍了浏览器 API 和第三方 API 的差别以及一些最新的典型应用。
- 绘制图形
-- 浏览器包含多种强大的图形编程工具,从可缩放矢量图形语言Scalable Vector Graphics (SVG) language,到HTML绘制元素 {{htmlelement("canvas")}} 元素(The Canvas API and WebGL). 这篇文章提供了部分canvas的简介,以及让你更深入学习的资源。
+- 浏览器包含多种强大的图形编程工具,从可缩放矢量图形语言 Scalable Vector Graphics (SVG) language,到 HTML 绘制元素 {{htmlelement("canvas")}} 元素 (The Canvas API and WebGL). 这篇文章提供了部分 canvas 的简介,以及让你更深入学习的资源。
- 视频和音频 API
-- HTML5能够通过元素标签嵌入富媒体——{{htmlelement("video")}} and {{htmlelement("audio")}}——而将有自己的API来控制回放,搜索等功能。本文向您展示了如何创建自定义播放控制等常见的任务。
+- HTML5 能够通过元素标签嵌入富媒体——{{htmlelement("video")}} and {{htmlelement("audio")}}——而将有自己的 API 来控制回放,搜索等功能。本文向您展示了如何创建自定义播放控制等常见的任务。
- 客户端存储
-- 现代web浏览器拥有很多不同的技术,能够让你存储与网站相关的数据,并在需要时调用它们,能够让你长期保存数据、保存离线网站及其他实现其他功能。本文解释了这些功能的基本原理。
+- 现代 web 浏览器拥有很多不同的技术,能够让你存储与网站相关的数据,并在需要时调用它们,能够让你长期保存数据、保存离线网站及其他实现其他功能。本文解释了这些功能的基本原理。
{{NextMenu("Learn/JavaScript/Client-side_Web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_Web_API")}}-首先,我们将从一个高层次看看API - 它们是什么;他们如何工作;如何在代码中使用它们,以及它们是如何组织的。我们也将看看不同主要类别的API以及它们的用途。
+首先,我们将从一个高层次看看 API - 它们是什么;他们如何工作;如何在代码中使用它们,以及它们是如何组织的。我们也将看看不同主要类别的 API 以及它们的用途。
-
预备知识 -基本计算机知识,对于HTML和CSS的基本理解(见JavaScript 第一步,创建JavaScript代码块,JavaScript 对象入门)。 +基本计算机知识,对于 HTML 和 CSS 的基本理解(见JavaScript 第一步,创建 JavaScript 代码块,JavaScript 对象入门)。 目标 -熟悉API,他们可以做什么,以及如何在代码中使用它们。 +熟悉 API,他们可以做什么,以及如何在代码中使用它们。 什么是API?
+什么是 API?
应用程序接口(API,Application Programming Interface)是基于编程语言构建的结构,使开发人员更容易地创建复杂的功能。它们抽象了复杂的代码,并提供一些简单的接口规则直接使用。
@@ -41,21 +41,21 @@什么是API?
-图片来自:Overloaded plug socket 提供者: The Clear Communication People于Flickr。
+图片来自:Overloaded plug socket 提供者: The Clear Communication People于 Flickr。
-同样,比如说,编程来显示一些3D图形,使用以更高级语言编写的API(例如JavaScript或Python)将会比直接编写直接控制计算机的GPU或其他图形功能的低级代码(比如C或C++)来执行操作要容易得多。
+同样,比如说,编程来显示一些 3D 图形,使用以更高级语言编写的 API(例如 JavaScript 或 Python)将会比直接编写直接控制计算机的 GPU 或其他图形功能的低级代码(比如 C 或 C++)来执行操作要容易得多。
-注:详细说明请见API - Glossary。
客户端JavaScript中的API
+客户端 JavaScript 中的 API
-客户端JavaScript中有很多可用的API — 他们本身并不是JavaScript语言的一部分,却建立在JavaScript语言核心的顶部,为使用JavaScript代码提供额外的超强能力。他们通常分为两类:
+客户端 JavaScript 中有很多可用的 API — 他们本身并不是 JavaScript 语言的一部分,却建立在 JavaScript 语言核心的顶部,为使用 JavaScript 代码提供额外的超强能力。他们通常分为两类:
-
@@ -66,68 +66,68 @@- 浏览器API内置于Web浏览器中,能从浏览器和电脑周边环境中提取数据,并用来做有用的复杂的事情 。例如Geolocation API提供了一些简单的JavaScript结构以获得位置数据,因此您可以在Google地图上标示您的位置。在后台,浏览器确实使用一些复杂的低级代码(例如C++)与设备的GPS硬件(或可以决定位置数据的任何设施)通信来获取位置数据并把这些数据返回给您的代码中使用浏览器环境;但是,这种复杂性通过API抽象出来,因而与您无关。
-- 第三方API缺省情况下不会内置于浏览器中,通常必须在Web中的某个地方获取代码和信息。例如Twitter API 使您能做一些显示最新推文这样的事情,它提供一系列特殊的结构,可以用来请求Twitter服务并返回特殊的信息。
+- 浏览器 API内置于 Web 浏览器中,能从浏览器和电脑周边环境中提取数据,并用来做有用的复杂的事情。例如Geolocation API提供了一些简单的 JavaScript 结构以获得位置数据,因此您可以在 Google 地图上标示您的位置。在后台,浏览器确实使用一些复杂的低级代码(例如 C++)与设备的 GPS 硬件(或可以决定位置数据的任何设施)通信来获取位置数据并把这些数据返回给您的代码中使用浏览器环境;但是,这种复杂性通过 API 抽象出来,因而与您无关。
+- 第三方 API缺省情况下不会内置于浏览器中,通常必须在 Web 中的某个地方获取代码和信息。例如Twitter API 使您能做一些显示最新推文这样的事情,它提供一系列特殊的结构,可以用来请求 Twitter 服务并返回特殊的信息。
客户端JavaScript中的API
-JavaScript,API和其他JavaScript工具之间的关系
+JavaScript,API 和其他 JavaScript 工具之间的关系
-如上所述,我们讨论了什么是客户端JavaScript API,以及它们与JavaScript语言的关系。让我们回顾一下,使其更清晰,并提及其他JavaScript工具的适用位置:
+如上所述,我们讨论了什么是客户端 JavaScript API,以及它们与 JavaScript 语言的关系。让我们回顾一下,使其更清晰,并提及其他 JavaScript 工具的适用位置:
-
-- JavaScript — 一种内置于浏览器的高级脚本语言,您可以用来实现Web页面/应用中的功能。注意JavaScript也可用于其他象Node这样的的编程环境。但现在您不必考虑这些。
-- 客户端API — 内置于浏览器的结构程序,位于JavaScript语言顶部,使您可以更容易的实现功能。
-- 第三方API — 置于第三方普通的结构程序(例如Twitter,Facebook),使您可以在自己的Web页面中使用那些平台的某些功能(例如在您的Web页面显示最新的Tweets)。
-- JavaScript库 — 通常是包含具有特定功能的一个或多个JavaScript文件,把这些文件关联到您的Web页以快速或授权编写常见的功能。例如包含jQuery和Mootools
-- JavaScript框架 — 从库开始的下一步,JavaScript框架视图把HTML、CSS、JavaScript和其他安装的技术打包在一起,然后用来从头编写一个完整的Web应用。
+- JavaScript — 一种内置于浏览器的高级脚本语言,您可以用来实现 Web 页面/应用中的功能。注意 JavaScript 也可用于其他象Node这样的的编程环境。但现在您不必考虑这些。
+- 客户端 API — 内置于浏览器的结构程序,位于 JavaScript 语言顶部,使您可以更容易的实现功能。
+- 第三方 API — 置于第三方普通的结构程序(例如 Twitter,Facebook),使您可以在自己的 Web 页面中使用那些平台的某些功能(例如在您的 Web 页面显示最新的 Tweets)。
+- JavaScript 库 — 通常是包含具有特定功能的一个或多个 JavaScript 文件,把这些文件关联到您的 Web 页以快速或授权编写常见的功能。例如包含 jQuery 和 Mootools
+- JavaScript 框架 — 从库开始的下一步,JavaScript 框架视图把 HTML、CSS、JavaScript 和其他安装的技术打包在一起,然后用来从头编写一个完整的 Web 应用。
API可以做什么?
+API 可以做什么?
-在主流浏览器中有大量的可用API,您可以在代码中做许多的事情,对此可以查看MDN API index page。
+在主流浏览器中有大量的可用 API,您可以在代码中做许多的事情,对此可以查看MDN API index page。
-常见浏览器API
+常见浏览器 API
-特别地,您将使用的最常见的浏览器API类别(以及我们将更详细地介绍的)是:
+特别地,您将使用的最常见的浏览器 API 类别(以及我们将更详细地介绍的)是:
-
-- 操作文档的API内置于浏览器中。最明显的例子是DOM(文档对象模型)API,它允许您操作HTML和CSS — 创建、移除以及修改HTML,动态地将新样式应用到您的页面,等等。每当您看到一个弹出窗口出现在一个页面上,或者显示一些新的内容时,这都是DOM的行为。 您可以在在Manipulating documents中找到关于这些类型的API的更多信息。
-- 从服务器获取数据的API 用于更新网页的一小部分是相当好用的。这个看似很小的细节能对网站的性能和行为产生巨大的影响 — 如果您只是更新一个股票列表或者一些可用的新故事而不需要从服务器重新加载整个页面将使网站或应用程序感觉更加敏感和“活泼”。使这成为可能的API包括
-XMLHttpRequest
和Fetch API。您也可能会遇到描述这种技术的术语Ajax。您可以在Fetching data from the server找到关于类似的API的更多信息。- 用于绘制和操作图形的API目前已被浏览器广泛支持 — 最流行的是允许您以编程方式更新包含在HTML {{htmlelement("canvas")}} 元素中的像素数据以创建2D和3D场景的Canvas和WebGL。例如,您可以绘制矩形或圆形等形状,将图像导入到画布上,然后使用Canvas API对其应用滤镜(如棕褐色滤镜或灰度滤镜),或使用WebGL创建具有光照和纹理的复杂3D场景。这些API经常与用于创建动画循环的API(例如{{domxref("window.requestAnimationFrame()")}})和其他API一起不断更新诸如动画和游戏之类的场景。
-- 音频和视频API例如{{domxref("HTMLMediaElement")}},Web Audio API和WebRTC允许您使用多媒体来做一些非常有趣的事情,比如创建用于播放音频和视频的自定义UI控件,显示字幕字幕和您的视频,从网络摄像机抓取视频,通过画布操纵(见上),或在网络会议中显示在别人的电脑上,或者添加效果到音轨(如增益,失真,平移等) 。
-- 设备API基本上是以对网络应用程序有用的方式操作和检索现代设备硬件中的数据的API。我们已经讨论过访问设备位置数据的地理定位API,因此您可以在地图上标注您的位置。其他示例还包括通过系统通知(参见Notifications API)或振动硬件(参见Vibration API)告诉用户Web应用程序有用的更新可用。
-- 客户端存储API在Web浏览器中的使用变得越来越普遍 - 如果您想创建一个应用程序来保存页面加载之间的状态,甚至让设备在处于脱机状态时可用,那么在客户端存储数据将会是非常有用的。例如使用Web Storage API的简单的键 - 值存储以及使用IndexedDB API的更复杂的表格数据存储。
+- 操作文档的 API内置于浏览器中。最明显的例子是DOM(文档对象模型)API,它允许您操作 HTML 和 CSS — 创建、移除以及修改 HTML,动态地将新样式应用到您的页面,等等。每当您看到一个弹出窗口出现在一个页面上,或者显示一些新的内容时,这都是 DOM 的行为。 您可以在在Manipulating documents中找到关于这些类型的 API 的更多信息。
+- 从服务器获取数据的 API 用于更新网页的一小部分是相当好用的。这个看似很小的细节能对网站的性能和行为产生巨大的影响 — 如果您只是更新一个股票列表或者一些可用的新故事而不需要从服务器重新加载整个页面将使网站或应用程序感觉更加敏感和“活泼”。使这成为可能的 API 包括
+XMLHttpRequest
和Fetch API。您也可能会遇到描述这种技术的术语Ajax。您可以在Fetching data from the server找到关于类似的 API 的更多信息。- 用于绘制和操作图形的 API目前已被浏览器广泛支持 — 最流行的是允许您以编程方式更新包含在 HTML {{htmlelement("canvas")}} 元素中的像素数据以创建 2D 和 3D 场景的Canvas和WebGL。例如,您可以绘制矩形或圆形等形状,将图像导入到画布上,然后使用 Canvas API 对其应用滤镜(如棕褐色滤镜或灰度滤镜),或使用 WebGL 创建具有光照和纹理的复杂 3D 场景。这些 API 经常与用于创建动画循环的 API(例如{{domxref("window.requestAnimationFrame()")}})和其他 API 一起不断更新诸如动画和游戏之类的场景。
+- 音频和视频 API例如{{domxref("HTMLMediaElement")}},Web Audio API和WebRTC允许您使用多媒体来做一些非常有趣的事情,比如创建用于播放音频和视频的自定义 UI 控件,显示字幕字幕和您的视频,从网络摄像机抓取视频,通过画布操纵(见上),或在网络会议中显示在别人的电脑上,或者添加效果到音轨(如增益,失真,平移等) 。
+- 设备 API基本上是以对网络应用程序有用的方式操作和检索现代设备硬件中的数据的 API。我们已经讨论过访问设备位置数据的地理定位 API,因此您可以在地图上标注您的位置。其他示例还包括通过系统通知(参见Notifications API)或振动硬件(参见Vibration API)告诉用户 Web 应用程序有用的更新可用。
+- 客户端存储 API在 Web 浏览器中的使用变得越来越普遍 - 如果您想创建一个应用程序来保存页面加载之间的状态,甚至让设备在处于脱机状态时可用,那么在客户端存储数据将会是非常有用的。例如使用Web Storage API的简单的键 - 值存储以及使用IndexedDB API的更复杂的表格数据存储。
常见第三方API
+常见第三方 API
-第三方API种类繁多; 下列是一些比较流行的你可能迟早会用到的第三方API:
+第三方 API 种类繁多; 下列是一些比较流行的你可能迟早会用到的第三方 API:
- The Twitter API, 允许您在您的网站上展示您最近的推文等。
-- The Google Maps API 允许你在网页上对地图进行很多操作(这很有趣,它也是Google地图的驱动器)。现在它是一整套完整的,能够胜任广泛任务的API。其能力已经被Google Maps API Picker见证。
-- The Facebook suite of API 允许你将很多Facebook生态系统中的功能应用到你的app,使之受益,比如说它提供了通过Facebook账户登录、接受应用内支付、推送有针对性的广告活动等功能。
-- The YouTube API, 允许你将Youtube上的视频嵌入到网站中去,同时提供搜索Youtube,创建播放列表等众多功能。
-- The Twilio API, 其为您的app提供了针对语音通话和视频聊天的框架,以及从您的app发送短信息或多媒体信息等诸多功能。
+- The Google Maps API 允许你在网页上对地图进行很多操作(这很有趣,它也是 Google 地图的驱动器)。现在它是一整套完整的,能够胜任广泛任务的 API。其能力已经被Google Maps API Picker见证。
+- The Facebook suite of API 允许你将很多 Facebook 生态系统中的功能应用到你的 app,使之受益,比如说它提供了通过 Facebook 账户登录、接受应用内支付、推送有针对性的广告活动等功能。
+- The YouTube API, 允许你将 Youtube 上的视频嵌入到网站中去,同时提供搜索 Youtube,创建播放列表等众多功能。
+- The Twilio API, 其为您的 app 提供了针对语音通话和视频聊天的框架,以及从您的 app 发送短信息或多媒体信息等诸多功能。
--注: 你可以在 Programmable Web API directory.上发现更多关于第三方API的信息。
+注: 你可以在 Programmable Web API directory.上发现更多关于第三方 API 的信息。
API如何工作?
+API 如何工作?
-不同的JavaScript API以稍微不同的方式工作,但通常它们具有共同的特征和相似的主题。
+不同的 JavaScript API 以稍微不同的方式工作,但通常它们具有共同的特征和相似的主题。
它们是基于对象的
-API使用一个或多个 JavaScript objects 在您的代码中进行交互,这些对象用作API使用的数据(包含在对象属性中)的容器以及API提供的功能(包含在对象方法中)。
+API 使用一个或多个 JavaScript objects 在您的代码中进行交互,这些对象用作 API 使用的数据(包含在对象属性中)的容器以及 API 提供的功能(包含在对象方法中)。
-注意:如果您不熟悉对象如何工作,则应继续学习 JavaScript objects 模块。
让我们回到Geolocation API的例子 - 这是一个非常简单的API,由几个简单的对象组成:
+让我们回到 Geolocation API 的例子 - 这是一个非常简单的 API,由几个简单的对象组成:
@@ -143,10 +143,10 @@
- {{domxref("Geolocation")}}, 其中包含三种控制地理数据检索的方法
-- {{domxref("Position")}}, 表示在给定的时间的相关设备的位置。 — 它包含一个当前位置的 {{domxref("Coordinates")}} 对象。还包含了一个时间戳,这个时间戳表示获取到位置的时间。
+- {{domxref("Position")}}, 表示在给定的时间的相关设备的位置。 — 它包含一个当前位置的 {{domxref("Coordinates")}} 对象。还包含了一个时间戳,这个时间戳表示获取到位置的时间。
- {{domxref("Coordinates")}}, 其中包含有关设备位置的大量有用数据,包括经纬度,高度,运动速度和运动方向等。
它们是基于对象的
});--Note: 当您第一次加载上述实例,应当出现一个对话框询问您是否乐意对此应用共享位置信息(参见 它们在适当的地方有额外的安全机制 这一稍后将会提到的部分)。 您需要同意这项询问以将您的位置于地图上绘制。如果您始终无法看见地图,您可能需要手动修改许可项。修改许可项的方法取决于您使用何种浏览器,对于Firefox浏览器来说,在页面信息 > 权限 中修改位置权限,在Chrome浏览器中则进入 设置 > 隐私 > 显示高级设置 > 内容设置,其后修改位置设定。
+Note: 当您第一次加载上述实例,应当出现一个对话框询问您是否乐意对此应用共享位置信息(参见 它们在适当的地方有额外的安全机制 这一稍后将会提到的部分)。您需要同意这项询问以将您的位置于地图上绘制。如果您始终无法看见地图,您可能需要手动修改许可项。修改许可项的方法取决于您使用何种浏览器,对于 Firefox 浏览器来说,在页面信息 > 权限 中修改位置权限,在 Chrome 浏览器中则进入 设置 > 隐私 > 显示高级设置 > 内容设置,其后修改位置设定。
我们首先要使用 {{domxref("Geolocation.getCurrentPosition()")}} 方法返回设备的当前位置。浏览器的 {{domxref("Geolocation")}} 对象通过调用 {{domxref("Navigator.geolocation")}} 属性来访问.
+我们首先要使用 {{domxref("Geolocation.getCurrentPosition()")}} 方法返回设备的当前位置。浏览器的 {{domxref("Geolocation")}} 对象通过调用 {{domxref("Navigator.geolocation")}} 属性来访问。
navigator.geolocation.getCurrentPosition(function(position) { ... });@@ -163,22 +163,22 @@它们是基于对象的
注意:由另一个函数作为参数的函数称为 (callback function "回调函数").
-仅在操作完成时调用函数的模式在JavaScript API中非常常见 - 确保一个操作已经完成,然后在另一个操作中尝试使用该操作返回的数据。这些被称为 asynchronous “异步”操作。由于获取设备的当前位置依赖于外部组件(设备的GPS或其他地理定位硬件), 我们不能保证会立即使用返回的数据。 因此,这样子是行不通的:
+仅在操作完成时调用函数的模式在 JavaScript API 中非常常见 - 确保一个操作已经完成,然后在另一个操作中尝试使用该操作返回的数据。这些被称为 asynchronous “异步”操作。由于获取设备的当前位置依赖于外部组件(设备的 GPS 或其他地理定位硬件),我们不能保证会立即使用返回的数据。因此,这样子是行不通的:
var position = navigator.geolocation.getCurrentPosition(); var myLatitude = position.coords.latitude;-如果第一行还没有返回结果,则第二行将会出现错误,因为位置数据还不可用。 出于这个原因,涉及同步操作的API被设计为使用 {{glossary("callback function")}}s “回调函数”,或更现代的 Promises 系统,这些系统在ECMAScript 6中可用,并被广泛用于较新的API。
+如果第一行还没有返回结果,则第二行将会出现错误,因为位置数据还不可用。出于这个原因,涉及同步操作的 API 被设计为使用 {{glossary("callback function")}}s“回调函数”,或更现代的 Promises 系统,这些系统在 ECMAScript 6 中可用,并被广泛用于较新的 API。
-我们将Geolocation API与第三方API(Google Maps API)相结合, — 我们正在使用它来绘制Google地图上由
+getCurrentPosition()
返回的位置。 我们通过链接到页面上使这个API可用。 — 你会在HTML中找到这一行:我们将 Geolocation API 与第三方 API(Google Maps API)相结合, — 我们正在使用它来绘制 Google 地图上由
getCurrentPosition()
返回的位置。 我们通过链接到页面上使这个 API 可用。 — 你会在 HTML 中找到这一行:<script type="text/javascript" src="https://maps.google.com/maps/API/js?key=AIzaSyDDuGt0E5IEGkcE6ZfrKfUtE9Ko_de66pA"></script>-要使用该API, 我们首先使用
+google.maps.LatLng()
构造函数创建一个LatLng
对象实例, 该构造函数需要我们的地理定位 {{domxref("Coordinates.latitude")}} 和 {{domxref("Coordinates.longitude")}}值作为参数:要使用该 API, 我们首先使用
google.maps.LatLng()
构造函数创建一个LatLng
对象实例, 该构造函数需要我们的地理定位 {{domxref("Coordinates.latitude")}} 和 {{domxref("Coordinates.longitude")}}值作为参数:var latlng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);-该对象实例被设置为
+myOptions
对象的center
属性的值。然后我们通过调用google.maps.Map()
构造函数创建一个对象实例来表示我们的地图, 并传递它两个参数 — 一个参数是我们要渲染地图的 {{htmlelement("div")}} 元素的引用 (ID为map_canvas
), 以及另一个参数是我们在上面定义的myOptions
对象该对象实例被设置为
myOptions
对象的center
属性的值。然后我们通过调用google.maps.Map()
构造函数创建一个对象实例来表示我们的地图, 并传递它两个参数 — 一个参数是我们要渲染地图的 {{htmlelement("div")}} 元素的引用 (ID 为map_canvas
), 以及另一个参数是我们在上面定义的myOptions
对象var myOptions = { zoom: 8, @@ -191,29 +191,29 @@它们是基于对象的
这样做一来,我们的地图呈现了。
-最后一块代码突出显示了您将在许多API中看到的两种常见模式。 首先,API对象通常包含构造函数,可以调用这些构造函数来创建用于编写程序的对象的实例。 其次,API对象通常有几个可用的options(如上面的
+myOptions
对象),可以调整以获得您的程序所需的确切环境(根据不同的环境,编写不同的Options
对象)。 API构造函数通常接受options对象作为参数,这是您设置这些options的地方。最后一块代码突出显示了您将在许多 API 中看到的两种常见模式。 首先,API 对象通常包含构造函数,可以调用这些构造函数来创建用于编写程序的对象的实例。其次,API 对象通常有几个可用的 options(如上面的
myOptions
对象),可以调整以获得您的程序所需的确切环境 (根据不同的环境,编写不同的Options
对象)。API 构造函数通常接受 options 对象作为参数,这是您设置这些 options 的地方。-注意:如果您不能立即理解这个例子的细节,请不要担心。 我们将在未来的文章中详细介绍第三方API。
+注意:如果您不能立即理解这个例子的细节,请不要担心。我们将在未来的文章中详细介绍第三方 API。
它们有可识别的入口点
-使用API时,应确保知道API入口点的位置。 在Geolocation API中,这非常简单 - 它是 {{domxref("Navigator.geolocation")}} 属性, 它返回浏览器的 {{domxref("Geolocation")}} 对象,所有有用的地理定位方法都可用。
+使用 API 时,应确保知道 API 入口点的位置。在 Geolocation API 中,这非常简单 - 它是 {{domxref("Navigator.geolocation")}} 属性,它返回浏览器的 {{domxref("Geolocation")}} 对象,所有有用的地理定位方法都可用。
-文档对象模型 (DOM) API有一个更简单的入口点 —它的功能往往被发现挂在 {{domxref("Document")}} 对象, 或任何你想影响的HTML元素的实例,例如:
+文档对象模型 (DOM) API 有一个更简单的入口点 —它的功能往往被发现挂在 {{domxref("Document")}} 对象,或任何你想影响的 HTML 元素的实例,例如:
var em = document.createElement('em'); // create a new em element var para = document.querySelector('p'); // reference an existing p element em.textContent = 'Hello there!'; // give em some text content para.appendChild(em); // embed em inside para-其他API具有稍微复杂的入口点,通常涉及为要编写的API代码创建特定的上下文。例如,Canvas API的上下文对象是通过获取要绘制的 {{htmlelement("canvas")}} 元素的引用来创建的,然后调用它的{{domxref("HTMLCanvasElement.getContext()")}}方法:
+其他 API 具有稍微复杂的入口点,通常涉及为要编写的 API 代码创建特定的上下文。例如,Canvas API 的上下文对象是通过获取要绘制的 {{htmlelement("canvas")}} 元素的引用来创建的,然后调用它的{{domxref("HTMLCanvasElement.getContext()")}}方法:
var canvas = document.querySelector('canvas'); var ctx = canvas.getContext('2d');-然后,我们想通过调用内容对象 (它是{{domxref("CanvasRenderingContext2D")}}的一个实例)的属性和方法来实现我们想要对画布进行的任何操作, 例如:
+然后,我们想通过调用内容对象 (它是{{domxref("CanvasRenderingContext2D")}}的一个实例) 的属性和方法来实现我们想要对画布进行的任何操作,例如:
Ball.prototype.draw = function() { ctx.beginPath(); @@ -228,9 +228,9 @@它们有可识别的入口点
它们使用事件来处理状态的变化
-我们之前已经在课程中讨论了事件,在我们的 事件介绍文章中 - 详细介绍了客户端Web事件是什么以及它们在代码中的用法。如果您还不熟悉客户端Web API事件的工作方式,则应继续阅读。
+我们之前已经在课程中讨论了事件,在我们的 事件介绍文章中 - 详细介绍了客户端 Web 事件是什么以及它们在代码中的用法。如果您还不熟悉客户端 Web API 事件的工作方式,则应继续阅读。
-一些Web API不包含事件,但有些包含一些事件。当事件触发时,允许我们运行函数的处理程序属性通常在单独的 “Event handlers”(事件处理程序) 部分的参考资料中列出。作为一个简单的例子,
+XMLHttpRequest
对象的实例 (每一个实例都代表一个到服务器的HTTP请求,来取得某种新的资源)都有很多事件可用,例如onload
事件在成功返回时就触发包含请求的资源,并且现在就可用。一些 Web API 不包含事件,但有些包含一些事件。当事件触发时,允许我们运行函数的处理程序属性通常在单独的“Event handlers”(事件处理程序) 部分的参考资料中列出。作为一个简单的例子,
XMLHttpRequest
对象的实例 (每一个实例都代表一个到服务器的 HTTP 请求,来取得某种新的资源)都有很多事件可用,例如onload
事件在成功返回时就触发包含请求的资源,并且现在就可用。下面的代码提供了一个简单的例子来说明如何使用它:
@@ -250,19 +250,19 @@它们使用事件来处理
注意:您可以在我们的ajax.html示例中看到此代码 (或者 在线运行版本 see it live also).
-前五行指定了我们要获取的资源的位置,使用
+XMLHttpRequest()
构造函数创建请求对象的新实例 ,打开HTTP 的GET
请求以取得指定资源,指定响应以JSON格式发送,然后发送请求。前五行指定了我们要获取的资源的位置,使用
-XMLHttpRequest()
构造函数创建请求对象的新实例 ,打开 HTTP 的GET
请求以取得指定资源,指定响应以 JSON 格式发送,然后发送请求。然后
+onload
处理函数指定我们如何处理响应。 我们知道请求会成功返回,并在需要加载事件(如onload
事件)之后可用(除非发生错误),所以我们将包含返回的JSON的响应保存在superHeroes
变量中,然后将其传递给两个不同的函数以供进一步处理。然后
onload
处理函数指定我们如何处理响应。我们知道请求会成功返回,并在需要加载事件(如onload
事件)之后可用(除非发生错误),所以我们将包含返回的 JSON 的响应保存在superHeroes
变量中,然后将其传递给两个不同的函数以供进一步处理。它们在适当的地方有额外的安全机制
-WebAPI功能受到与JavaScript和其他Web技术(例如同源政策)相同的安全考虑 但是他们有时会有额外的安全机制。例如,一些更现代的WebAPI将只能在通过HTTPS提供的页面上工作,因为它们正在传输潜在的敏感数据(例如 服务工作者 和 推送)。
+WebAPI 功能受到与 JavaScript 和其他 Web 技术(例如同源政策)相同的安全考虑 但是他们有时会有额外的安全机制。例如,一些更现代的 WebAPI 将只能在通过 HTTPS 提供的页面上工作,因为它们正在传输潜在的敏感数据(例如 服务工作者 和 推送)。
-另外,一旦调用WebAPI请求,用户就可以在您的代码中启用一些WebAPI请求权限。作为一个例子,在加载我们之前的Geolocation 示例时,您可能注意到了类似下面的对话框 :
+另外,一旦调用 WebAPI 请求,用户就可以在您的代码中启用一些 WebAPI 请求权限。作为一个例子,在加载我们之前的Geolocation 示例时,您可能注意到了类似下面的对话框 :
-该 通知API 请求以类似的方式许可:
+该 通知 API 请求以类似的方式许可:
@@ -270,6 +270,6 @@它们在适当的地
概要
-在这一点上,您应该对API是什么,它们是如何工作的以及在JavaScript代码中可以对它们做什么有一个很好的了解。你可能很兴奋开始用特定的API来做一些有趣的事情,so let's go! 接下来,我们将看到使用文档对象模型(DOM)处理文档。
+在这一点上,您应该对 API 是什么,它们是如何工作的以及在 JavaScript 代码中可以对它们做什么有一个很好的了解。你可能很兴奋开始用特定的 API 来做一些有趣的事情,so let's go! 接下来,我们将看到使用文档对象模型(DOM)处理文档。
{{NextMenu("Learn/JavaScript/Client-side_Web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_Web_API")}}
diff --git a/files/zh-cn/learn/javascript/client-side_web_apis/manipulating_documents/index.html b/files/zh-cn/learn/javascript/client-side_web_apis/manipulating_documents/index.html index 0be8c627a7ab47..1d70e5d6f5eda0 100644 --- a/files/zh-cn/learn/javascript/client-side_web_apis/manipulating_documents/index.html +++ b/files/zh-cn/learn/javascript/client-side_web_apis/manipulating_documents/index.html @@ -7,42 +7,42 @@{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Introduction", "Learn/JavaScript/Client-side_web_APIs/Fetching_data", "Learn/JavaScript/Client-side_web_APIs")}}-在编写web页面或应用时,你最想做的事情之一就是以某种方式操作文档结构。这通常使用一套大量使用{{domxref("Document")}}对象来控制HTML和样式信息的文档对象模型(DOM)来实现,在本文中,我们可以更详细的看到怎样使用DOM,连同一些其他有趣的API以有趣的方式改变你的环境
+在编写 web 页面或应用时,你最想做的事情之一就是以某种方式操作文档结构。这通常使用一套大量使用{{domxref("Document")}}对象来控制 HTML 和样式信息的文档对象模型(DOM)来实现,在本文中,我们可以更详细的看到怎样使用 DOM,连同一些其他有趣的 API 以有趣的方式改变你的环境
-
- 前提: -基础的计算机常识,基本了解HTML、CSS和JavaScript - 包括JavaScript对象。 +前提: +基础的计算机常识,基本了解 HTML、CSS 和 JavaScript - 包括 JavaScript 对象。 - 目标: -熟悉核心DOM API, 以及其他和DOM与文档操作相关的常见API。 +目标: +熟悉核心 DOM API, 以及其他和 DOM 与文档操作相关的常见 API。 web浏览器的重要部分
+web 浏览器的重要部分
-web浏览器的软件中有很多活动的程序片段,而许多片段web开发人员无法使用JavaScript来控制或操作,因此Web浏览器是一个很复杂的软件组合。你可能认为这样的限制是不是好事,但是浏览器被锁定是有充分理由的,主要集中在安全方面。如果一个网站可以访问您存储的密码或其他敏感信息,犹如你一样登录到网站,试想会发生什么?
+web 浏览器的软件中有很多活动的程序片段,而许多片段 web 开发人员无法使用 JavaScript 来控制或操作,因此 Web 浏览器是一个很复杂的软件组合。你可能认为这样的限制是不是好事,但是浏览器被锁定是有充分理由的,主要集中在安全方面。如果一个网站可以访问您存储的密码或其他敏感信息,犹如你一样登录到网站,试想会发生什么?
-尽管有局限性,Web API仍然允许我们访问许多的功能,使我们用web页做很多事情。有几个在代码中经常引用的非常明显的部位 - 下面的图表表示了直接出现在web页面视图中的浏览器的主要部分:
+尽管有局限性,Web API 仍然允许我们访问许多的功能,使我们用 web 页做很多事情。有几个在代码中经常引用的非常明显的部位 - 下面的图表表示了直接出现在 web 页面视图中的浏览器的主要部分:
-
- window是载入浏览器的标签,在JavaScript中用{{domxref("Window")}}对象来表示,使用这个对象的可用方法,你可以返回窗口的大小(参见{{domxref("Window.innerWidth")}}和{{domxref("Window.innerHeight")}}),操作载入窗口的文档,存储客户端上文档的特殊数据(例如使用本地数据库或其他存储设备),为当前窗口绑定event handler,等等。
-- navigator表示浏览器存在于web上的状态和标识(即用户代理)。在JavaScript中,用{{domxref("Navigator")}}来表示。你可以用这个对象获取一些信息,比如来自用户摄像头的地理信息、用户偏爱的语言、多媒体流等等。
-- document(在浏览器中用DOM表示)是载入窗口的实际页面,在JavaScript中用{{domxref("Document")}} 对象表示,你可以用这个对象来返回和操作文档中HTML和CSS上的信息。例如获取DOM中一个元素的引用,修改其文本内容,并应用新的样式,创建新的元素并添加为当前元素的子元素,甚至把他们一起删除。
+- window 是载入浏览器的标签,在 JavaScript 中用{{domxref("Window")}}对象来表示,使用这个对象的可用方法,你可以返回窗口的大小(参见{{domxref("Window.innerWidth")}}和{{domxref("Window.innerHeight")}}),操作载入窗口的文档,存储客户端上文档的特殊数据(例如使用本地数据库或其他存储设备),为当前窗口绑定event handler,等等。
+- navigator 表示浏览器存在于 web 上的状态和标识(即用户代理)。在 JavaScript 中,用{{domxref("Navigator")}}来表示。你可以用这个对象获取一些信息,比如来自用户摄像头的地理信息、用户偏爱的语言、多媒体流等等。
+- document(在浏览器中用 DOM 表示)是载入窗口的实际页面,在 JavaScript 中用{{domxref("Document")}} 对象表示,你可以用这个对象来返回和操作文档中 HTML 和 CSS 上的信息。例如获取 DOM 中一个元素的引用,修改其文本内容,并应用新的样式,创建新的元素并添加为当前元素的子元素,甚至把他们一起删除。
在本文中,我们主要关注操作文档,但是也会稍微关注一下其他有用的部位。
文档对象模型
-在浏览器标签中当前载入的文档用文档对象模型来表示。这是一个由浏览器生成的“树结构”,使编程语言可以很容易的访问HTML结构 — 例如浏览器自己在呈现页面时,使用它将样式和其他信息应用于正确的元素,而页面呈现完成以后,开发人员可以用JavaScript操作DOM。
+在浏览器标签中当前载入的文档用文档对象模型来表示。这是一个由浏览器生成的“树结构”,使编程语言可以很容易的访问 HTML 结构 — 例如浏览器自己在呈现页面时,使用它将样式和其他信息应用于正确的元素,而页面呈现完成以后,开发人员可以用 JavaScript 操作 DOM。
-我们已经创建一个简单的例子dom-example.html (see it live also). 在你的浏览器中打开它 — 这是一个很简单的页面,包含了一个{{htmlelement("section")}} 元素,里面有一个图像和有链接的段落。HTML源码如下:
+我们已经创建一个简单的例子dom-example.html (see it live also). 在你的浏览器中打开它 — 这是一个很简单的页面,包含了一个{{htmlelement("section")}} 元素,里面有一个图像和有链接的段落。HTML 源码如下:
<!DOCTYPE html> <html> @@ -58,53 +58,53 @@-文档对象模型
</body> </html>另一方面,DOM树如下所示:
+另一方面,DOM 树如下所示:
-注意: 这个DOM树状图是用Ian Hickson的Live DOM viewer生成的
+注意: 这个 DOM 树状图是用 Ian Hickson 的Live DOM viewer生成的
这里你可以看到,文档中每个元素和文本在树中都有它们自己的入口 — 称之为节点。你将用不同的术语来描述节点的类型和它们相对于其他节点的位置:
-
-- 元素节点: 一个元素,存在于DOM中。
-- 根节点: 树中顶层节点,在HTML的情况下,总是一个
+HTML
节点(其他标记词汇,如SVG和定制XML将有不同的根元素)。- 元素节点: 一个元素,存在于 DOM 中。
+- 根节点: 树中顶层节点,在 HTML 的情况下,总是一个
HTML
节点(其他标记词汇,如 SVG 和定制 XML 将有不同的根元素)。- 子节点: 直接位于另一个节点内的节点。例如上面例子中,
IMG
是SECTION
的子节点。- 后代节点: 位于另一个节点内任意位置的节点。例如 上面例子中,
IMG
是SECTION
的子节点,也是一个后代节点。IMG
不是BODY
的子节点,因为它在树中低了BODY
两级,但它是BODY
的后代之一。- 父节点: 里面有另一个节点的节点。例如上面的例子中
-BODY
是SECTION
的父节点。- 兄弟节点: DOM树中位于同一等级的节点。例如上面例子中,
+IMG
和P
是兄弟。- 兄弟节点: DOM 树中位于同一等级的节点。例如上面例子中,
IMG
和P
是兄弟。- 文本节点: 包含文字串的节点
在用DOM工作之前,熟悉这些术语是很有用的,因为你将会遇到大量代码术语的使用。你在研究CSS时也会遇到这些术语(例如后代选择器、子选择器)
+在用 DOM 工作之前,熟悉这些术语是很有用的,因为你将会遇到大量代码术语的使用。你在研究 CSS 时也会遇到这些术语(例如后代选择器、子选择器)
-主动学习: 基本的DOM 操作
+主动学习:基本的 DOM 操作
-要开始学习DOM操作,我们先做一个实际的例子。
+要开始学习 DOM 操作,我们先做一个实际的例子。
- 本地备份dom-example.html page和与之相关的image。
- 在闭合的
-</body>
标签上面加入<script></script>
元素。- 要操作DOM内的元素,首先需要选择它,并将它的引用存储在一个变量中。在script元素中,添加下列代码行: +
- 要操作 DOM 内的元素,首先需要选择它,并将它的引用存储在一个变量中。在 script 元素中,添加下列代码行:
-var link = document.querySelector('a');- 现在你有了一个存储在变量中的元素引用,你可以使用它的可用属性和方法来操作它(在{{htmlelement("a")}}元素的情况下定义为接口{{domxref("HTMLAnchorElement")}},它更常常用的父接口是{{domxref("HTMLElement")}}和表示DOM中所有节点的{{domxref("Node")}})。首先,更新 {{domxref("Node.textContent")}}属性的值来修改链接中的文字。在上面的代码后面加入一行代码: +
- 现在你有了一个存储在变量中的元素引用,你可以使用它的可用属性和方法来操作它(在{{htmlelement("a")}}元素的情况下定义为接口{{domxref("HTMLAnchorElement")}},它更常常用的父接口是{{domxref("HTMLElement")}}和表示 DOM 中所有节点的{{domxref("Node")}})。首先,更新 {{domxref("Node.textContent")}}属性的值来修改链接中的文字。在上面的代码后面加入一行代码:
-link.textContent = 'Mozilla Developer Network';- 我们也能修改链接指向的URL,使得它被点击时不会走向错误的位置。在底部再加入下列代码: +
- 我们也能修改链接指向的 URL,使得它被点击时不会走向错误的位置。在底部再加入下列代码:
link.href = 'https://developer.mozilla.org';--注意,和JavaScript中的许多事情一样,有很多方法可以选择一个元素,并在一个变量中存储一个引用。{{domxref("Document.querySelector()")}}是推荐的主流方法,它允许你使用CSS选择器选择元素,使用很方便。上面的
+querySelector()
调用会匹配它在文档中遇到的第一个{{htmlelement("a")}}元素。如果想对多个元素进行匹配和操作,你可以使用{{domxref("Document.querySelectorAll()")}},这个方法匹配文档中每个匹配选择器的元素,并把它们的引用存储在一个array中。注意,和 JavaScript 中的许多事情一样,有很多方法可以选择一个元素,并在一个变量中存储一个引用。{{domxref("Document.querySelector()")}}是推荐的主流方法,它允许你使用 CSS 选择器选择元素,使用很方便。上面的
querySelector()
调用会匹配它在文档中遇到的第一个{{htmlelement("a")}}元素。如果想对多个元素进行匹配和操作,你可以使用{{domxref("Document.querySelectorAll()")}},这个方法匹配文档中每个匹配选择器的元素,并把它们的引用存储在一个array中。对于获取元素引用,还有一些更旧的方法,如:
-
@@ -116,7 +116,7 @@- {{domxref("Document.getElementById()")}},选择一个
+id
属性值已知的元素,例如<p id="myId">My paragraph</p>
。ID作为参数传递给函数,即var elementRef = document.getElementById('myId')
。- {{domxref("Document.getElementById()")}},选择一个
id
属性值已知的元素,例如<p id="myId">My paragraph</p>
。ID 作为参数传递给函数,即var elementRef = document.getElementById('myId')
。- {{domxref("Document.getElementsByTagName()")}},返回页面中包含的所有已知类型元素的数组。如
<p>
s,<a>
。元素类型作为参数传递给函数,即var elementRefArray = document.getElementsByTagName('p')
.创建并放置新的节点
以上只是让你稍微尝试一下你可以做的事情,让我们进一步看看我们可以怎样来创建新的元素。
-
-- 回到当前的例子,我们先获取到{{htmlelement("section")}}元素的引用 — 在已有script中添加下列代码(其他代码也同样处理): +
- 回到当前的例子,我们先获取到{{htmlelement("section")}}元素的引用 — 在已有 script 中添加下列代码(其他代码也同样处理):
var sect = document.querySelector('section');- 现在用{{domxref("Document.createElement()")}}创建一个新的段落,用与之前相同的方法赋予相同的文本: @@ -135,17 +135,17 @@
创建并放置新的节点
这是给DOM添加节点要做的大部分工作 — 在构建动态接口时,你将做大量使用这些方法(我们在后面可以看到一些例子)。
+这是给 DOM 添加节点要做的大部分工作 — 在构建动态接口时,你将做大量使用这些方法(我们在后面可以看到一些例子)。
移动和删除元素
-也许有时候你想移动或从DOM中删除节点,这是完全可能的。
+也许有时候你想移动或从 DOM 中删除节点,这是完全可能的。
-如果你想把具有内部链接的段落移到sectioin的底部,简单的做法是:
+如果你想把具有内部链接的段落移到 sectioin 的底部,简单的做法是:
sect.appendChild(linkPara);-这样可以把段落下移到section的底部。你可能想过要做第二个副本,但是情况并非如此 —
+linkPara
是指向该段落唯一副本的引用。如果你想做一个副本并也把它添加进去,只能用{{domxref("Node.cloneNode()")}} 方法来替代。这样可以把段落下移到 section 的底部。你可能想过要做第二个副本,但是情况并非如此 —
linkPara
是指向该段落唯一副本的引用。如果你想做一个副本并也把它添加进去,只能用{{domxref("Node.cloneNode()")}} 方法来替代。删除节点也非常的简单,至少,你拥有要删除的节点和其父节点的引用。在当前情况下,我们只要使用{{domxref("Node.removeChild()")}}即可,如下:
@@ -159,7 +159,7 @@移动和删除元素
操作样式
-通过JavaScript以不同的方式来操作CSS样式是可能的。
+通过 JavaScript 以不同的方式来操作 CSS 样式是可能的。
首先,使用 {{domxref("Document.stylesheets")}}返回{{domxref("CSSStyleSheet")}}数组,获取绑定到文档的所有样式表的序列。然后添加/删除想要的样式。然而,我们并不想扩展这些特性,因此它们在操作样式方面有点陈旧和困难,而现在有了更容易的方法。
@@ -179,14 +179,14 @@操作样式
-注意: CSS样式的JavaSript属性版本以小驼峰式命名法书写,而CSS版本带连接符号(
+backgroundColor
对background-color
)。确保你不会混淆,否则就不能工作。注意: CSS 样式的 JavaSript 属性版本以小驼峰式命名法书写,而 CSS 版本带连接符号(
backgroundColor
对background-color
)。确保你不会混淆,否则就不能工作。现在我们来看看另一个操作文档样式的常用方法。
-
-- 删除之前添加到JavaScript中的五行代码。
-- 在HTML的{{htmlelement("head")}}中添加下列代码 : +
- 删除之前添加到 JavaScript 中的五行代码。
+- 在 HTML 的{{htmlelement("head")}}中添加下列代码 :
-<style> .highlight { color: white; @@ -197,42 +197,42 @@操作样式
} </style>- 现在我们改为使用HTML操作的常用方法 — {{domxref("Element.setAttribute()")}} — 这里有两个参数,你想在元素上设置的属性,你要为它设置的值。在这种情况下,我们在段落中设置类名为highlight: +
- 现在我们改为使用 HTML 操作的常用方法 — {{domxref("Element.setAttribute()")}} — 这里有两个参数,你想在元素上设置的属性,你要为它设置的值。在这种情况下,我们在段落中设置类名为 highlight:
-para.setAttribute('class', 'highlight');- 刷新页面,看不到改变 — CSS仍然应用到段落,但是这次给出CSS规则选择的类不是内联CSS样式。
+- 刷新页面,看不到改变 — CSS 仍然应用到段落,但是这次给出 CSS 规则选择的类不是内联 CSS 样式。
两种方式各有优缺点,选择哪种取决于你自己。第一种方式无需安装,适合简单应用,第二种方式更加正统(没有CSS和JavaScript的混合,没有内联样式,而这些被认为是不好的体验)。当你开始构建更大更具吸引力的应用时,你可能会更多地使用第二种方法,但这完全取决于你自己。
+两种方式各有优缺点,选择哪种取决于你自己。第一种方式无需安装,适合简单应用,第二种方式更加正统(没有 CSS 和 JavaScript 的混合,没有内联样式,而这些被认为是不好的体验)。当你开始构建更大更具吸引力的应用时,你可能会更多地使用第二种方法,但这完全取决于你自己。
-在这一点上,我们还没有做任何有用的事!使用JavaScript创建静态内容是毫无意义的 — 最好将其写入HTML,而不使用JavaScript。用JavaScript创建内容也有其他问题(如不能被搜索引擎读取),比HTML复杂得多。
+在这一点上,我们还没有做任何有用的事!使用 JavaScript 创建静态内容是毫无意义的 — 最好将其写入 HTML,而不使用 JavaScript。用 JavaScript 创建内容也有其他问题(如不能被搜索引擎读取),比 HTML 复杂得多。
-在接下来的几节中我们将看看DOM API一些更实际的用途。
+在接下来的几节中我们将看看 DOM API 一些更实际的用途。
--注意: 你可以在GitHub上找到演示程序finished version of the dom-example.html (see it live also).
+注意: 你可以在 GitHub 上找到演示程序finished version of the dom-example.html (see it live also).
主动学习:从Window对象中获取有用的信息
+主动学习:从 Window 对象中获取有用的信息
-到目前为止,我们只真正看到使用{{domxref("Node")}}和{{domxref("Document")}} 特性来操纵文档,但是没有理由不能从其他来源获取数据并在UI中使用它。想想我们最新文件中的演示例子 maps-example.html — 那里我们获取一些位置数据并用来显示你所在区域的地图。你只要确保你的数据格式正确;使用JavaScript比其他许多语言更容易,因为它是弱类型的——例如,当你想把它们打印到屏幕上时,数字会自动转换成字符串。
+到目前为止,我们只真正看到使用{{domxref("Node")}}和{{domxref("Document")}} 特性来操纵文档,但是没有理由不能从其他来源获取数据并在 UI 中使用它。想想我们最新文件中的演示例子 maps-example.html — 那里我们获取一些位置数据并用来显示你所在区域的地图。你只要确保你的数据格式正确;使用 JavaScript 比其他许多语言更容易,因为它是弱类型的——例如,当你想把它们打印到屏幕上时,数字会自动转换成字符串。
在这个例子中,我们解决了一个常见的问题 — 不管窗口的大小是多少,确保应用程序和它所在的窗口视图一样大。在玩游戏的情况下,想在游戏中尽可能多地使用屏幕区域,这种方法是很有用的。
-一开始,要做一个window-resize-example.html和bgtile.png文件的本地拷贝。打开文件看一看 — 你可以看到我们用一个{{htmlelement("div")}}元素包裹屏幕的小部分,用来获得应用的background tile。我们也用它来表示应用的UI区域。
+一开始,要做一个window-resize-example.html和bgtile.png文件的本地拷贝。打开文件看一看 — 你可以看到我们用一个{{htmlelement("div")}}元素包裹屏幕的小部分,用来获得应用的 background tile。我们也用它来表示应用的 UI 区域。
-
- 首先,获取这个div的引用,然后获取视窗(显示文档的内部窗口)的宽度和高度, 并存入变量中 — 这两个值包含在{{domxref("Window.innerWidth")}} 和 {{domxref("Window.innerHeight")}}属性中。在已存在的{{htmlelement("script")}}元素中加入下列代码: +
- 首先,获取这个 div 的引用,然后获取视窗(显示文档的内部窗口)的宽度和高度,并存入变量中 — 这两个值包含在{{domxref("Window.innerWidth")}} 和 {{domxref("Window.innerHeight")}}属性中。在已存在的{{htmlelement("script")}}元素中加入下列代码:
-var div = document.querySelector('div'); var WIDTH = window.innerWidth; var HEIGHT = window.innerHeight;- 接下来,我们将动态地改变div的宽度和高度,使其等于视窗的宽度和高度。 在您的代码下面添加以下两行: +
- 接下来,我们将动态地改变 div 的宽度和高度,使其等于视窗的宽度和高度。在您的代码下面添加以下两行:
-div.style.width = WIDTH + 'px'; div.style.height = HEIGHT + 'px';- 保存并刷新浏览器 — 现在可以看到不管你使用什么大小的屏幕,div变得和视窗一样大。如果要调整窗口大小使其更大,你可以看到div会保持相同大小 — 因为我们只能设置一次。
-- 在我们调整窗口时,我们怎样用事件来调整div的大小? {{domxref("Window")}}对象有一个称为resize的可用事件。每次窗口调整大小时都会触发该事件 — 我们可以通过{{domxref("Window.onresize")}} 事件处理程序来访问它,并返回每次改变大小的代码。在代码底部添加下列程序: +
- 保存并刷新浏览器 — 现在可以看到不管你使用什么大小的屏幕,div 变得和视窗一样大。如果要调整窗口大小使其更大,你可以看到 div 会保持相同大小 — 因为我们只能设置一次。
+- 在我们调整窗口时,我们怎样用事件来调整 div 的大小? {{domxref("Window")}}对象有一个称为 resize 的可用事件。每次窗口调整大小时都会触发该事件 — 我们可以通过{{domxref("Window.onresize")}} 事件处理程序来访问它,并返回每次改变大小的代码。在代码底部添加下列程序:
window.onresize = function() { WIDTH = window.innerWidth; HEIGHT = window.innerHeight; @@ -246,7 +246,7 @@主动学习:
注意: 如果你被卡住了,可查看finished window resize example (see it live also).
主动学习: 一个动态的购物单
+主动学习:一个动态的购物单
作为文章的收尾,我们想给你一个小小的挑战 — 我们要做一个简单的购物单的例子,使用表单的输入框和按钮动态的向购物单中添加购物项。在输入中添加项,然后按下按钮:
@@ -256,23 +256,23 @@主动学习: 一个动态的购
- 输入框应该是空白的并已聚焦,为你准备好输入另一个项。
-完成后的演示程序看起来有点像这样的:
+完成后的演示程序看起来有点像这样的:
要完成实验,要按照下面的步骤,确保购物单的行为如上所述。
-
@@ -282,7 +282,7 @@- 首先,下载shopping-list.html文件,并存入本地。你会看到它有一些极小的CSS,一个带有label、input和button的list和一个空的list以及{{htmlelement("script")}} 元素。要添加的所有程序都在script里面。
-- 创建三个变量来保存list({{htmlelement("ul")}})、{{htmlelement("input")}}和{{htmlelement("button")}}元素的引用。
+- 首先,下载shopping-list.html文件,并存入本地。你会看到它有一些极小的 CSS,一个带有 label、input 和 button 的 list 和一个空的 list 以及{{htmlelement("script")}} 元素。要添加的所有程序都在 script 里面。
+- 创建三个变量来保存 list({{htmlelement("ul")}})、{{htmlelement("input")}}和{{htmlelement("button")}}元素的引用。
- 创建一个函数响应点击按钮。
- 在函数体内,开始要在一个变量中存储输入框的当前值。
- 然后,为输入框元素设置空字符 -
-''
使其为空- 创建三个新元素 — 一个list项({{htmlelement('li')}}),{{htmlelement('span')}}和 {{htmlelement('button')}},并把它们存入变量之中。
-- 把span和button作为list项的子节点。
-- 把之前保存的输入框元素的值设置为span的文本内容,按钮的文本内容设置为'Delete'
-- 把list项设置为list的子节点。
-- 为删除按钮绑定事件处理程序。当点击按钮时,删除它所在的整个list项。
+- 创建三个新元素 — 一个 list 项({{htmlelement('li')}}),{{htmlelement('span')}}和 {{htmlelement('button')}},并把它们存入变量之中。
+- 把 span 和 button 作为 list 项的子节点。
+- 把之前保存的输入框元素的值设置为 span 的文本内容,按钮的文本内容设置为'Delete'
+- 把 list 项设置为 list 的子节点。
+- 为删除按钮绑定事件处理程序。当点击按钮时,删除它所在的整个 list 项。
- 最后,使用
focus()
方法聚焦输入框准备输入下一个购物项。主动学习: 一个动态的购
总结
-我们已经结束了对文档和DOM操作的研究。在这一点上,你应该了解Web浏览器在控制文档和用户Web体验的其他方面方面的重要部分。更重要的是,你应该了解什么是文档对象模型,怎样操作它来创建有用的功能。
+我们已经结束了对文档和 DOM 操作的研究。在这一点上,你应该了解 Web 浏览器在控制文档和用户 Web 体验的其他方面方面的重要部分。更重要的是,你应该了解什么是文档对象模型,怎样操作它来创建有用的功能。
另见
@@ -295,6 +295,6 @@另见
- {{domxref("HTMLElement")}}, {{domxref("HTMLInputElement")}}, {{domxref("HTMLImageElement")}}, etc.
-(MDN上有完整的Web API 列表,参见Web API接口参考 !)
+(MDN 上有完整的 Web API 列表,参见Web API 接口参考 !)
{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Introduction", "Learn/JavaScript/Client-side_web_APIs/Fetching_data", "Learn/JavaScript/Client-side_web_APIs")}}diff --git a/files/zh-cn/learn/javascript/client-side_web_apis/third_party_apis/index.html b/files/zh-cn/learn/javascript/client-side_web_apis/third_party_apis/index.html index 1bc0122a245b0d..a884bf3edd4711 100644 --- a/files/zh-cn/learn/javascript/client-side_web_apis/third_party_apis/index.html +++ b/files/zh-cn/learn/javascript/client-side_web_apis/third_party_apis/index.html @@ -11,7 +11,7 @@ ---{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Fetching_data", "Learn/JavaScript/Client-side_web_APIs/Drawing_graphics", "Learn/JavaScript/Client-side_web_APIs")}}-到目前为止我们已经介绍的API是内置在浏览器中的,但并不是所有的API都是。许多大型网站和服务(例如Google地图,Twitter,Facebook,PayPal等)提供的API允许开发者使用他们的数据(例如在博客上显示您的Twitter流)或服务(例如在您的网站上显示自定义Google地图,或者使用Facebook登录来登录你的用户)。本文着眼于浏览器API和第三方API的区别,并展示了后者的一些典型用途。
+到目前为止我们已经介绍的 API 是内置在浏览器中的,但并不是所有的 API 都是。许多大型网站和服务(例如 Google 地图,Twitter,Facebook,PayPal 等)提供的 API 允许开发者使用他们的数据(例如在博客上显示您的 Twitter 流)或服务(例如在您的网站上显示自定义 Google 地图,或者使用 Facebook 登录来登录你的用户)。本文着眼于浏览器 API 和第三方 API 的区别,并展示了后者的一些典型用途。
@@ -21,32 +21,32 @@
-目的: -学习了解第三方API的运作方式,以及如何运用它们来提高你的网站性能 +学习了解第三方 API 的运作方式,以及如何运用它们来提高你的网站性能 什么是第三方API?
+什么是第三方 API?
-第三方API是由第三方(通常是Facebook,Twitter或Google等公司)提供的API,允许您通过JavaScript访问其功能,并在您自己的站点上使用它。 正如我们在 API介绍章节 所展示的, 最显著的例子就是运用 Google Maps APIs 在你的网页上展示自定义地图。
+第三方 API 是由第三方(通常是 Facebook,Twitter 或 Google 等公司)提供的 API,允许您通过 JavaScript 访问其功能,并在您自己的站点上使用它。正如我们在 API 介绍章节 所展示的,最显著的例子就是运用 Google Maps APIs 在你的网页上展示自定义地图。
-让我们再来瞧一眼这个地图的例子 (see the source code on GitHub; see it live also), 从这里可以知道第三方API和浏览器API的区别是怎么样的。
+让我们再来瞧一眼这个地图的例子 (see the source code on GitHub; see it live also), 从这里可以知道第三方 API 和浏览器 API 的区别是怎么样的。
-Note: 您可能想要一次获得所有的代码示例,在这种情况下,您可以搜索repo来获取每个部分中需要的示例文件。
+Note: 您可能想要一次获得所有的代码示例,在这种情况下,您可以搜索 repo 来获取每个部分中需要的示例文件。
它们植根于第三方服务器
-浏览器API在浏览器构建之初就存在 — 用JavaScript就可以立即访问它们。例如, 例子中所使用的 Geolocation API 就是通过使用
+Navigator
对象的属性 geolocation 来访问的, 它返回一个名为Geolocation
的对象。 这个例子使用了这个对象的方法getCurrentPosition()
来请求当前设备所处的地点:浏览器 API 在浏览器构建之初就存在 — 用 JavaScript 就可以立即访问它们。例如,例子中所使用的 Geolocation API 就是通过使用
Navigator
对象的属性 geolocation 来访问的,它返回一个名为Geolocation
的对象。 这个例子使用了这个对象的方法getCurrentPosition()
来请求当前设备所处的地点:navigator.geolocation.getCurrentPosition(function(position) { ... });-第三方API,从某种角度讲,植根于第三方服务器上。要通过 JavaScript获取它们,您首先需要链接到其功能接口上并使其在您的页面上生效。通常来说,这首先需要您通过一个 {{htmlelement("script")}} 元素连接到第三方服务器所开放的JavaScript库,如下所示:
+第三方 API,从某种角度讲,植根于第三方服务器上。要通过 JavaScript 获取它们,您首先需要链接到其功能接口上并使其在您的页面上生效。通常来说,这首先需要您通过一个 {{htmlelement("script")}} 元素连接到第三方服务器所开放的 JavaScript 库,如下所示:
<script type="text/javascript" src="https://maps.google.com/maps/api/js?key=AIzaSyDDuGt0E5IEGkcE6ZfrKfUtE9Ko_de66pA"></script>-然后您便可使用该库中可用的对象了,如:
+然后您便可使用该库中可用的对象了,如:
var latlng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude); var myOptions = { @@ -58,35 +58,35 @@它们植根于第三方服务器
-代码中我们用
+google.maps.LatLng()
构造器创建了一个新的LatLng
对象,它包含了我们想展示的地址的纬度和经度,作为一个Geolocation API返回。然后,我们创建了包含这个对象,和其他有关地图显示信息的选项对象(myOptions
) 。最后,用google.maps.Map()
构造器创建了map
对象,它接受网页元素(地图展示处)和选项对象两个参数。代码中我们用
-google.maps.LatLng()
构造器创建了一个新的LatLng
对象,它包含了我们想展示的地址的纬度和经度,作为一个 Geolocation API 返回。然后,我们创建了包含这个对象,和其他有关地图显示信息的选项对象 (myOptions
) 。最后,用google.maps.Map()
构造器创建了map
对象,它接受网页元素(地图展示处)和选项对象两个参数。以上就是用 Google Maps API 建立一个简单地图所需要的所有信息。所有复杂的工作都全由你所连接的第三方服务器处理,包括展示正确地理位置的地图块,等等。
+以上就是用 Google Maps API 建立一个简单地图所需要的所有信息。所有复杂的工作都全由你所连接的第三方服务器处理,包括展示正确地理位置的地图块,等等。
-Note: 一些api处理对其功能的访问略有不同,相反,它们要求开发人员向特定的URL模式发出HTTP请求(参见从服务器获取数据),以检索特定的数据。这些被称为RESTful api,稍后我们将在文章中展示这个示例。
+Note: 一些 api 处理对其功能的访问略有不同,相反,它们要求开发人员向特定的 URL 模式发出 HTTP 请求 (参见从服务器获取数据),以检索特定的数据。这些被称为 RESTful api,稍后我们将在文章中展示这个示例。
权限的不同处理方式
-正如我们在第一篇文章中所讨论的,浏览器api的安全性通常是通过权限提示。这样做的目的是为了让用户知道他们访问的网站上发生了什么,并且不太可能成为恶意使用API的人的受害者。
+正如我们在第一篇文章中所讨论的,浏览器 api 的安全性通常是通过权限提示。这样做的目的是为了让用户知道他们访问的网站上发生了什么,并且不太可能成为恶意使用 API 的人的受害者。
-第三方API有一个稍微不同的权限系统——它们倾向于使用关键代码来允许开发人员访问API功能。再次查看我们链接到的谷歌地图API库的URL:
+第三方 API 有一个稍微不同的权限系统——它们倾向于使用关键代码来允许开发人员访问 API 功能。再次查看我们链接到的谷歌地图 API 库的 URL:
https://maps.google.com/maps/api/js?key=AIzaSyDDuGt0E5IEGkcE6ZfrKfUtE9Ko_de66pA-URL末尾提供的URL参数是一个开发人员密钥—应用程序的开发人员必须应用它来获取一个密钥,然后以一种特定的方式将其包含在代码中,才能允许访问API的功能。对于谷歌映射(以及其他谷歌API),可以在谷歌云平台上申请一个密钥。
+URL 末尾提供的 URL 参数是一个开发人员密钥—应用程序的开发人员必须应用它来获取一个密钥,然后以一种特定的方式将其包含在代码中,才能允许访问 API 的功能。对于谷歌映射 (以及其他谷歌 API),可以在谷歌云平台上申请一个密钥。
-其他API的包含方式稍微不同,但是大多数API的模式都非常相似。
+其他 API 的包含方式稍微不同,但是大多数 API 的模式都非常相似。
-需要密钥的原因是:所用使用API功能的人都需要承担责任。当开发者注册一个密钥之后,如果他们开始恶意使用API(例如跟踪位置,试图用大量的垃圾邮件干扰用户正常工作),此时API的提供者可以采取措施。最简单的措施是撤销开发者的API的使用权。
+需要密钥的原因是:所用使用 API 功能的人都需要承担责任。当开发者注册一个密钥之后,如果他们开始恶意使用 API(例如跟踪位置,试图用大量的垃圾邮件干扰用户正常工作),此时 API 的提供者可以采取措施。最简单的措施是撤销开发者的 API 的使用权。
-扩展the Google Maps示例
+扩展 the Google Maps 示例
-现在我们已经检验了Google Maps API示例以及它的运作方式,让我们添加一些更多的功能来展示如何使用API的其他特性。
+现在我们已经检验了 Google Maps API 示例以及它的运作方式,让我们添加一些更多的功能来展示如何使用 API 的其他特性。
- -
要开始这个部分, 确保你已经在一个新的目录复制 Google Maps启动文件。 如果你已经 克隆了示例存储库,那么你已经拥有了一个这个文件的拷贝,你可以在javascript/apis/third-party-apis/google-maps目录中找到该文件。
+要开始这个部分,确保你已经在一个新的目录复制 Google Maps 启动文件。 如果你已经 克隆了示例存储库,那么你已经拥有了一个这个文件的拷贝,你可以在javascript/apis/third-party-apis/google-maps目录中找到该文件。
接下来,用以下步骤获取你自己的开发者密钥:
@@ -97,41 +97,41 @@扩展the Google Maps示例
- 单击“启用 API”按钮。
- 选择Google Maps JavaScript API.
- 单击“启用”按钮。
-- 单击创建凭据,然后选择API密钥。
-- 复制你的API密钥并将示例中的第一个{{htmlelement("script")}}元素中的现有密钥替换为你自己的密钥。(位于
+?key=
和属性结束引号标记 ("
)之间的位置。)- 单击创建凭据,然后选择 API 密钥。
+- 复制你的 API 密钥并将示例中的第一个{{htmlelement("script")}}元素中的现有密钥替换为你自己的密钥。(位于
?key=
和属性结束引号标记 ("
) 之间的位置。)- 打开你的Google Maps起始文件,找到
+INSERT-YOUR-API-KEY-HERE
字符串,然后将其替换为你从Google Cloud Platform API Manager dashboard获取的实际API密钥。- 打开你的 Google Maps 起始文件,找到
INSERT-YOUR-API-KEY-HERE
字符串,然后将其替换为你从 Google Cloud Platform API Manager dashboard 获取的实际 API 密钥。添加自定义标记
-添加一个标记在地图上(icon)在某种程度上是很容易的,你只需要创建一个新的标记使用google.maps.Marker()构造函数,传递给它一个包含位置显示标记的选择对象(如LatLng对象),和Map对象来显示它。
+添加一个标记在地图上 (icon) 在某种程度上是很容易的,你只需要创建一个新的标记使用 google.maps.Marker() 构造函数,传递给它一个包含位置显示标记的选择对象 (如 LatLng 对象),和 Map 对象来显示它。
@@ -153,16 +153,16 @@
- -
在
+var map ...
行下面添加下列代码:在
var map ...
行下面添加下列代码:var marker = new google.maps.Marker({ position: latlng, map: map });-现在如果你刷新你的页面, 你会看到地图中间弹出了一个小小的漂亮标记。这很酷, 但是这并不是一个定制的标记图标 — 它使用了默认的标记图标。
+现在如果你刷新你的页面,你会看到地图中间弹出了一个小小的漂亮标记。这很酷,但是这并不是一个定制的标记图标 — 它使用了默认的标记图标。
- -
如果要使用定制化的图标,我们需要在创建标记时通过URL来明确说明。首先,在刚才添加的代码块之后添加下面的代码:
+如果要使用定制化的图标,我们需要在创建标记时通过 URL 来明确说明。首先,在刚才添加的代码块之后添加下面的代码:
var iconBase = 'https://maps.google.com/mapfiles/kml/shapes/';-这定义了所有Google Maps官方图标存储的URL(如果你想的话你也可以使用你自己的图标存储位置)。
+这定义了所有 Google Maps 官方图标存储的 URL(如果你想的话你也可以使用你自己的图标存储位置)。
- -
图标的位置应当在选项对象的
+icon
属性中说明。更新Constructor并添加icon属性,如下:图标的位置应当在选项对象的
icon
属性中说明。更新 Constructor 并添加 icon 属性,如下:var marker = new google.maps.Marker({ position: latlng, @@ -139,7 +139,7 @@-添加自定义标记
map: map });这里我们用
+iconBase
加上图标的文件名,从而创建完整URL的方式阐明了icon属性。现在尝试重新加载你的例子,你会看到你的地图上显示了一个定制的标记!这里我们用
iconBase
加上图标的文件名,从而创建完整 URL 的方式阐明了 icon 属性。现在尝试重新加载你的例子,你会看到你的地图上显示了一个定制的标记!添加自定义标记
单击标记时显示弹出窗口
-Google地图的另一个常见用例是在点击其名称或标记时显示有关某个地点的更多信息(弹出式广告在Google Maps API中称为信息窗口)。 这也很容易实现,所以让我们来看看它。
+Google 地图的另一个常见用例是在点击其名称或标记时显示有关某个地点的更多信息(弹出式广告在 Google Maps API 中称为信息窗口)。这也很容易实现,所以让我们来看看它。
- -
首先,您需要指定一个包含HTML的JavaScript字符串,该字符串将定义弹出窗口的内容。 这将由API注入弹出窗口,并且可以包含您想要的任何内容。 在
+google.maps.Marker()
构造函数定义下面添加以下行:首先,您需要指定一个包含 HTML 的 JavaScript 字符串,该字符串将定义弹出窗口的内容。这将由 API 注入弹出窗口,并且可以包含您想要的任何内容。在
google.maps.Marker()
构造函数定义下面添加以下行:var contentString = '<div id="content"><h2 id="firstHeading" class="firstHeading">Custom info window</h2><p>This is a cool custom info window.</p></div>';- -
然后,你需要使用
+google.maps.InfoWindow()
构造器,创建一个新的info window object。在之前的代码下面,添加以下代码:然后,你需要使用
google.maps.InfoWindow()
构造器,创建一个新的 info window object。在之前的代码下面,添加以下代码:var infowindow = new google.maps.InfoWindow({ content: contentString @@ -171,7 +171,7 @@单击标记时显示弹出窗口
还有其他可用的属性 (查看 Info Windows), 但是在这里我们只具体说明指向内容源的content
属性。- -
@@ -340,19 +340,19 @@最后,为了在单击标记(marker)时显示弹出窗口,我们使用了一个简单的点击事件处理器。在
+google.maps.InfoWindow()
构造器代码下面,添加以下代码:最后,为了在单击标记 (marker) 时显示弹出窗口,我们使用了一个简单的点击事件处理器。在
google.maps.InfoWindow()
构造器代码下面,添加以下代码:marker.addListener('click', function() { infowindow.open(map, marker); @@ -190,7 +190,7 @@Controlling what map contro
- -
将其值设置为
+false
(或完全删除此属性),重新加载示例,将看到地图缩放按钮、 scale indicator等等。将其值设置为
false
(或完全删除此属性),重新加载示例,将看到地图缩放按钮、scale indicator 等等。现在撤销上一次更改。
@@ -209,28 +209,28 @@Controlling what map contro
就是现在 - 看看 Google Maps APIs documentation,发现更多乐趣!
-一个RESTful API — NYTimes
+一个 RESTful API — NYTimes
-现在让我们看看另一个API示例 - New York Times API。 此API允许您检索纽约时报的新闻故事信息并将其显示在您的网站上。 这种类型的API称为RESTful API - 我们不像使用Google地图那样使用JavaScript库的功能获取数据,而是通过向特定网址发出HTTP请求来获取数据,其中包含搜索术语和其他属性编码的数据 URL(通常作为URL参数)。 这是您在API中遇到的常见模式。
+现在让我们看看另一个 API 示例 - New York Times API。此 API 允许您检索纽约时报的新闻故事信息并将其显示在您的网站上。这种类型的 API 称为 RESTful API - 我们不像使用 Google 地图那样使用 JavaScript 库的功能获取数据,而是通过向特定网址发出 HTTP 请求来获取数据,其中包含搜索术语和其他属性编码的数据 URL(通常作为 URL 参数)。这是您在 API 中遇到的常见模式。
-使用第三方API的方法
+使用第三方 API 的方法
-下面我们将带您完成练习,向您展示如何使用NYTimes API,它还提供了一组更为通用的步骤,您可以将其用作处理新API的方法。
+下面我们将带您完成练习,向您展示如何使用 NYTimes API,它还提供了一组更为通用的步骤,您可以将其用作处理新 API 的方法。
查找文档
-当您想要使用第三方API时,必须找出文档的位置,以便了解API具有哪些功能,以及如何使用它们等等。NYTimes API文档位于 https://developer.nytimes.com/。
+当您想要使用第三方 API 时,必须找出文档的位置,以便了解 API 具有哪些功能,以及如何使用它们等等。NYTimes API 文档位于 https://developer.nytimes.com/。
获取一个开发者密钥
-出于安全性和问责制的原因,大多数API都要求您使用某种开发人员密钥。 要注册NYTimes API密钥,您需要访问 https://developer.nytimes.com/signup。
+出于安全性和问责制的原因,大多数 API 都要求您使用某种开发人员密钥。要注册 NYTimes API 密钥,您需要访问 https://developer.nytimes.com/signup。
@@ -442,7 +442,7 @@
- -
申请 "Article Search API" 的 API key ——新建一个应用,选择这个 API ,(填写名称和描述,打开 "Article Search API" 下面的开关,然后点击 “创建(Create)”)
+申请 "Article Search API" 的 API key ——新建一个应用,选择这个 API,(填写名称和描述,打开 "Article Search API" 下面的开关,然后点击“创建 (Create)”)
- -
从结果页面获取 API 。
+从结果页面获取 API。
现在开始构建这个应用,下载 nytimes_start.html 和 nytimes.css 到一个新的本地目录。如果已经克隆过这个仓库 cloned the examples repository, 里面就已经有这 2 个文件了,它们存放在 javascript/apis/third-party-apis/nytimes 目录下。HTML 文件里的
@@ -241,9 +241,9 @@<script>
标签下已经包含了构建这个应用需要用到的变量;下面我们来填写函数。获取一个开发者密钥
-将API连接到应用
+将 API 连接到应用
-首先,建立 API 和本地应用的连接。对于这个 API ,每次向服务器对应的 URL 发起 get 请求,都需要把 API key 作为 get 请求的参数。
+首先,建立 API 和本地应用的连接。对于这个 API,每次向服务器对应的 URL 发起 get 请求,都需要把 API key 作为 get 请求的参数。
-
- @@ -285,11 +285,11 @@
将API连接到应用
+
submitSearch()
设置起始页码为 0 ,然后调用fetchResults()
函数。其中,先调用事件对象的preventDefault()
函数,阻止实际的表单提交事件 (会破坏应用,至于为什么可以自己试一试)。然后,处理字符串,构建完整的请求 URL 。以下是几个必要的步骤:
submitSearch()
设置起始页码为 0,然后调用fetchResults()
函数。其中,先调用事件对象的preventDefault()
函数,阻止实际的表单提交事件 (会破坏应用,至于为什么可以自己试一试)。然后,处理字符串,构建完整的请求 URL。以下是几个必要的步骤:@@ -309,7 +309,7 @@
- 基本的 URL (
-baseURL
变量).- API key ,需要放到
+api-key
URL 参数里面去 (key
变量).- API key,需要放到
api-key
URL 参数里面去 (key
变量).- 页码,需要放到
page
URL 参数里面去 (pageNumber
变量).- 搜索项,需要放到
q
URL 参数里面去 (searchTerm
输入框的文字 {{htmlelement("input")}}).将API连接到应用
Note: 示例包含了基本的表单数据验证操作 — 表项提交之前必须有内容 (用
-required
属性实现),此外,日期字段有确定的pattern
属性,它们的值必须由 8 个数字组成 (pattern="[0-9]{8}"
),否则不能提交。更多细节参考 Form data validation从api请求数据
+从 api 请求数据
现在 URL 已经构造好了,下面向它发起请求。本例使用 Fetch API
@@ -404,7 +404,7 @@显示数据
添加分页按钮
-为了使分页按钮工作,我们将增加(或减少)
+pageNumber
变量的值,然后用页面 url 参数中包含的新值重新运行 fetch 请求。这么做是因为 NYTimes API 每次最多只返回 10 篇文章 — 如果查询结果超过 10 篇,而page
URL 参数设为 0 (或者忽略这个参数 — 0 是默认值),只返回前 10 篇 (0-9) ,后续的 10 篇 (10-19) 对应参数值 1 ,以此类推。为了使分页按钮工作,我们将增加(或减少)
pageNumber
变量的值,然后用页面 url 参数中包含的新值重新运行 fetch 请求。这么做是因为 NYTimes API 每次最多只返回 10 篇文章 — 如果查询结果超过 10 篇,而page
URL 参数设为 0 (或者忽略这个参数 — 0 是默认值),只返回前 10 篇 (0-9) ,后续的 10 篇 (10-19) 对应参数值 1,以此类推。根据这个特性就可以轻松实现一个简单的翻页函数。
@@ -434,7 +434,7 @@添加分页按钮
第一个函数很简单 — 增加
-pageNumber
变量,然后再次运行fetchResults()
函数 展示下一页的结果。第二个函数基本上执行相反的操作,不过有个额外的步骤是检测
+pageNumber
在 -1 之前是否已经是 0 — 如果 fetch 请求的page
URL 参数是负数,会导致错误。如果pageNumber
已经是 0 ,则直接执行return
退出函数,避免多余的计算。 (如果当前页面已经是首页,就不需要重新加载)。第二个函数基本上执行相反的操作,不过有个额外的步骤是检测
pageNumber
在 -1 之前是否已经是 0 — 如果 fetch 请求的page
URL 参数是负数,会导致错误。如果pageNumber
已经是 0,则直接执行return
退出函数,避免多余的计算。 (如果当前页面已经是首页,就不需要重新加载)。添加分页按钮
Note: 完整代码参考 finished nytimes API example code on GitHub (实例参考 see it running live here).
-YouTube示例
+YouTube 示例
我们还做了另外一个示例用来学习 — 参考 YouTube video search example. 这个示例用了下面 2 个 API:
@@ -451,7 +451,7 @@YouTube示例
- YouTube IFrame Player API ,把返回的视频查询结果展示到 IFrame 视频播放器里,然后就可以播放了。
-这个示例的有趣之处在于,它把两个第三方 API 结合起来做了一个应用。第一个 API 是 RESTful API ,而第二个 API 更像是 Mapquest (有 API 专用方法 (API-specific methods), etc.)。但是,值得注意的是,这两个 API 均需要将 JavaScript 库应用于该页面。RESTful API 自己有用于处理 HTTP 请求并返回结果的函数。
+这个示例的有趣之处在于,它把两个第三方 API 结合起来做了一个应用。第一个 API 是 RESTful API,而第二个 API 更像是 Mapquest (有 API 专用方法 (API-specific methods), etc.)。但是,值得注意的是,这两个 API 均需要将 JavaScript 库应用于该页面。RESTful API 自己有用于处理 HTTP 请求并返回结果的函数。
diff --git a/files/zh-cn/learn/javascript/client-side_web_apis/video_and_audio_apis/index.html b/files/zh-cn/learn/javascript/client-side_web_apis/video_and_audio_apis/index.html index 7c714ba8a71def..f348840af0e068 100644 --- a/files/zh-cn/learn/javascript/client-side_web_apis/video_and_audio_apis/index.html +++ b/files/zh-cn/learn/javascript/client-side_web_apis/video_and_audio_apis/index.html @@ -1,5 +1,5 @@ --- -title: 视频和音频API +title: 视频和音频 API slug: Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs translation_of: Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs --- @@ -7,22 +7,22 @@{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Drawing_graphics", "Learn/JavaScript/Client-side_web_APIs/Client-side_storage", "Learn/JavaScript/Client-side_web_APIs")}}-HTML5提供了用于在文档中嵌入富媒体的元素 — {{htmlelement("video")}}和{{htmlelement("audio")}} — 这些元素通过自带的API来控制视频或音频的播放,定位进度等。本文将向你展示如何执行一些常见的任务,如创建自定义播放控件。
+HTML5 提供了用于在文档中嵌入富媒体的元素 — {{htmlelement("video")}}和{{htmlelement("audio")}} — 这些元素通过自带的 API 来控制视频或音频的播放,定位进度等。本文将向你展示如何执行一些常见的任务,如创建自定义播放控件。
-
前提: -JavaScript基础(见JavaScript第一步,创建JavaScript代码块,JavaScript对象入门),Web API简介 +JavaScript 基础(见JavaScript 第一步,创建 JavaScript 代码块,JavaScript 对象入门),Web API 简介 目标: -学习如何通过浏览器API来控制视频和音频的播放。 +学习如何通过浏览器 API 来控制视频和音频的播放。 HTML5视频和音频
+HTML5 视频和音频
{{htmlelement("video")}}和{{htmlelement("audio")}}元素允许我们把视频和音频嵌入到网页当中。就像我们在音频和视频内容文中展示的一样,一个典型的实现如下所示:
@@ -36,17 +36,17 @@HTML5视频和音频
{{EmbedGHLiveSample("learning-area/html/multimedia-and-embedding/video-and-audio-content/multiple-video-formats.html", '100%', 380)}}
-你可以点击上面的文章链接来查看相关HTML元素的所有特性;但在这篇文章中,主要目的是学习我们最感兴趣的{{htmlattrxref("controls", "video")}}属性,它会启用默认的播放设置。如果没有指定该属性,则播放器中不会显示相关控件:
+你可以点击上面的文章链接来查看相关 HTML 元素的所有特性;但在这篇文章中,主要目的是学习我们最感兴趣的{{htmlattrxref("controls", "video")}}属性,它会启用默认的播放设置。如果没有指定该属性,则播放器中不会显示相关控件:
{{EmbedGHLiveSample("learning-area/html/multimedia-and-embedding/video-and-audio-content/multiple-video-formats-no-controls.html", '100%', 380)}}
至此,你可能会觉得这个属性作用不大,但是它确实很有优势。使用原生浏览器控件的一个很大的问题在于,它们在各个浏览器中都不相同 — 对于跨浏览器的支持并不是很好!另一个问题是,在大多数浏览器中原生控件难以通过键盘来操作。
-你可以通过隐藏本地控件(通过删除controls属性),然后使用HTML,CSS和JavaScript编写自己的代码来解决这两个问题。 在下一节中,我们将看到如何通过一些可用的工具来实现。
+你可以通过隐藏本地控件(通过删除 controls 属性),然后使用 HTML,CSS 和 JavaScript 编写自己的代码来解决这两个问题。在下一节中,我们将看到如何通过一些可用的工具来实现。
HTMLMediaElement API
-作为HTML5规范的一部分,{{domxref("HTMLMediaElement")}} API提供允许你以编程方式来控制视频和音频播放的功能—例如 {{domxref("HTMLMediaElement.play()")}}, {{domxref("HTMLMediaElement.pause()")}},等。该接口对{{htmlelement("audio")}}和{{htmlelement("video")}}两个元素都是可用的,因为在这两个元素中要实现的功能几乎是相同的。让我们通过一个例子来一步步演示一些功能。
+作为 HTML5 规范的一部分,{{domxref("HTMLMediaElement")}} API 提供允许你以编程方式来控制视频和音频播放的功能—例如 {{domxref("HTMLMediaElement.play()")}}, {{domxref("HTMLMediaElement.pause()")}},等。该接口对{{htmlelement("audio")}}和{{htmlelement("video")}}两个元素都是可用的,因为在这两个元素中要实现的功能几乎是相同的。让我们通过一个例子来一步步演示一些功能。
我们最终的示例(和功能)将会如下所示:
@@ -56,11 +56,11 @@入门
想要使用这个示例的代码来入门,请下载media-player-start.zip 并解压到您的硬盘上的一个新建目录里。如果想要下载examples repo,它位于
-javascript/apis/video-audio/start/
路径下。下载并解压之后,如果您加载这个HTML,你将会看到一个通过浏览器原生播放控件渲染的非常一般的HTML5视频播放器。
+下载并解压之后,如果您加载这个 HTML,你将会看到一个通过浏览器原生播放控件渲染的非常一般的 HTML5 视频播放器。
探索 HTML
-打开HTML index文件。你将看到一些功能;HTML由视频播放器和它的控件所控制:
+打开 HTML index 文件。你将看到一些功能;HTML 由视频播放器和它的控件所控制:
<div class="player"> <video controls> @@ -84,18 +84,18 @@探索 HTML
- 整个播放器被包装在一个{{htmlelement("div")}}元素之中,所以如果有必要的话,可以把它作为一个单元整体来设置其样式。
- {{htmlelement("video")}}元素层包含两个{{htmlelement("source")}}元素,这样可以根据浏览器来加载其所支持的不同视频格式。
-- 控件 HTML 大概是最有趣的: +
- 控件 HTML 大概是最有趣的:
- 我们有四个 {{htmlelement("button")}} — play/pause, stop, rewind, and fast forward.
-- 每个
-<button>
都有一个class名
, 一个data-icon
属性来决定在每个按钮上显示什么图标 (在下一节讲述它是如何工作的), 和一个aria-label
属性为每一个按钮提供容易理解的描述, 即使我们没有在tags内提供可读的标签。当用户关注这些元素时含有aria-label
属性的内容也会被讲述人读出来。- 有一个设定的计时器 {{htmlelement("div")}}用来报告已经播放的时长。为了好玩,我们提供了两种报告机制 — 一个 {{htmlelement("span")}} 包含了流逝时间的分钟和秒,和一个额外的
+<div>
用来创建一个水平的随着时间增加而增长的进度条。要想了解完成版本看上去是咋样的, 点击查看完成版本.- 每个
+<button>
都有一个class名
, 一个data-icon
属性来决定在每个按钮上显示什么图标 (在下一节讲述它是如何工作的), 和一个aria-label
属性为每一个按钮提供容易理解的描述,即使我们没有在 tags 内提供可读的标签。当用户关注这些元素时含有aria-label
属性的内容也会被讲述人读出来。- 有一个设定的计时器 {{htmlelement("div")}}用来报告已经播放的时长。为了好玩,我们提供了两种报告机制 — 一个 {{htmlelement("span")}} 包含了流逝时间的分钟和秒,和一个额外的
<div>
用来创建一个水平的随着时间增加而增长的进度条。要想了解完成版本看上去是咋样的,点击查看完成版本.探索 CSS
-现在打开CSS文件来查看里面的内容。例子中的CSS样式并不是很复杂, 我们突出了最主要的一部分。首先注意
+.controls
的样式:现在打开 CSS 文件来查看里面的内容。例子中的 CSS 样式并不是很复杂,我们突出了最主要的一部分。首先注意
.controls
的样式:.controls { visibility: hidden; @@ -118,12 +118,12 @@探索 CSS
-
-- 我们从设置为
-hidden
的自定义控件{{cssxref("visibility")}}开始。稍后在我们的JavaScript中, 我们将控件设置为visible
, 并且从<video>
元素中移除controls
属性。这是因为, 如果JavaScript由于某种原因没有加载, 用户依然可以使用原生的控件播放视频。- 默认情况下,我们将控件的
-opacity
设置为0.5 {{cssxref("opacity")}},这样当您尝试观看视频时,它们就不会分散注意力。 只有当您将鼠标悬停/聚焦在播放器上时,控件才会完全不透明。- 我们使用Flexbox({{cssxref("display")}}: flex)布置控制栏内的按钮,以简化操作。
+- 我们从设置为
+hidden
的自定义控件{{cssxref("visibility")}}开始。稍后在我们的 JavaScript 中,我们将控件设置为visible
, 并且从<video>
元素中移除controls
属性。这是因为,如果 JavaScript 由于某种原因没有加载,用户依然可以使用原生的控件播放视频。- 默认情况下,我们将控件的
+opacity
设置为 0.5 {{cssxref("opacity")}},这样当您尝试观看视频时,它们就不会分散注意力。只有当您将鼠标悬停/聚焦在播放器上时,控件才会完全不透明。- 我们使用 Flexbox({{cssxref("display")}}: flex) 布置控制栏内的按钮,以简化操作。
接下来,让我们看看我们的按钮图标:
+接下来,让我们看看我们的按钮图标:
@font-face { font-family: 'HeydingsControlsRegular'; @@ -144,17 +144,17 @@-探索 CSS
text-shadow: 1px 1px 0px black; }首先在CSS的最上方我们使用 {{cssxref("@font-face")}} 块来导入自定义Web字体。这是一种图标字体 —— 字母表中的所有字符都是各种常用图标,你可以尝试在程序中调用。
+首先在 CSS 的最上方我们使用 {{cssxref("@font-face")}} 块来导入自定义 Web 字体。这是一种图标字体 —— 字母表中的所有字符都是各种常用图标,你可以尝试在程序中调用。
接下来,我们使用这些内容来显示每个按钮上的图标:
-
- 我们使用 {{cssxref("::before")}} 选择器在每个 {{htmlelement("button")}} 元素之前显示内容。
- 我们使用 {{cssxref("content")}} 属性将各情况下要显示的内容设置为
-data-icon
属性的内容。例如在播放按钮的情况下,data-icon
包含大写的“P”。- 我们使用 {{cssxref("font-family")}} 将自定义Web字体应用于我们的按钮上。在该字体中“P”对应的是“播放”图标,因此播放按钮上显示“播放”图标。
+- 我们使用 {{cssxref("font-family")}} 将自定义 Web 字体应用于我们的按钮上。在该字体中“P”对应的是“播放”图标,因此播放按钮上显示“播放”图标。
图标字体非常酷有很多原因 —— 减少HTTP请求,因为您不需要将这些图标作为图像文件下载。同时具有出色的可扩展性,以及您可以使用文本属性来设置它们的样式 —— 例如 {{cssxref("color")}} 和 {{cssxref("text-shadow")}}。
+图标字体非常酷有很多原因 —— 减少 HTTP 请求,因为您不需要将这些图标作为图像文件下载。同时具有出色的可扩展性,以及您可以使用文本属性来设置它们的样式 —— 例如 {{cssxref("color")}} 和 {{cssxref("text-shadow")}}。
最后让我们来看看进度条的 CSS:
@@ -185,22 +185,22 @@探索 CSS
}-
- 我们将外部
-.timer
<div>
设为flex:5,这样它占据了控件栏的大部分宽度。 我们还设置 {{cssxref("position")}}: relative
,这样我们就可以根据它的边界方便地定位元素,而不是{{htmlelement("body")}} 元素的边界。- 内部
+<div>
position:absolute
绝对定位于外部<div>
的顶部。 它的初始宽度为0,因此根本无法看到它。随着视频的播放,JavaScript将动态的增加其宽度。- 我们将外部
+.timer
<div>
设为 flex:5,这样它占据了控件栏的大部分宽度。我们还设置 {{cssxref("position")}}: relative
,这样我们就可以根据它的边界方便地定位元素,而不是{{htmlelement("body")}} 元素的边界。- 内部
<div>
position:absolute
绝对定位于外部<div>
的顶部。它的初始宽度为 0,因此根本无法看到它。随着视频的播放,JavaScript 将动态的增加其宽度。- -
<span>
也绝对位于计时器/进度条timer
栏的左侧附近。- 我们还对内部
+<div>
和<span>
定义适当数值的 {{cssxref("z-index")}} ,以便进度条显示在最上层,内部<div>
显示在下层。 这样,我们确保我们可以看到所有信息 —— 一个box不会遮挡另一个。- 我们还对内部
<div>
和<span>
定义适当数值的 {{cssxref("z-index")}} ,以便进度条显示在最上层,内部<div>
显示在下层。这样,我们确保我们可以看到所有信息 —— 一个 box 不会遮挡另一个。实现 JavaScript
-我们已经有了一个相当完整的 HTML 和CSS 接口;现在我们只需要调通所有按钮以使控件正常工作。
+我们已经有了一个相当完整的 HTML 和 CSS 接口;现在我们只需要调通所有按钮以使控件正常工作。
- -
在与 index.html 文件相同的目录下创建新的JavaScript文件。命名为
+custom-player.js
。在与 index.html 文件相同的目录下创建新的 JavaScript 文件。命名为
custom-player.js
。- -
@@ -285,7 +285,7 @@在此文件的顶部,插入以下代码:
+在此文件的顶部,插入以下代码:
var media = document.querySelector('video'); var controls = document.querySelector('.controls'); @@ -257,7 +257,7 @@-播放和暂停视频
} }我们使用if语句来检查视频是否暂停。如果视频已暂停,{{domxref("HTMLMediaElement.paused")}} 属性将返回 true,任何视频没有播放的时间,包括第一次加载时处于0的时间段都是视频暂停状态。如果已暂停,我们把play按钮的
+data-icon
属性值设置成"u", 用以表示 "暂停" 按钮图标,并且调用{{domxref("HTMLMediaElement.play()")}} 函数播放视频。我们使用 if 语句来检查视频是否暂停。如果视频已暂停,{{domxref("HTMLMediaElement.paused")}} 属性将返回 true,任何视频没有播放的时间,包括第一次加载时处于 0 的时间段都是视频暂停状态。如果已暂停,我们把 play 按钮的
data-icon
属性值设置成"u", 用以表示 "暂停" 按钮图标,并且调用{{domxref("HTMLMediaElement.play()")}} 函数播放视频。点击第二次,按钮将会切换回去——"播放"按钮图标将会再次显示,并且视频将会被{{domxref("HTMLMediaElement.paused()")}} 函数暂停。
暂停视频
} -在 HTMLMediaElement API 中没有
+stop()
方法——等效的办法是先用pause()
暂停视频,然后设置{{domxref("HTMLMediaElement.currentTime","currentTime")}} 属性为0。设置currentTime
的值(单位:秒)将会立刻使视频跳到该位置。在 HTMLMediaElement API 中没有
stop()
方法——等效的办法是先用pause()
暂停视频,然后设置{{domxref("HTMLMediaElement.currentTime","currentTime")}} 属性为 0。设置currentTime
的值(单位:秒)将会立刻使视频跳到该位置。之后要做的事是把显示的图标设置成“播放”图标。无论视频使暂停还是正在播放,您都希望它随后可以播放。
探索快进和快退
} -您会注意到,首先我们初始化两个变量 - intervalFwd和intervalRwd - 您将在后面发现它们的用途。
+您会注意到,首先我们初始化两个变量 - intervalFwd 和 intervalRwd - 您将在后面发现它们的用途。
让我们逐步浏览
mediaBackward()
(mediaForward()
的功能性完全相同,但效果相反):-
- 我们清除在快进功能上设置的所有classes和intervals ––这样做是因为如果我们在按下
+fwd
(快进)按钮后再按下rwd
(快退)按钮,就可以取消任何快进的功能并将其替换为快退功能。如果我们试图同时做到这两点,播放器就会暂停。- 我们清除在快进功能上设置的所有 classes 和 intervals ––这样做是因为如果我们在按下
fwd
(快进)按钮后再按下rwd
(快退)按钮,就可以取消任何快进的功能并将其替换为快退功能。如果我们试图同时做到这两点,播放器就会暂停。- 使用
if
语句检查是否已在rwd
按钮上设置了用来指示它已被按下的active
类。{{domxref("classList")}}是一个非常方便的属性,存在于每个元素上 ––它包含元素上设置的所有类的列表,以及添加/删除类的方法等。使用classList.contains()
方法检查列表是否包含active
类。这将返回布尔值true/false
结果。- 如果在
-rwd
按钮上设置了active
,我们使用classList.remove()
删除它,清除第一次按下按钮时设置的间隔(参见下面的更多解释),并使用{{domxref("HTMLMediaElement.play()")}}取消快退并开始正常播放视频。- 如果尚未设置,使用
+classList.add()
将active
类添加到rwd
按钮,使用{{domxref("HTMLMediaElement.pause()")}}暂停视频,然后设置intervalRwd
变量为{{domxref("WindowOrWorkerGlobalScope.setInterval", "setInterval()")}}的调用。调用时,setInterval()
会创建一个活动间隔,这意味着它每隔x毫秒运行一个作为第一个参数给出的函数,其中x是第二个参数的值。 所以这里我们每200毫秒运行一次windBackward()
函数 ––我们将使用此函数不断向后滚动(快退动作)视频。要停止{{domxref("WindowOrWorkerGlobalScope.setInterval", "setInterval()")}}运行,你必须调用{{domxref("WindowOrWorkerGlobalScope.clearInterval", "clearInterval()")}},给它识别要清除的间隔的名称,在本例中是变量名称intervalRwd(请参阅函数中较早的clearInterval()调用)。- 如果尚未设置,使用
classList.add()
将active
类添加到rwd
按钮,使用{{domxref("HTMLMediaElement.pause()")}}暂停视频,然后设置intervalRwd
变量为{{domxref("WindowOrWorkerGlobalScope.setInterval", "setInterval()")}}的调用。调用时,setInterval()
会创建一个活动间隔,这意味着它每隔 x 毫秒运行一个作为第一个参数给出的函数,其中 x 是第二个参数的值。所以这里我们每 200 毫秒运行一次windBackward()
函数 ––我们将使用此函数不断向后滚动(快退动作)视频。要停止{{domxref("WindowOrWorkerGlobalScope.setInterval", "setInterval()")}}运行,你必须调用{{domxref("WindowOrWorkerGlobalScope.clearInterval", "clearInterval()")}},给它识别要清除的间隔的名称,在本例中是变量名称 intervalRwd(请参阅函数中较早的 clearInterval()调用)。- -
最后,对于本节,定义在setInterval()调用中需要调用的windBackward()和windForward()函数。在以上两个函数下面添加以下内容:
+最后,对于本节,定义在 setInterval()调用中需要调用的 windBackward()和 windForward()函数。在以上两个函数下面添加以下内容:
function windBackward() { if(media.currentTime <= 3) { @@ -374,18 +374,18 @@-探索快进和快退
} }同样,我们将完成这些功能中的第一个,因为它们几乎完全相同,但彼此相反。在
+windBackward()
中,我们执行以下操作 ––请记住,当间隔处于活动状态时,此函数每200毫秒运行一次。同样,我们将完成这些功能中的第一个,因为它们几乎完全相同,但彼此相反。在
windBackward()
中,我们执行以下操作 ––请记住,当间隔处于活动状态时,此函数每 200 毫秒运行一次。-
- 我们从一个
-if
语句开始,该语句检查当前时间是否小于3秒,即,如果再倒退三秒将使其超过视频的开始。这会导致奇怪的行为,所以如果是这种情况,我们通过调用stopMedia()
来停止视频播放,从倒带按钮中删除active
类,并清除intervalRwd
间隔以停止快退功能。如果我们没有做到最后一步,视频将永远保持快退。- 如果当前时间不在视频开始的3秒内,我们只需通过执行
+media.currentTime-=3
从当前时间中删除三秒。因此,实际上,我们将视频快退3秒,每200毫秒一次。- 我们从一个
+if
语句开始,该语句检查当前时间是否小于 3 秒,即,如果再倒退三秒将使其超过视频的开始。这会导致奇怪的行为,所以如果是这种情况,我们通过调用stopMedia()
来停止视频播放,从倒带按钮中删除active
类,并清除intervalRwd
间隔以停止快退功能。如果我们没有做到最后一步,视频将永远保持快退。- 如果当前时间不在视频开始的 3 秒内,我们只需通过执行
media.currentTime-=3
从当前时间中删除三秒。因此,实际上,我们将视频快退 3 秒,每 200 毫秒一次。更新已用时间
-我们要实施的媒体播放器的最后一块是显示的时间。为此,我们将运行一个函数,以便每次在<video>元素上触发 {{event("timeupdate")}}事件时更新时间显示。此事件触发的频率取决于您的浏览器,CPU电源等(see this stackoverflow post)。
+我们要实施的媒体播放器的最后一块是显示的时间。为此,我们将运行一个函数,以便每次在<video>元素上触发 {{event("timeupdate")}}事件时更新时间显示。此事件触发的频率取决于您的浏览器,CPU 电源等(see this stackoverflow post)。
在代码下方添加
@@ -424,9 +424,9 @@addEventListener()
行:更新已用时间
@@ -453,17 +453,17 @@
- 首先,我们计算{{domxref("HTMLMediaElement.currentTime")}} 值中的分钟数和秒数。
- 然后我们初始化另外两个变量 ––
-minuteValue
和secondValue
。- 两个
+if
语句计算出分钟数和秒数是否小于10.如果是这样,它们会在类似数值时钟显示工作的方式上为值添加前置的零。- 两个
if
语句计算出分钟数和秒数是否小于 10.如果是这样,它们会在类似数值时钟显示工作的方式上为值添加前置的零。- 要显示的实际时间值设置为
-minuteValue
加上冒号字符加secondValue
。- 计时器的{{domxref("Node.textContent")}}值设置为时间值,因此它显示在UI中。
+- 计时器的{{domxref("Node.textContent")}}值设置为时间值,因此它显示在 UI 中。
- 我们应该设置内部
<div>
的长度是通过首先计算外部<div>
的宽度来计算出来的(任何元素的{{domxref("HTMLElement.clientWidth", "clientWidth")}} 属性将包含它的长度),然后乘以{{domxref("HTMLMediaElement.currentTime")}}除以媒体的总{{domxref("HTMLMediaElement.duration")}}。- 我们将内部
<div>
的宽度设置为等于计算的条形长度加上“px”,因此它将设置为该像素数修复播放和暂停
小结
-我想我们已经在这篇文章中教过你足够多了。使用{{domxref("HTMLMediaElement")}} API可以为创建简单的视频和音频播放器提供丰富的可用功能,然而这只是冰山一角。 有关更复杂和有趣功能的链接,请参阅下面的“另请参阅”部分。
+我想我们已经在这篇文章中教过你足够多了。使用{{domxref("HTMLMediaElement")}} API 可以为创建简单的视频和音频播放器提供丰富的可用功能,然而这只是冰山一角。有关更复杂和有趣功能的链接,请参阅下面的“另请参阅”部分。
以下是一些有关如何增强我们构建的现有示例的建议:
-
-- 如果视频是一小时或更长时间(嗯,它不会显示小时;只有几分钟和几秒),当前显示时间会中断。 你能弄清楚如何更改示例以使其显示小时数吗?
+- 如果视频是一小时或更长时间(嗯,它不会显示小时;只有几分钟和几秒),当前显示时间会中断。你能弄清楚如何更改示例以使其显示小时数吗?
- -
由于
+<audio>
元素具有相同的{{domxref("HTMLMediaElement")}}功能,因此您可以轻松地将此播放器用于<audio>
元素。 试着这样做。由于
<audio>
元素具有相同的{{domxref("HTMLMediaElement")}}功能,因此您可以轻松地将此播放器用于<audio>
元素。试着这样做。- -
你能找到一种方法将计时器内部的
+<div>
元素转换为真正的搜索条/ 滑动条- 也就是说,当你点击条形图上的某个位置时,它会跳转到视频播放中的相对位置吗? 作为提示,您可以通过getBoundingClientRect()
方法找出元素左/右和上/下侧的X和Y值 , 而且你可以通过 {{domxref("Document")}} 对象调用的click事件的事件对象找到鼠标单击的坐标。举个栗子:你能找到一种方法将计时器内部的
<div>
元素转换为真正的搜索条/ 滑动条 - 也就是说,当你点击条形图上的某个位置时,它会跳转到视频播放中的相对位置吗?作为提示,您可以通过getBoundingClientRect()
方法找出元素左/右和上/下侧的X和Y值,而且你可以通过 {{domxref("Document")}} 对象调用的 click 事件的事件对象找到鼠标单击的坐标。举个栗子:document.onclick = function(e) { console.log(e.x) + ',' + console.log(e.y) @@ -475,9 +475,9 @@另请参阅
- {{domxref("HTMLMediaElement")}}
-- 视频和音频内容— <video>和<audio>的简单指南.
+- 视频和音频内容— <video>和<audio>的简单指南。
- Audio and video delivery — detailed guide to delivering media inside the browser, with many tips, tricks, and links to further more advanced tutorials.
-- Audio 与 video 操作 — 操作audio 和 video 的详细指南,例如:使用 Canvas API, Web Audio API, 等等。
+- Audio 与 video 操作 — 操作 audio 和 video 的详细指南,例如:使用 Canvas API, Web Audio API,等等。
- {{htmlelement("video")}} and {{htmlelement("audio")}} reference pages.
Media formats supported by the HTML audio and video elements.
diff --git a/files/zh-cn/learn/javascript/first_steps/a_first_splash/index.html b/files/zh-cn/learn/javascript/first_steps/a_first_splash/index.html index 7941b53a2b4d3c..37f2ae84b38333 100644 --- a/files/zh-cn/learn/javascript/first_steps/a_first_splash/index.html +++ b/files/zh-cn/learn/javascript/first_steps/a_first_splash/index.html @@ -22,27 +22,27 @@-
- 预备知识: -计算机基础知识,初步理解HTML和CSS,了解JavaScript。 +预备知识: +计算机基础知识,初步理解 HTML 和 CSS,了解 JavaScript。 - 目标: -获得编写JavaScript的初体验,初步了解编写JavaScript时会涉及哪些内容。 +目标: +获得编写 JavaScript 的初体验,初步了解编写 JavaScript 时会涉及哪些内容。 我们并不要求你立刻完整理解所有代码,当前只是概括地介绍一些抽象的概念,并且让你对JavaScript(以及其他编程语言)工作原理有一定的认知。所有具体特性将在后续文章中详细介绍。
+我们并不要求你立刻完整理解所有代码,当前只是概括地介绍一些抽象的概念,并且让你对 JavaScript(以及其他编程语言)工作原理有一定的认知。所有具体特性将在后续文章中详细介绍。
-注: 可以看到,JavaScript 中许多代码特性和其他编程语言是一致的( 函数、循环,等等)。尽管代码语法不尽相同,但概念基本类似。
+注:可以看到,JavaScript 中许多代码特性和其他编程语言是一致的( 函数、循环,等等)。尽管代码语法不尽相同,但概念基本类似。
像程序员一样思考
-学习编程,语法本身并不难,真正困难的是如何应用它来解决现实世界的问题。 你要开始像程序员那样思考。一般来讲,这种思考包括了解你程序运行的目的,为达到该目的应选定的代码类型,以及如何使这些代码协同运行。
+学习编程,语法本身并不难,真正困难的是如何应用它来解决现实世界的问题。你要开始像程序员那样思考。一般来讲,这种思考包括了解你程序运行的目的,为达到该目的应选定的代码类型,以及如何使这些代码协同运行。
-为达成这一点,我们需要努力编程,获取语法经验,注重实践,再加一点创造力,几项缺一不可。代码写的越多,就会完成的越优秀。虽然我们不能保证你在5分钟内拥有“程序员大脑”,但是整个课程中你将得到大量机会来训练程序员思维。
+为达成这一点,我们需要努力编程,获取语法经验,注重实践,再加一点创造力,几项缺一不可。代码写的越多,就会完成的越优秀。虽然我们不能保证你在 5 分钟内拥有“程序员大脑”,但是整个课程中你将得到大量机会来训练程序员思维。
请牢记这一点,然后开始观察本文的示例,体会一下将其分解为可操作任务的大体过程。
@@ -80,8 +80,8 @@Top hidden code
<body> <h1>猜数字游戏</h1> - <p>我刚才随机选定了一个100以内的自然数。看你能否在 10 次以内猜中它。每次我都会告诉你所猜的结果是高了还是低了。</p> - <div class="form"> <label for="guessField">请猜数: </label><input type="text" id="guessField" class="guessField"> <input type="submit" value="确定" class="guessSubmit"> </div> + <p>我刚才随机选定了一个 100 以内的自然数。看你能否在 10 次以内猜中它。每次我都会告诉你所猜的结果是高了还是低了。</p> + <div class="form"> <label for="guessField">请猜数:</label><input type="text" id="guessField" class="guessField"> <input type="submit" value="确定" class="guessSubmit"> </div> <div class="resultParas"> <p class="guesses"></p> <p class="lastResult"></p> @@ -102,7 +102,7 @@Top hidden code
function checkGuess() { let userGuess = Number(guessField.value); if (guessCount === 1) { - guesses.textContent = '上次猜的数: '; + guesses.textContent = '上次猜的数:'; } guesses.textContent += userGuess + ' '; @@ -169,7 +169,7 @@Top hidden code
假设你的老板给你布置了以下游戏设计任务要求:
-我想让你开发一个猜数字游戏。游戏应随机选择一个 100 以内的自然数, 然后邀请玩家在 10 轮以内猜出这个数字。每轮后都应告知玩家的答案正确与否,如果出错了,则告诉他数字是低了还是高了。并且应显示出玩家前一轮所猜的数字。一旦玩家猜对,或者用尽所有机会,游戏将结束。游戏结束后,可以让玩家选择再次开始。
+我想让你开发一个猜数字游戏。游戏应随机选择一个 100 以内的自然数,然后邀请玩家在 10 轮以内猜出这个数字。每轮后都应告知玩家的答案正确与否,如果出错了,则告诉他数字是低了还是高了。并且应显示出玩家前一轮所猜的数字。一旦玩家猜对,或者用尽所有机会,游戏将结束。游戏结束后,可以让玩家选择再次开始。
看到这个要求,首先我们要做的是将其分解成简单的可操作的任务,尽可能从程序员的思维去思考:
@@ -201,14 +201,14 @@Top hidden code
- 显示控件允许玩家重新开始游戏。
- 一旦游戏重启,确保游戏的逻辑和UI完全重置,然后返回步骤1。
+- 一旦游戏重启,确保游戏的逻辑和 UI 完全重置,然后返回步骤 1。
让我们继续,看看我们如何将这些步骤转换为代码,构建这个示例,从而探索 JavaScript 的功能。
初始设置
-本教程开始前,请将 number-guessing-game-start.html 文件保存下来。同时在文本编辑器和Web浏览器中将其打开,可以看到一个简单的标题,一段游戏说明,和一个用于输入猜测的表单,此时表单不会执行任何操作。
+本教程开始前,请将 number-guessing-game-start.html 文件保存下来。同时在文本编辑器和 Web 浏览器中将其打开,可以看到一个简单的标题,一段游戏说明,和一个用于输入猜测的表单,此时表单不会执行任何操作。
我们将在 HTML 底部的 {{htmlelement("script")}} 元素中添加新的代码:
@@ -235,7 +235,7 @@添加变量以保存数据
let guessCount = 1; let resetButton; -这段代码设置了存储数据的变量和常量以供程序使用。变量本质上是值(例如数字或字符串)的容器。 你可以使用关键字
+let
(旧代码中使用var
)和一个名字来创建变量(请参阅 let 和 var 之间的区别)。常量用于存储不希望更改的数据,用关键字const
创建,本例中用常量来保存对界面元素的引用。界面元素的文字可能会改变,但引用是不变的。这段代码设置了存储数据的变量和常量以供程序使用。变量本质上是值(例如数字或字符串)的容器。你可以使用关键字
let
(旧代码中使用var
)和一个名字来创建变量(请参阅 let 和 var 之间的区别)。常量用于存储不希望更改的数据,用关键字const
创建,本例中用常量来保存对界面元素的引用。界面元素的文字可能会改变,但引用是不变的。可以使用等号(=)和一个值来为变量赋值。
@@ -243,7 +243,7 @@添加变量以保存数据
- 我们用数学算法得出一个 1 到 100 之间的随机数,并赋值给第一个变量(
-randomNumber
)。- 接下来的三个常量均存储着一个引用,分别指向HTML结果段落中某个元素,用于在代码后面段落中插入值:
+- 接下来的三个常量均存储着一个引用,分别指向 HTML 结果段落中某个元素,用于在代码后面段落中插入值:
<p class="guesses"></p> <p class="lastResult"></p> @@ -270,7 +270,7 @@函数(Function)
}-+@@ -283,7 +283,7 @@函数(Function)
-让我们尝试一下。保存你的代码并刷新浏览器页面 。然后进入
+让我们尝试一下。保存你的代码并刷新浏览器页面。然后进入@@ -447,7 +447,7 @@
开发者工具 JavaScript 控制台,并输入以下代码:Hidden code
您也可以使用
++
运算符将文本字符串连接在一起(术语“串联”(concatenation))。 尝试依次输入以下行:您也可以使用
+
运算符将文本字符串连接在一起(术语“串联”(concatenation))。尝试依次输入以下行:let name = 'Bingo'; name; @@ -456,7 +456,7 @@-Hidden code
let greeting = name + hello; greeting;还有一些快捷操作符可用,称为 复合赋值操作符。 例如,如果你只希望在现有字符串末尾添加一个新串,可以这样做:
+还有一些快捷操作符可用,称为 复合赋值操作符。例如,如果你只希望在现有字符串末尾添加一个新串,可以这样做:
name += ' says hello!';@@ -535,14 +535,14 @@条件语句(Conditional)
唷——好多的代码!让我们来逐段探究。
-
-- 第一行(行标 2)声明了一个名为
-userGuess
的变量,并将其设置为在文本字段中输入的值。 我们还对这个值应用了内置的Number()
方法,只是为了确保该值是一个数字。- 接下来,我们遇到我们的第一个条件代码块(3 - 5 行)。 条件代码块让你能够根据某个条件的真假来选择性地运行代码。 虽然看起来有点像一个函数,但它不是。 条件块的最简单形式是从关键字
+if
开始,然后是一些括号,然后是一些花括号。 括号内包含一个比较。 如果比较结果为true
,就会执行花括号内的代码。 反之,花括号中的代码就会被跳过,从而执行下面的代码。 本文的示例中,比较测试的是guessCount
变量是否等于1,即玩家是不是第一次猜数字:- 第一行(行标 2)声明了一个名为
+userGuess
的变量,并将其设置为在文本字段中输入的值。我们还对这个值应用了内置的Number()
方法,只是为了确保该值是一个数字。- 接下来,我们遇到我们的第一个条件代码块(3 - 5 行)。条件代码块让你能够根据某个条件的真假来选择性地运行代码。虽然看起来有点像一个函数,但它不是。条件块的最简单形式是从关键字
if
开始,然后是一些括号,然后是一些花括号。括号内包含一个比较。如果比较结果为true
,就会执行花括号内的代码。反之,花括号中的代码就会被跳过,从而执行下面的代码。本文的示例中,比较测试的是guessCount
变量是否等于 1,即玩家是不是第一次猜数字: guessCount === 1如果是, 我们让
+guesses
段落的文本内容等于“上次猜的数:
”。如果不是就不用了。如果是,我们让
guesses
段落的文本内容等于“上次猜的数:
”。如果不是就不用了。
- 第 6 行将当前
@@ -553,12 +553,12 @@userGuess
值附加到guesses
段落的末尾,并加上一个空格,以使每两个猜测值之间有一个空格。条件语句(Conditional)
- 最后的一个块是
else { }
,前两个比较都不返回true
时(也就是玩家尚未猜对,但是还有机会)才会执行这里的代码。在这个情况下,我们会告诉玩家他们猜错了,并执行另一个条件测试,判断并告诉玩家猜测的数字是高了还是低了。- 函数最后三行(26 - 28 行)是为下次猜测值提交做准备的。我们把
+guessCount
变量的值加 1,以使玩家消耗一次机会 (++
是自增操作符,为自身加 1),然后我们把表单中文本域的值清空,重新聚焦于此,准备下一轮游戏。- 函数最后三行(26 - 28 行)是为下次猜测值提交做准备的。我们把
guessCount
变量的值加 1,以使玩家消耗一次机会(++
是自增操作符,为自身加 1),然后我们把表单中文本域的值清空,重新聚焦于此,准备下一轮游戏。事件(Event)
-现在,我们有一个实现比较不错的
+checkGuess()
函数了,但它现在什么事情也做不了,因为我们还没有调用它。 理想中,我们希望在点击“确定”按钮时调用它,为此,我们需要使用事件。 事件就是浏览器中发生的事儿,比如点击按钮、加载页面、播放视频,等等,我们可以通过调用代码来响应事件。 侦听事件发生的结构称为事件监听器(Event Listener),响应事件触发而运行的代码块被称为事件处理器(Event Handler)。现在,我们有一个实现比较不错的
checkGuess()
函数了,但它现在什么事情也做不了,因为我们还没有调用它。理想中,我们希望在点击“确定”按钮时调用它,为此,我们需要使用事件。事件就是浏览器中发生的事儿,比如点击按钮、加载页面、播放视频,等等,我们可以通过调用代码来响应事件。侦听事件发生的结构称为事件监听器(Event Listener),响应事件触发而运行的代码块被称为事件处理器(Event Handler)。在
@@ -566,7 +566,7 @@checkGuess()
函数后添加以下代码:事件(Event)
这里为
-guessSubmit
按钮添加了一个事件监听器。addEventListener()
方法包含两个可输入值(称为“参数”(argument)),监听事件的类型(本例中为“click
”),和当事件发生时我们想要执行的代码(本例中为checkGuess()
函数)。注意,addEventListener()
中作为参数的函数名不加括号。现在,保存代码并刷新页面,示例应该能够工作了,但还不够完善。 现在唯一的问题是,如果玩家猜对或游戏次数用完,游戏将出错,因为我们尚未定义游戏结束时应运行的
+setGameOver()
函数。 现在,让我们补全所缺代码,并完善示例功能。现在,保存代码并刷新页面,示例应该能够工作了,但还不够完善。现在唯一的问题是,如果玩家猜对或游戏次数用完,游戏将出错,因为我们尚未定义游戏结束时应运行的
setGameOver()
函数。现在,让我们补全所缺代码,并完善示例功能。补全游戏功能
@@ -582,7 +582,7 @@补全游戏功能
}-
@@ -626,13 +626,13 @@- 前两行通过将
+disable
属性设置为true
来禁用表单文本输入和按钮。 这样做是必须的,否则用户就可以在游戏结束后提交更多的猜测,游戏的规则将遭到破坏。- 前两行通过将
disable
属性设置为true
来禁用表单文本输入和按钮。这样做是必须的,否则用户就可以在游戏结束后提交更多的猜测,游戏的规则将遭到破坏。- 接下来的三行创建一个新的 {{htmlelement("button")}} 元素,设置它的文本为“开始新游戏”,并把它添加到当前 HTML 的底部。
- 最后一行在新按钮上设置了一个事件监听器,当它被点击时,一个名为
resetGame()
的函数被将被调用。补全游戏功能
循环(Loop)
-上面代码中有一部分需要我们仔细研读,那就是 for 循环。 循环是一个非常重要的编程概念,它让你能够重复运行一段代码,直到满足某个条件为止。
+上面代码中有一部分需要我们仔细研读,那就是 for 循环。循环是一个非常重要的编程概念,它让你能够重复运行一段代码,直到满足某个条件为止。
首先,请再次转到 浏览器开发工具 JavaScript 控制台 然后输入以下内容:
for (let i = 1; i < 21; i++) { console.log(i); }-发生了什么? 控制台中打印出了数字 1 到 20。 这正是循环所为。一个 for 循环需要三个输入值(参数):
+发生了什么?控制台中打印出了数字 1 到 20。这正是循环所为。一个 for 循环需要三个输入值(参数):
- 起始值:本例中我们从 1 开始计数,但其他任意数字也可以。
@@ -651,11 +651,11 @@i
也可以用任何你喜欢的名字替换,但一般约定用i
,因为它很短,且易于记忆。循环(Loop)
浅谈对象(Object)
-在讨论前最后再改进一波。 在
+let resetButton
(脚本顶端部分)下方添加下面一行内容,然后保存文件:在讨论前最后再改进一波。在
let resetButton
(脚本顶端部分)下方添加下面一行内容,然后保存文件:guessField.focus();-这一行通过 {{domxref("HTMLElement.focus", "focus()")}} 方法让光标在页面加载完毕时自动放置于 {{htmlelement("input")}} 输入框内,这意味着玩家可以马上开始第一次猜测,而无需点击输入框。 这只是一个小的改进,却提高了可用性——为使用户能投入游戏提供一个良好的视觉线索。
+这一行通过 {{domxref("HTMLElement.focus", "focus()")}} 方法让光标在页面加载完毕时自动放置于 {{htmlelement("input")}} 输入框内,这意味着玩家可以马上开始第一次猜测,而无需点击输入框。这只是一个小的改进,却提高了可用性——为使用户能投入游戏提供一个良好的视觉线索。
深入分析一下。JavaScript 中一切都是对象。对象是存储在单个分组中的相关功能的集合。可以创建自己的对象,但这是较高阶的知识,我们今后才会谈及。现在,仅需简要讨论浏览器内置的对象,它们已经能够做许多有用的事情。
@@ -663,7 +663,7 @@浅谈对象(Object)
const guessField = document.querySelector('.guessField');-使用 {{domxref("document")}} 对象的 {{domxref("document.querySelector", "querySelector()")}} 方法可以获得这个引用。
+querySelector()
需要一个信息——用一个 CSS选择器 可以选中需要引用的元素。使用 {{domxref("document")}} 对象的 {{domxref("document.querySelector", "querySelector()")}} 方法可以获得这个引用。
querySelector()
需要一个信息——用一个 CSS 选择器 可以选中需要引用的元素。因为
@@ -681,7 +681,7 @@guessField
现在包含一个指向 {{htmlelement("input")}} 元素的引用,它现在就能够访问一系列的属性(存储于对象内部的基础变量,其中一些的值无法改变)和方法(存储在对象内部的基础函数)。focus()
是 {{htmlelement("input")}} 元素可用方法之一,因此我们可以使用这行代码将光标聚焦于此文本框上︰操作浏览器对象
- 输入
guessField
,控制台将会显示此变量包含一个 {{htmlelement("input")}} 元素。同时控制台还能自动补全运行环境中对象的名字,包括你的变量!- 现在输入下面的代码:
+guessField.value = 'Hello';-value
属性表示当前文本区域中输入的值。 在输入这条指令后,你将看到文本域区中的文本被我们修改了!value
属性表示当前文本区域中输入的值。在输入这条指令后,你将看到文本域区中的文本被我们修改了!- 现在试试输入
guesses
然后回车。控制台会显示一个包含 {{htmlelement("p")}} 元素的变量。- 现在试试输入下面这一行:
guesses.value@@ -689,13 +689,13 @@操作浏览器对象
- 为了改变段落中的文本内容, 你需要用 {{domxref("Node.textContent", "textContent")}} 属性来代替
-value
。试试这个:guesses.textContent = '我的段落在哪里?';- 下面是一些有趣的东西。 尝试依次输入下面几行: +
- 下面是一些有趣的东西。尝试依次输入下面几行:
-guesses.style.backgroundColor = 'yellow'; guesses.style.fontSize = '200%'; guesses.style.padding = '10px'; guesses.style.boxShadow = '3px 3px 6px black';- 页面上的每个元素都有一个
+style
属性,它本身包含一个对象,其属性包含应用于该元素的所有内联 CSS 样式。 让我们可以使用 JavaScript 在元素上动态设置新的 CSS 样式。- 页面上的每个元素都有一个
style
属性,它本身包含一个对象,其属性包含应用于该元素的所有内联 CSS 样式。让我们可以使用 JavaScript 在元素上动态设置新的 CSS 样式。大功告成...
diff --git a/files/zh-cn/learn/javascript/first_steps/arrays/index.html b/files/zh-cn/learn/javascript/first_steps/arrays/index.html index a00a0158e0c1e7..3fbf92b2b100b5 100644 --- a/files/zh-cn/learn/javascript/first_steps/arrays/index.html +++ b/files/zh-cn/learn/javascript/first_steps/arrays/index.html @@ -17,29 +17,29 @@{{PreviousMenuNext("Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps/Silly_story_generator", "Learn/JavaScript/First_steps")}}-在本模块的最后一篇文章中, 我们将看看数组 —— 一种将一组数据存储在单个变量名下的优雅方式。 现在我们看看它有什么用,然后探索如何来创建一个数组,检索、添加和删除存储在数组中的元素,以及其他更多的功能。
+在本模块的最后一篇文章中,我们将看看数组 —— 一种将一组数据存储在单个变量名下的优雅方式。 现在我们看看它有什么用,然后探索如何来创建一个数组,检索、添加和删除存储在数组中的元素,以及其他更多的功能。
-
- 前提: +前提: 基本的电脑知识,对 HTML、CSS 语法有基础的理解,能理解什么是 JavaScript。 - 目的: +目的: 理解什么是数组,和如何在 JavaScript 中操作数组。 数组是什么?
+数组是什么?
-数组通常被描述为“像列表一样的对象”; 简单来说,数组是一个包含了多个值的对象。数组对象可以存储在变量中,并且能用和其他任何类型的值完全相同的方式处理,区别在于我们可以单独访问列表中的每个值,并使用列表执行一些有用和高效的操作,如循环 - 它对数组中的每个元素都执行相同的操作。 也许我们有一系列产品和价格存储在一个数组中,我们想循环遍历所有这些产品,并将它们打印在发票上,同时将所有产品的价格统计在一起,然后将总价格打印在底部。
+数组通常被描述为“像列表一样的对象”; 简单来说,数组是一个包含了多个值的对象。数组对象可以存储在变量中,并且能用和其他任何类型的值完全相同的方式处理,区别在于我们可以单独访问列表中的每个值,并使用列表执行一些有用和高效的操作,如循环 - 它对数组中的每个元素都执行相同的操作。也许我们有一系列产品和价格存储在一个数组中,我们想循环遍历所有这些产品,并将它们打印在发票上,同时将所有产品的价格统计在一起,然后将总价格打印在底部。
-
如果我们没有数组,我们必须将每个产品存储在一个单独的变量中,然后调用打印的代码,并为每个产品单独添加。 花费的时间要长得多,效率很低,而且也容易出错。 如果我们有 10 个产品需要添加发票,那就只是有点麻烦而已,但是 100 个,或者 1000 个呢? 我们稍后将在文章中使用这个例子。
+如果我们没有数组,我们必须将每个产品存储在一个单独的变量中,然后调用打印的代码,并为每个产品单独添加。花费的时间要长得多,效率很低,而且也容易出错。如果我们有 10 个产品需要添加发票,那就只是有点麻烦而已,但是 100 个,或者 1000 个呢?我们稍后将在文章中使用这个例子。
-像以前的文章一样,我们通过在 JavaScript 控制台中输入一些示例来了解数组的基础知识。 我们在下面提供了一个(您也可以在单独的选项卡或窗口中打开此控制台,或者如果您愿意,请使用浏览器的开发者工具控制台)。
+像以前的文章一样,我们通过在 JavaScript 控制台中输入一些示例来了解数组的基础知识。我们在下面提供了一个(您也可以在单独的选项卡或窗口中打开此控制台,或者如果您愿意,请使用浏览器的开发者工具控制台)。
Hidden code
@@ -158,11 +158,11 @@创建数组
数组由方括号构成,其中包含用逗号分隔的元素列表。
-
- 假设我们想在一个数组中存储一个购物清单 - 我们会做一些像下面这样的事情。 在您的控制台中输入以下行: +
- 假设我们想在一个数组中存储一个购物清单 - 我们会做一些像下面这样的事情。在您的控制台中输入以下行:
-let shopping = ['bread', 'milk', 'cheese', 'hummus', 'noodles']; shopping;- 在这种情况下,数组中的每个项目都是一个字符串,但请记住,您可以将任何类型的元素存储在数组中 - 字符串,数字,对象,另一个变量,甚至另一个数组。 您也可以混合和匹配项目类型 - 它们并不都是数字,字符串等。尝试下面这些: +
- 在这种情况下,数组中的每个项目都是一个字符串,但请记住,您可以将任何类型的元素存储在数组中 - 字符串,数字,对象,另一个变量,甚至另一个数组。您也可以混合和匹配项目类型 - 它们并不都是数字,字符串等。尝试下面这些:
@@ -178,7 +178,7 @@let sequence = [1, 1, 2, 3, 5, 8, 13]; let random = ['tree', 795, [0, 1, 2]];访问和修改数组元素
shopping[0]; // returns "bread"-- 您还可以简单地为单个数组元素提供新值来修改数组中的元素。 例如: +
- 您还可以简单地为单个数组元素提供新值来修改数组中的元素。例如:
shopping[0] = 'tahini'; shopping; // shopping will now return [ "tahini", "milk", "cheese", "hummus", "noodles" ]@@ -186,21 +186,21 @@访问和修改数组元素
Note: 我们以前说过,但还是提醒一下 —— 电脑从 0 开始计数!- -
-请注意,数组中包含数组的话称之为多维数组。 您可以通过将两组方括号链接在一起来访问数组内的另一个数组。 例如,要访问数组内部的一个项目,即
+random
数组中的第三个项目(参见上一节),我们可以这样做:请注意,数组中包含数组的话称之为多维数组。您可以通过将两组方括号链接在一起来访问数组内的另一个数组。例如,要访问数组内部的一个项目,即
random
数组中的第三个项目(参见上一节),我们可以这样做:random[2][2];- 在继续之前,尝试对您的数组示例进行一些修改。 玩一玩,看看哪些有效,哪些无效。
+- 在继续之前,尝试对您的数组示例进行一些修改。玩一玩,看看哪些有效,哪些无效。
获取数组长度
-你可以通过使用 {{jsxref("Array.prototype.length","length")}} 属性获取数组的长度(数组中有多少项元素),这与查找字符串的长度(以字符为单位)完全相同 。 尝试以下代码:
+你可以通过使用 {{jsxref("Array.prototype.length","length")}} 属性获取数组的长度(数组中有多少项元素),这与查找字符串的长度(以字符为单位)完全相同。尝试以下代码:
sequence.length; // should return 7-虽然 length 属性也有其他用途,但最常用于循环(循环遍历数组中的所有项)。 例如:
+虽然 length 属性也有其他用途,但最常用于循环(循环遍历数组中的所有项)。例如:
let sequence = [1, 1, 2, 3, 5, 8, 13]; for (let i = 0; i < sequence.length; i++) { @@ -211,7 +211,7 @@获取数组长度
@@ -221,14 +221,14 @@
- 在数组中的元素编号 0 开始循环。
-- 在元素编号等于数组长度的时候停止循环。 这适用于任何长度的数组,但在这种情况下,它将在编号 7 的时候终止循环(这很好,因为我们希望最后一位元素的编号是 6)。
+- 在元素编号等于数组长度的时候停止循环。这适用于任何长度的数组,但在这种情况下,它将在编号 7 的时候终止循环(这很好,因为我们希望最后一位元素的编号是 6)。
- 对于每个元素,使用 console.log() 将其打印到浏览器控制台。
一些有用的数组方法
字符串和数组之间的转换
-通常,您会看到一个包含在一个长长的字符串中的原始数据,您可能希望将有用的项目分成更有用的表单,然后对它们进行处理,例如将它们显示在数据表中。 为此,我们可以使用 {{jsxref("String.prototype.split()","split()")}} 方法。 在其最简单的形式中,这需要一个参数,您要将字符串分隔的字符,并返回分隔符之间的子串,作为数组中的项。
+通常,您会看到一个包含在一个长长的字符串中的原始数据,您可能希望将有用的项目分成更有用的表单,然后对它们进行处理,例如将它们显示在数据表中。为此,我们可以使用 {{jsxref("String.prototype.split()","split()")}} 方法。在其最简单的形式中,这需要一个参数,您要将字符串分隔的字符,并返回分隔符之间的子串,作为数组中的项。
Note: 好吧,从技术上讲,这是一个字符串方法,而不是一个数组方法,但是我们把它放在数组中,因为它在这里很合适。
-
- 我们来玩一下这个方法,看看它是如何工作的。 首先,在控制台中创建一个字符串: +
- 我们来玩一下这个方法,看看它是如何工作的。首先,在控制台中创建一个字符串:
let myData = 'Manchester,London,Liverpool,Birmingham,Leeds,Carlisle';- 现在我们用每个逗号分隔它: @@ -241,11 +241,11 @@
-字符串和数组之间的转换
- 您也可以使用 {{jsxref("Array.prototype.join()","join()")}} 方法进行相反的操作。 尝试以下: +
- 您也可以使用 {{jsxref("Array.prototype.join()","join()")}} 方法进行相反的操作。尝试以下:
-let myNewString = myArray.join(','); myNewString;- 将数组转换为字符串的另一种方法是使用 {{jsxref("Array.prototype.toString()","toString()")}} 方法。
toString()
可以比join()
更简单,因为它不需要一个参数,但更有限制。 使用join()
可以指定不同的分隔符(尝试使用与逗号不同的字符运行步骤4)。 +- 将数组转换为字符串的另一种方法是使用 {{jsxref("Array.prototype.toString()","toString()")}} 方法。
@@ -253,14 +253,14 @@toString()
可以比join()
更简单,因为它不需要一个参数,但更有限制。使用join()
可以指定不同的分隔符(尝试使用与逗号不同的字符运行步骤 4)。let dogNames = ["Rocket","Flash","Bella","Slugger"]; dogNames.toString(); //Rocket,Flash,Bella,Slugger字符串和数组之间的转换
添加和删除数组项 -我们还没有涵盖添加和删除数组元素,现在让我们来看看。 我们将使用在上一节中最后提到的
+myArray
数组。 如果您尚未遵循该部分,请先在控制台中创建数组:我们还没有涵盖添加和删除数组元素,现在让我们来看看。我们将使用在上一节中最后提到的
myArray
数组。如果您尚未遵循该部分,请先在控制台中创建数组:let myArray = ['Manchester', 'London', 'Liverpool', 'Birmingham', 'Leeds', 'Carlisle'];首先,要在数组末尾添加或删除一个项目,我们可以使用 {{jsxref("Array.prototype.push()","push()")}} 和 {{jsxref("Array.prototype.pop()","pop()")}}。
-
- 让我们先使用
push()
—— 注意,你需要添加一个或多个要添加到数组末尾的元素。 尝试下面的代码: +- 让我们先使用
-push()
—— 注意,你需要添加一个或多个要添加到数组末尾的元素。尝试下面的代码:myArray.push('Cardiff'); myArray; @@ -268,15 +268,15 @@添加和删除数组项
myArray;- 当方法调用完成时,将返回数组的新长度。 如果要将新数组长度存储在变量中。例如: +
- 当方法调用完成时,将返回数组的新长度。如果要将新数组长度存储在变量中。例如:
-var newLength = myArray.push('Bristol'); myArray; newLength;- 从数组中删除最后一个元素的话直接使用
pop()
就可以。 例如: +- 从数组中删除最后一个元素的话直接使用
-pop()
就可以。例如:myArray.pop();- 当方法调用完成时,将返回已删除的项目。 你也可以这样做: +
- 当方法调用完成时,将返回已删除的项目。你也可以这样做:
let removedItem = myArray.pop(); myArray; removedItem;@@ -300,15 +300,15 @@添加和删除数组项
积极学习:打印这些产品
-我们回到前面描述的例子 —— 打印出发票上的产品名称和价格,然后计算总价格并将其印在底部。 在下面的可编辑示例中,包含数字的注释 —— 每个注释标记都是您必须向代码添加内容的地方。 它们如下:
+我们回到前面描述的例子 —— 打印出发票上的产品名称和价格,然后计算总价格并将其印在底部。在下面的可编辑示例中,包含数字的注释 —— 每个注释标记都是您必须向代码添加内容的地方。它们如下:
-
- 在
-// number 1
注释下面是一些字符串,每个字符串包含一个产品名称和一个冒号分隔的价格。 我们希望您将其转换为一个数组,并将其存储在名为products
的数组中。- 与
-// number 2
注释同一行的是 for 循环的开头。 在这行中,我们目前有i <= 0
,这是一个条件测试,导致 for循环 立即停止,因为它说“当i
不再小于或等于0”时停止,而i
从0开始。 我们希望您使用条件测试来替换它,当i
不再小于products
数组的长度时,该条件测试会停止循环。- 就在
-// number 3
注释的下方,我们希望您编写一行代码,将当前数组项目(名称:价格)分成两个独立的项目,一个只包含该名称,一个只包含该价格。 如果您不确定如何执行此操作,请参阅有用的字符串方法文章以获得一些帮助,甚至更好的看看本文中的字符串和数组之间的转换部分。- 作为上述代码行的一部分,您还需要将价格从字符串转换为数字。 如果你不记得如何做,请查看第一个字符串文章。
-- 有一个名为
-total
的变量被创建,并在代码的顶部赋值为 0。 在循环内(在// number 4
注释下面),我们希望您添加一行,将当前项目价格添加到循环中的迭代变量,以便在代码结尾处将正确的总数打印到发票上。 您可能需要一个赋值运算符来执行此操作。- 我们希望您改变
+// number 5
注释的行,以便使itemText
变量等于“当前项目名称 - $ 当前项目价格”,例如“Shoes - $ 23.99”,以此将每个项目的正确信息都印在发票上。 这只是简单的字符串连接,您应该对此很熟悉。- 在
+// number 1
注释下面是一些字符串,每个字符串包含一个产品名称和一个冒号分隔的价格。我们希望您将其转换为一个数组,并将其存储在名为products
的数组中。- 与
+// number 2
注释同一行的是 for 循环的开头。在这行中,我们目前有i <= 0
,这是一个条件测试,导致 for 循环 立即停止,因为它说“当i
不再小于或等于 0”时停止,而i
从 0 开始。我们希望您使用条件测试来替换它,当i
不再小于products
数组的长度时,该条件测试会停止循环。- 就在
+// number 3
注释的下方,我们希望您编写一行代码,将当前数组项目(名称:价格)分成两个独立的项目,一个只包含该名称,一个只包含该价格。如果您不确定如何执行此操作,请参阅有用的字符串方法文章以获得一些帮助,甚至更好的看看本文中的字符串和数组之间的转换部分。- 作为上述代码行的一部分,您还需要将价格从字符串转换为数字。如果你不记得如何做,请查看第一个字符串文章。
+- 有一个名为
+total
的变量被创建,并在代码的顶部赋值为 0。在循环内(在// number 4
注释下面),我们希望您添加一行,将当前项目价格添加到循环中的迭代变量,以便在代码结尾处将正确的总数打印到发票上。您可能需要一个赋值运算符来执行此操作。- 我们希望您改变
// number 5
注释的行,以便使itemText
变量等于“当前项目名称 - $ 当前项目价格”,例如“Shoes - $ 23.99”,以此将每个项目的正确信息都印在发票上。这只是简单的字符串连接,您应该对此很熟悉。@@ -387,20 +387,20 @@Playable code
{{ EmbedLiveSample('Playable_code', '100%', 600) }}
-积极学习:前5个搜索
+积极学习:前 5 个搜索
-当您在 Web 程序中维护当前活动元素的记录时,{{jsxref("Array.prototype.push()","push()")}} 和 {{jsxref("Array.prototype.pop()","pop()")}} 是不错的方法。 例如,在动画场景中,您可能会有一系列表示当前显示的背景图像的对象,并且由于性能或混乱原因,您可能只需要一次显示 50 个。 当创建新对象并将其添加到数组中时,可以从数组中删除较旧的对象以保持所需的数量。
+当您在 Web 程序中维护当前活动元素的记录时,{{jsxref("Array.prototype.push()","push()")}} 和 {{jsxref("Array.prototype.pop()","pop()")}} 是不错的方法。例如,在动画场景中,您可能会有一系列表示当前显示的背景图像的对象,并且由于性能或混乱原因,您可能只需要一次显示 50 个。当创建新对象并将其添加到数组中时,可以从数组中删除较旧的对象以保持所需的数量。
-在这个例子中,我们将展示一种更简单的使用方法 - 在这里我们给你一个假的搜索网站,一个搜索框。 这个想法是,当在搜索框中输入时,列表中会显示5个先前的搜索字词。 当列表项目数量超过 5 时,每当新项目被添加到顶部时,最后一个项目开始被删除,因此总是显示5个以前的搜索字词。
+在这个例子中,我们将展示一种更简单的使用方法 - 在这里我们给你一个假的搜索网站,一个搜索框。这个想法是,当在搜索框中输入时,列表中会显示 5 个先前的搜索字词。当列表项目数量超过 5 时,每当新项目被添加到顶部时,最后一个项目开始被删除,因此总是显示 5 个以前的搜索字词。
-Note: 在真正的搜索应用中,您可能可以点击先前的搜索字词返回上一次搜索,并显示实际的搜索结果! 我们现在只是保持简单的逻辑。
+Note: 在真正的搜索应用中,您可能可以点击先前的搜索字词返回上一次搜索,并显示实际的搜索结果!我们现在只是保持简单的逻辑。
要完成该应用程序,我们需要您:
-
@@ -492,7 +492,7 @@- 在
+//number 1
注释下面添加一行,将输入到搜索框中的当前值添加到数组的开头。 这可以使用searchInput.value
检索。- 在
//number 1
注释下面添加一行,将输入到搜索框中的当前值添加到数组的开头。这可以使用searchInput.value
检索。- 在
// number 2
注释下方添加一行,该行删除数组末尾的当前值。Playable code 2
总结
-阅读本文后,我们相信您会明白数组是很有用的; 你会看到它们在 JavaScript 中随处可见,通常与循环相关,以便对数组中的每个元素做同样的事情。 我们将教你所有有用的基础知识,了解下一个模块中的循环,但现在你应该给自己鼓掌,并稍加休息; 您已经完成了本单元中的所有文章!
+阅读本文后,我们相信您会明白数组是很有用的; 你会看到它们在 JavaScript 中随处可见,通常与循环相关,以便对数组中的每个元素做同样的事情。我们将教你所有有用的基础知识,了解下一个模块中的循环,但现在你应该给自己鼓掌,并稍加休息; 您已经完成了本单元中的所有文章!
唯一需要做的就是通过这个模块的评估,这将测试你对之前的文章的理解。
diff --git a/files/zh-cn/learn/javascript/first_steps/math/index.html b/files/zh-cn/learn/javascript/first_steps/math/index.html index b3d1959f858ad6..e8e19fafca4cfd 100644 --- a/files/zh-cn/learn/javascript/first_steps/math/index.html +++ b/files/zh-cn/learn/javascript/first_steps/math/index.html @@ -1,5 +1,5 @@ --- -title: JavaScript中的基础数学 — 数字和操作符 +title: JavaScript 中的基础数学 — 数字和操作符 slug: Learn/JavaScript/First_steps/Math translation_of: Learn/JavaScript/First_steps/Math --- @@ -13,7 +13,7 @@前提: -基本的计算机知识,对HTML和CSS初步了解,知道JavaScript是什么。 +基本的计算机知识,对 HTML 和 CSS 初步了解,知道 JavaScript 是什么。 目标: @@ -33,26 +33,26 @@数字类型
在编程中,即使是人人熟知的最普遍的十进制数,也比你想象的要复杂的多。我们使用不同的术语来描述不同类型的十进制数,例如:
-
-- 整数 就是整数,例如 10, 400, 或者 -5.
+- 整数 就是整数,例如 10, 400, 或者 -5.
- 浮点数 (浮点) 有小数点或小数位,例如 12.5,和 56.7786543。
- 双精度双精度是一种特定类型的浮点数,它们具有比标准浮点数更高的精度(这意味着它们精确到更大的小数位数)。
我们甚至有不同类型的数字系统! 十进制是基数10(意味着它在每列使用0-9),但是我们也有这样的东西:
+我们甚至有不同类型的数字系统!十进制是基数 10(意味着它在每列使用 0-9),但是我们也有这样的东西:
-
- 二进制 — 计算机的最基础语言—— 0 和 1
-- 八进制 — 基数8,每列使用0-7
-- 十六进制 — 基数16,每列使用0-9,然后使用a-f。 在CSS中设置颜色时,可能会遇到这些数字。
+- 八进制 — 基数 8,每列使用 0-7
+- 十六进制 — 基数 16,每列使用 0-9,然后使用 a-f。在 CSS 中设置颜色时,可能会遇到这些数字。
在你开始担心你的大脑混乱之前,先停下来吧! 一开始,我们将在本课程中坚持使用十进制数; 你很少会遇到需要开始考虑其他类型的情况,如果有的话。
+在你开始担心你的大脑混乱之前,先停下来吧!一开始,我们将在本课程中坚持使用十进制数; 你很少会遇到需要开始考虑其他类型的情况,如果有的话。
-第二个好消息是,与其他一些编程语言不同,JavaScript只有一个数据类型用来表示数字(包括 integers 和 decimals ),您猜对了,{{jsxref("Number")}}。 这意味着,你在JavaScript中处理的任何类型的数字,都以完全相同的方式处理它们。
+第二个好消息是,与其他一些编程语言不同,JavaScript 只有一个数据类型用来表示数字(包括 integers 和 decimals),您猜对了,{{jsxref("Number")}}。这意味着,你在 JavaScript 中处理的任何类型的数字,都以完全相同的方式处理它们。
这是我们的全部数字
-让我们快点玩一些数字,以重新定义我们所需要的基本语法。 在您的开发工具JavaScript控制台中输入下面列出的命令。
+让我们快点玩一些数字,以重新定义我们所需要的基本语法。在您的开发工具 JavaScript 控制台中输入下面列出的命令。
@@ -64,7 +64,7 @@这是我们的全部数字
myFloat;- 数值键入不带引号 —— 在继续之前尝试声明和初始化更多包含数字的变量。
-- 现在我们来看看我们的原始变量是否是相同的数据类型。 在JavaScript中有一个称为{{jsxref("Operators / typeof", "typeof")}} 的运算符。 输入如下所示的两行: +
- 现在我们来看看我们的原始变量是否是相同的数据类型。在 JavaScript 中有一个称为{{jsxref("Operators / typeof", "typeof")}} 的运算符。输入如下所示的两行:
@@ -110,17 +110,17 @@typeof myInt; typeof myFloat;在这两种情况下,都应该返回"number"
—— 这使得事情变得更简单,因为若是不同的数字具有不同的数据类型,那么我们还须以不同的方式处理它们。呦!算术运算符
- %
求余(有时候也叫取模) +求余 (有时候也叫取模) - 在你将左边的数分成同右边数字相同的若干整数部分后,返回剩下的余数
+ 8 % 3
(返回 2,8除以3的倍数,余下2 。)8 % 3
(返回 2,8 除以 3 的倍数,余下 2。)@@ -128,14 +128,14 @@ **
幂 - 取底数的指数次方,即指数所指定的底数相乘。它在EcmaScript 2016 中首次引入。
+取底数的指数次方,即指数所指定的底数相乘。它在 EcmaScript 2016 中首次引入。
5 ** 5
(返回 3125,相当于5 * 5 * 5 * 5 * 5
。)算术运算符
Note: 你以后有时候会看到参与算术计算的数字被称为 操作数({{Glossary("Operand", "operands")}})。
+Note: 你以后有时候会看到参与算术计算的数字被称为 操作数 ({{Glossary("Operand", "operands")}})。
Note: 有时你可能会看到使用较旧的 {{jsxref("Math.pow()")}} 方法表达的指数,该方法的工作方式非常相似。 例如,在 Math.pow(7, 3)
中,7
是基数,3
是指数,因此表达式的结果是 343
。 Math.pow(7, 3)
相当于 7 ** 3
。
Note: 有时你可能会看到使用较旧的 {{jsxref("Math.pow()")}} 方法表达的指数,该方法的工作方式非常相似。例如,在 Math.pow(7, 3)
中,7
是基数,3
是指数,因此表达式的结果是 343
。 Math.pow(7, 3)
相当于 7 ** 3
。
我们可能不需要教你如何做基础数学,但我们想测试你对所涉及的语法的理解。 尝试将下面的示例输入到开发者工具JavaScript控制台中。
+我们可能不需要教你如何做基础数学,但我们想测试你对所涉及的语法的理解。尝试将下面的示例输入到开发者工具 JavaScript 控制台中。
let num1 = 10; let num2 = 50; 9 * num1; @@ -161,46 +161,46 @@算术运算符
运算符优先级
-我们来看看上面的最后一个例子,假设num2的值为50,num1的值为10(如上所述):
+我们来看看上面的最后一个例子,假设 num2 的值为 50,num1 的值为 10(如上所述):
num2 + num1 / 8 + 2;-一般人,你会将它看作“50加10等于60”,然后“8加2等于10”,最后“60除以10等于6”。
+一般人,你会将它看作“50 加 10 等于 60”,然后“8 加 2 等于 10”,最后“60 除以 10 等于 6”。
-但浏览器的“10除以8等于1.25”,那么“50加1.25加2等于53.25”。
+但浏览器的“10 除以 8 等于 1.25”,那么“50 加 1.25 加 2 等于 53.25”。
-这是因为运算符优先级 —— 一些运算符将在计算算式(在编程中称为表达式)的结果时先于其他运算符被执行。 JavaScript中的运算符优先级与学校的数学课程相同 - 乘法和除法总是先完成,然后是加法和减法(总是从左到右进行计算)。
+这是因为运算符优先级 —— 一些运算符将在计算算式(在编程中称为表达式)的结果时先于其他运算符被执行。JavaScript 中的运算符优先级与学校的数学课程相同 - 乘法和除法总是先完成,然后是加法和减法(总是从左到右进行计算)。
-如果想要改变计算优先级,可以把想要优先计算的部分用括号围住。 所以要得到结果为6,我们可以这样做:
+如果想要改变计算优先级,可以把想要优先计算的部分用括号围住。所以要得到结果为 6,我们可以这样做:
(num2 + num1) / (8 + 2);尝试看看。
-Note: 注意:可以在表达式和运算符中找到所有JavaScript运算符的完整列表及其优先级。
+Note: 注意:可以在表达式和运算符中找到所有 JavaScript 运算符的完整列表及其优先级。
自增和自减运算符
-有时候,您需要反复把一个变量加1或减1。 这可以方便地使用增量(
+++
)和递减(--
)运算符来完成。 我们在JavaScript 初体验文章的“猜数字”游戏中使用了++,当我们添加1到我们的guessCount变量来跟踪用户在每次转动之后剩下的猜测时。有时候,您需要反复把一个变量加 1 或减 1。这可以方便地使用增量(
++
)和递减(--
)运算符来完成。我们在JavaScript 初体验文章的“猜数字”游戏中使用了++,当我们添加 1 到我们的 guessCount 变量来跟踪用户在每次转动之后剩下的猜测时。guessCount++;--Note: 它们最常用于 循环 中,您将在以后的课程中了解。 例如,假设您想循环查看价格表,并为每个价格增加销售税。 您可以使用循环依次查看每个值,并在每种情况下进行必要的计算,以添加销售税。 当需要时,增量器用于移动到下一个值。 我们实际上提供了一个简单的例子,显示了如何完成 —— 在线查看效果,并 查看源代码,看看是否可以发现增量器! 我们稍后将会详细介绍循环。
+Note: 它们最常用于 循环 中,您将在以后的课程中了解。例如,假设您想循环查看价格表,并为每个价格增加销售税。您可以使用循环依次查看每个值,并在每种情况下进行必要的计算,以添加销售税。当需要时,增量器用于移动到下一个值。我们实际上提供了一个简单的例子,显示了如何完成 —— 在线查看效果,并 查看源代码,看看是否可以发现增量器!我们稍后将会详细介绍循环。
我们来试试看你们的控制台。 首先,请注意,您不能将这些直接应用于一个数字,这可能看起来很奇怪,但是我们为变量赋值一个新的更新值,而不是对该值进行操作。 以下将返回错误:
+我们来试试看你们的控制台。首先,请注意,您不能将这些直接应用于一个数字,这可能看起来很奇怪,但是我们为变量赋值一个新的更新值,而不是对该值进行操作。以下将返回错误:
3++;-所以,你只能增加一个现有的变量。 尝试这个:
+所以,你只能增加一个现有的变量。尝试这个:
let num1 = 4; num1++;-好的,第二个奇怪的东西! 执行此操作时,您会看到返回值为4,这是因为浏览器返回当前值,然后增加变量。 如果您再次返回变量值,则可以看到它已经递增:
+好的,第二个奇怪的东西!执行此操作时,您会看到返回值为 4,这是因为浏览器返回当前值,然后增加变量。如果您再次返回变量值,则可以看到它已经递增:
num1;@@ -211,18 +211,18 @@自增和自减运算符
num2;
Note: 您可以使浏览器以其他方式进行操作 - 递增/递减变量,然后返回值 - 将操作符放在变量的开头,而不是结束。 再次尝试上面的例子,但这次使用 ++num1
和 --num2
。
Note: 您可以使浏览器以其他方式进行操作 - 递增/递减变量,然后返回值 - 将操作符放在变量的开头,而不是结束。再次尝试上面的例子,但这次使用 ++num1
和 --num2
。
赋值运算符是向变量分配值的运算符。 我们已经使用了最基本的一个很多次了:=
, 它只是将右边的值赋给左边的变量 ,即:
赋值运算符是向变量分配值的运算符。我们已经使用了最基本的一个很多次了:=
,它只是将右边的值赋给左边的变量,即:
let x = 3; // x 的值是 3 let y = 4; // y 的值是 4 -x = y; // x 和 y 有相同的值, 4+x = y; // x 和 y 有相同的值,4 -
但是还有一些更复杂的类型,它们提供了有用的快捷方式,可以使您的代码更加清洁和高效。 最常见的如下:
+但是还有一些更复杂的类型,它们提供了有用的快捷方式,可以使您的代码更加清洁和高效。最常见的如下:
尝试在你的控制台中输入上面的一些示例,以了解它们的工作原理。 在每种情况下,你是否可以猜出在输入第二行之前的值。
+尝试在你的控制台中输入上面的一些示例,以了解它们的工作原理。在每种情况下,你是否可以猜出在输入第二行之前的值。
请注意,您可以愉快地使用每个表达式右侧的其他变量,例如:
@@ -288,24 +288,24 @@在这个练习中,我们将让你填写一些数字和操作符来操纵一个框的大小。 该框使用称为{{domxref("Canvas API", "", "", "true")}}的浏览器API绘制。 没有必要担心这是如何工作的 - 现在只关注数学。 盒子的宽度和高度(以像素为单位)由变量 x
和 y
定义,变量 x
和 y
最初都被赋值为50。
在这个练习中,我们将让你填写一些数字和操作符来操纵一个框的大小。该框使用称为{{domxref("Canvas API", "", "", "true")}}的浏览器 API 绘制。没有必要担心这是如何工作的 - 现在只关注数学。盒子的宽度和高度(以像素为单位)由变量 x
和 y
定义,变量 x
和 y
最初都被赋值为 50。
{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/maths/editable_canvas.html", '100%', 620)}}
-在上面的可编辑代码框中,有两行标有清晰的注释,我们希望你更新以使框增长/缩小到某些大小,在每种情况下使用某些操作符和/或值。 我们希望你回答以下问题:
+在上面的可编辑代码框中,有两行标有清晰的注释,我们希望你更新以使框增长/缩小到某些大小,在每种情况下使用某些操作符和/或值。我们希望你回答以下问题:
如果你完全混淆了代码,别担心。 您可以随时按“重置”按钮,使事情恢复正常。 在您正确回答了上述所有问题后,可以自由地使用代码或创建自己的挑战。
+如果你完全混淆了代码,别担心。您可以随时按“重置”按钮,使事情恢复正常。在您正确回答了上述所有问题后,可以自由地使用代码或创建自己的挑战。
Note: 您可能会看到有些人在他们的代码中使用==
和!=
来判断相等和不相等,这些都是JavaScript中的有效运算符,但它们与===
/!==
不同,前者测试值是否相同, 但是数据类型可能不同,而后者的严格版本测试值和数据类型是否相同。 严格的版本往往导致更少的错误,所以我们建议您使用这些严格的版本。
Note: 您可能会看到有些人在他们的代码中使用==
和!=
来判断相等和不相等,这些都是 JavaScript 中的有效运算符,但它们与===
/!==
不同,前者测试值是否相同,但是数据类型可能不同,而后者的严格版本测试值和数据类型是否相同。严格的版本往往导致更少的错误,所以我们建议您使用这些严格的版本。
如果您尝试在控制台中输入这些值,您将看到它们都返回 true
/false
值 - 我们在上一篇文章中提到的那些布尔值。 这些是非常有用的,因为它们允许我们在我们的代码中做出决定 - 每次我们想要选择某种类型时,都会使用这些代码,例如:
如果您尝试在控制台中输入这些值,您将看到它们都返回 true
/false
值 - 我们在上一篇文章中提到的那些布尔值。这些是非常有用的,因为它们允许我们在我们的代码中做出决定 - 每次我们想要选择某种类型时,都会使用这些代码,例如:
当我们在以后的的文章中查看条件语句时,我们将介绍如何编写这样的逻辑。 现在,我们来看一个简单的例子:
+当我们在以后的的文章中查看条件语句时,我们将介绍如何编写这样的逻辑。现在,我们来看一个简单的例子:
<button>Start machine</button> <p>The machine is stopped.</p> @@ -396,7 +396,7 @@比较运算符
-您可以在updateBtn()函数内看到正在使用的等号运算符。 在这种情况下,我们不会测试两个数学表达式是否具有相同的值 - 我们正在测试一个按钮的文本内容是否包含某个字符串 - 但它仍然是工作原理。 如果按钮当前为“启动机器(start machine)”,则将其标签更改为“停止机器(stop machine)”,并根据需要更新标签。 如果按钮上写着“停机”时被按下,我们将显示回原来的内容。
+您可以在 updateBtn()函数内看到正在使用的等号运算符。在这种情况下,我们不会测试两个数学表达式是否具有相同的值 - 我们正在测试一个按钮的文本内容是否包含某个字符串 - 但它仍然是工作原理。如果按钮当前为“启动机器(start machine)”,则将其标签更改为“停止机器(stop machine)”,并根据需要更新标签。如果按钮上写着“停机”时被按下,我们将显示回原来的内容。
Note: 这种在两个状态之间来回交换的行为通常被称为 切换 (toggle)。它在一个状态和另一个状态之间切换 - 点亮,熄灭等
@@ -404,12 +404,12 @@比较运算符
总结
-在本文中,我们已经介绍了现在需要了解JavaScript中数字的基本信息。 你会发现,在你学习JavaScript过程中,num类型的数据一直都在被使用,所以熟练的掌握它是一个不错的选择。 如果你是那些不喜欢数学的人之一,你应该庆幸这一章内容很简短。
+在本文中,我们已经介绍了现在需要了解 JavaScript 中数字的基本信息。你会发现,在你学习 JavaScript 过程中,num 类型的数据一直都在被使用,所以熟练的掌握它是一个不错的选择。如果你是那些不喜欢数学的人之一,你应该庆幸这一章内容很简短。
-在下一篇文章中,我们将探讨文本,以及JavaScript如何让我们操纵它。
+在下一篇文章中,我们将探讨文本,以及 JavaScript 如何让我们操纵它。
-Note: 如果您喜欢数学,并希望阅读更多关于它如何在JavaScript中实现的, 那么你可以在 MDN's main JavaScript 部分读到更多关于它的内容。对于学习数字与日期 和 表达式与运算符 来说,那是一个不错的地方。
+Note: 如果您喜欢数学,并希望阅读更多关于它如何在 JavaScript 中实现的,那么你可以在 MDN's main JavaScript 部分读到更多关于它的内容。对于学习数字与日期 和 表达式与运算符 来说,那是一个不错的地方。
{{PreviousMenuNext("Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps")}}
@@ -423,7 +423,7 @@在这个模块
- 存储你需要的信息——变量
- JavaScript 中的基本运算——数值和运算符
- 文字处理——JavaScript 字符串
-- 实用的strings方法
+- 实用的 strings 方法
- Arrays
- Assessment: Silly story generator
diff --git a/files/zh-cn/learn/javascript/first_steps/silly_story_generator/index.html b/files/zh-cn/learn/javascript/first_steps/silly_story_generator/index.html index 197cad292eeb6e..6181f15b0c30a2 100644 --- a/files/zh-cn/learn/javascript/first_steps/silly_story_generator/index.html +++ b/files/zh-cn/learn/javascript/first_steps/silly_story_generator/index.html @@ -163,7 +163,7 @@步骤
以下是你的工作。
-初始化变量和函数:
+初始化变量和函数:
- 将刚下载的文本文件中的“1. 定义变量和函数”标题项下所有代码复制粘贴至 main.js 中。此时你就有了三个变量(
@@ -195,7 +195,7 @@customName
是对“输入自定义的名字”文本框的引用,randomize
是对“随机生成笑话”按钮的引用,story
是对 HTML 底部的、准备存放笑话的 {{htmlelement("p")}} 元素的引用)和一个函数(randomValueFromArray()
取一个数组作参数,随机返回数组中的一个元素)。步骤
- 将
newStory
的值设置为storyText
。声明新变量有必要的,只有这样才能在每次按下按钮后、在函数运行时生成一个新的随机笑话。如果直接操作storyText
则只能生成一次新故事- 将
xItem
、yItem
和zItem
分别设置为randomValueFromArray(insertX)
、randomValueFromArray(insertY)
和randomValueFromArray(insertZ)
。- 接下来将
-newStory
中的占位符(:inserta:
、:insertb:
和:insertc:
)替换为xItem
、yItem
和zItem
。有专用的字符串方法可供使用,并用该方法的返回值为newStory
赋值。每当按下按钮时,这些占位符都会替换为随机的笑话字符串。再给你一点提示,我们所说的这种方法每次只会将所找到的首个子字符串进行替换,因此该方法对某个占位符需要执行两次。- 在第一个
+if
块中再次调用这个字符串替换方法,以使newStory
字符串中的名字“李雷”替换为变量name
的值 。这里我们说:“如果customName
中有值,就把故事里的 “李雷”替换成它。” 如果是汉化版将newStory中的“李雷”替换成name
的值;- 在第一个
if
块中再次调用这个字符串替换方法,以使newStory
字符串中的名字“李雷”替换为变量name
的值。这里我们说:“如果customName
中有值,就把故事里的“李雷”替换成它。”如果是汉化版将 newStory 中的“李雷”替换成name
的值;- 在第二个
-if
块中检查american
单选按钮是否被选中。如果选中,就要将故事中的重量和温度值从公斤和摄氏度转换为磅和华氏度,具体事项如下:
- 确定英美单位的转换公式。
@@ -203,7 +203,7 @@步骤
- 就在上述两个变量的定义下方增加两个字符串置换操作,将“35 摄氏度”替换为
temperature
的值,将“140 公斤”替换为weight
的值。- 最后,在函数倒数第二行,将
+story.textContent
(程序中显示笑话结果的段落) 赋值为newStory
。- 最后,在函数倒数第二行,将
story.textContent
(程序中显示笑话结果的段落)赋值为newStory
。提示
@@ -215,7 +215,7 @@提示
document.querySelector('html').style.backgroundColor = 'red';
- -
Math.round()
是 Javascript 的内建函数,可取得与传入小数最接近的整数。- 本示例中有三类字符串需要替换。可以多次重复
+replace()
方法,也可使用正则表达式。例如:var text = 'I am the biggest lover, I love my love';
或text.replace(/love/g,'like');
会将所有的“love”替换为“like”。记住,字符串本身是不可修改的!- 本示例中有三类字符串需要替换。可以多次重复
replace()
方法,也可使用正则表达式。例如:var text = 'I am the biggest lover, I love my love';
或text.replace(/love/g,'like');
会将所有的“love”替换为“like”。记住,字符串本身是不可修改的!测验
diff --git a/files/zh-cn/learn/javascript/first_steps/strings/index.html b/files/zh-cn/learn/javascript/first_steps/strings/index.html index 940f6508355159..d42c348e8f4d28 100644 --- a/files/zh-cn/learn/javascript/first_steps/strings/index.html +++ b/files/zh-cn/learn/javascript/first_steps/strings/index.html @@ -1,5 +1,5 @@ --- -title: 文本处理 — JavaScript中的字符串 +title: 文本处理 — JavaScript 中的字符串 slug: Learn/JavaScript/First_steps/Strings tags: - JavaScript @@ -15,31 +15,31 @@{{PreviousMenuNext("Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps")}}-接下来,我们将把注意力转向文本片段——也就是编程中所说的字符串。在本文中,我们将了解在学习JavaScript时,您应该了解的关于字符串的所有常见事项,例如创建字符串、在字符串中转义引号,和连接字符串。
+接下来,我们将把注意力转向文本片段——也就是编程中所说的字符串。在本文中,我们将了解在学习 JavaScript 时,您应该了解的关于字符串的所有常见事项,例如创建字符串、在字符串中转义引号,和连接字符串。
- 预备知识: -基本的计算机读写能力,对HTML和CSS的基本理解,对JavaScript的理解。 +预备知识: +基本的计算机读写能力,对 HTML 和 CSS 的基本理解,对 JavaScript 的理解。 - 目标: -要熟悉JavaScript中字符串的基本知识。 +目标: +要熟悉 JavaScript 中字符串的基本知识。 语言的力量
-语言对人类非常重要——它们是我们交流的重要组成部分。由于Web是一种主要基于文本的媒介,旨在让人们进行交流和分享信息,因此对我们来说,掌握它所出现的单词是很有用的。{{glossary("HTML")}}为我们的文本提供了结构和意义, {{glossary("CSS")}} 允许我们精确地设计它的样式,JavaScript包含许多操作字符串的特性,创建定制的欢迎消息,在需要时显示正确的文本标签,将术语排序到所需的顺序,等等。
+语言对人类非常重要——它们是我们交流的重要组成部分。由于 Web 是一种主要基于文本的媒介,旨在让人们进行交流和分享信息,因此对我们来说,掌握它所出现的单词是很有用的。{{glossary("HTML")}}为我们的文本提供了结构和意义, {{glossary("CSS")}} 允许我们精确地设计它的样式,JavaScript 包含许多操作字符串的特性,创建定制的欢迎消息,在需要时显示正确的文本标签,将术语排序到所需的顺序,等等。
到目前为止,我们在课程中展示的所有程序都涉及到一些字符串操作。
字符串 — 基本知识
字符串与数字的处理方式第一眼看上去十分相似,但是当您深入挖掘时,您将会看到一些显著的差异。让我们首先在一个控制台输入一些基本的行来熟悉一下。
+ 我们在下面提供了一个 (您也可以在一个单独的选项卡或窗口中打开这个控制台,或者如果您愿意使用浏览器开发人员控制台)。
- 我们在下面提供了一个(您也可以在一个单独的选项卡或窗口中打开这个控制台,或者如果您愿意使用浏览器开发人员控制台)。Hidden code
@@ -152,18 +152,18 @@Hidden code
创建一个字符串
-
- 首先, 输入下面的代码: +
- 首先,输入下面的代码:
let string = 'The revolution will not be televised.'; string;就像我们处理数字一样,我们声明一个变量,用一个字符串值初始化它,然后返回值。这里惟一的区别是,在编写字符串时,我们需要在字符串上加上引号。- 如果你不这样做,或者在书写过程中,漏掉其中一个引号,你就会得到一个错误。
-
- 试着输入以下几行: + 试着输入以下几行:let badString = This is a test; let badString = 'This is a test; let badString = This is a test';- 这些行不起作用,因为没有引号的任何文本字符串都被假定为变量名、属性名、保留字或类似。如果浏览器不能找到它,那么将会引发语法错误(例如:"missing ; before statement")。
- 如果浏览器能够识别字符串从哪里开始,但是不能找到字符串的结尾符,如第二行所示,那么它则会提示这样的错误(“unterminated string literal”)。如果您写的程序目前也引发这样的错误,那么请你回过头来仔细检查你的代码,看是否漏写了引号。- 如果您之前定义了变量字符串,下面的操作将会起作用 — 现在来试一试: + 这些行不起作用,因为没有引号的任何文本字符串都被假定为变量名、属性名、保留字或类似。如果浏览器不能找到它,那么将会引发语法错误 (例如:"missing ; before statement")。
+
+ 如果浏览器能够识别字符串从哪里开始,但是不能找到字符串的结尾符,如第二行所示,那么它则会提示这样的错误 (“unterminated string literal”)。如果您写的程序目前也引发这样的错误,那么请你回过头来仔细检查你的代码,看是否漏写了引号。- 如果您之前定义了变量字符串,下面的操作将会起作用 — 现在来试一试:
let badString = string; badString;@@ -174,32 +174,32 @@创建一个字符串
单引号和双引号
-
- 在JavaScript中,您可以选择单引号或双引号来包裹字符串。
- 下面两种方式都可以: +- 在 JavaScript 中,您可以选择单引号或双引号来包裹字符串。
+ 下面两种方式都可以:let sgl = 'Single quotes.'; let dbl = "Double quotes"; sgl; dbl;- 两者之间几乎没有什么区别,根据个人偏好来使用。但是,您应该选择一个并坚持使用它,不一致的引号混用代码可能会让人很迷惑,特别是如果您在同一个字符串中使用不同的引号!
- 下面将返回一个错误: + 下面将返回一个错误:let badQuotes = 'What on earth?";- 浏览器会认为字符串没有被关闭,因为在字符串中您没有使用其他类型的引号。
-
- 例如,这两种情况都是可以的: + 例如,这两种情况都是可以的:let sglDbl = 'Would you eat a "fish supper"?'; let dblSgl = "I'm feeling blue."; sglDbl; dblSgl;- 但是,您不能在字符串中包含相同的引号,因为它是用来包含它们的。下面将会出现错误,因为它会混淆浏览器和字符串的结束位置: +
- 但是,您不能在字符串中包含相同的引号,因为它是用来包含它们的。下面将会出现错误,因为它会混淆浏览器和字符串的结束位置:
let bigmouth = 'I've got no right to take my place...';这个指引将会让我们很好地进入下一个主题。转义字符串中的字符
-要修复我们之前的问题代码行,我们需要避免引号的问题。转义字符意味着我们对它们做一些事情,以确保它们被识别成文本,而不是代码的一部分。在JavaScript中,我们通过在字符之前放一个反斜杠来实现这一点。试试这个:
+要修复我们之前的问题代码行,我们需要避免引号的问题。转义字符意味着我们对它们做一些事情,以确保它们被识别成文本,而不是代码的一部分。在 JavaScript 中,我们通过在字符之前放一个反斜杠来实现这一点。试试这个:
let bigmouth = 'I\'ve got no right to take my place...'; bigmouth;@@ -209,7 +209,7 @@转义字符串中的字符
连接字符串
-
- 连接是一个很花哨的编程词,意思是“连接在一起”。在JavaScript中连接字符串使用加号(+)操作符,我们也用它来将数字加在一起,但是在这种情况下,它做了一些不同的事情。让我们在控制台中尝试一个例子。 +
- 连接是一个很花哨的编程词,意思是“连接在一起”。在 JavaScript 中连接字符串使用加号 (+) 操作符,我们也用它来将数字加在一起,但是在这种情况下,它做了一些不同的事情。让我们在控制台中尝试一个例子。
let one = 'Hello, '; let two = 'how are you?'; let joined = one + two; @@ -231,7 +231,7 @@连接字符串
上下文中的串联
-让我们看一下在操作中使用的连接——这是本课程早些时候的一个例子:
+让我们看一下在操作中使用的连接——这是本课程早些时候的一个例子:
<button>Press me</button>@@ -244,42 +244,42 @@上下文中的串联
{{ EmbedLiveSample('上下文中的串联', '100%', 50, "", "", "hide-codepen-jsfiddle") }}
-这里我们使用的是第4行中的 {{domxref("window.prompt()", "window.prompt()")}} 函数, 它要求用户通过一个弹出对话框回答一个问题然后将他们输入的文本存储在一个给定的变量中 — 在这个例子中是就是
+name
变量。然后,我们在第5行中使用 {{domxref("window.alert()","window.alert()")}} 函数来显示另一个弹出窗口,其中包含一个字符串,我们用两个字符串常量和name变量通过连接进行组合。这里我们使用的是第 4 行中的 {{domxref("window.prompt()", "window.prompt()")}} 函数,它要求用户通过一个弹出对话框回答一个问题然后将他们输入的文本存储在一个给定的变量中 — 在这个例子中是就是
name
变量。然后,我们在第 5 行中使用 {{domxref("window.alert()","window.alert()")}} 函数来显示另一个弹出窗口,其中包含一个字符串,我们用两个字符串常量和 name 变量通过连接进行组合。数字与字符
-
- 当我们尝试添加(或连接)一个字符串和一个数字时,会发生什么?
- 让我们在我们的控制台中尝试一下: +- 当我们尝试添加 (或连接) 一个字符串和一个数字时,会发生什么?
-
+ 让我们在我们的控制台中尝试一下:'Front ' + 242;您可能会认为这会抛出一个错误,但它运行得很好。
试图将字符串表示为一个数字并不是很讲的通,但是用数字表示一个字符串则不然,因此浏览器很聪明地将数字转换为字符串,并将这两个字符串连接在一起。- 你甚至可以用两个数字来这么操作——你可以通过用引号将数字包装成一个字符串。尝试以下方法(我们使用typeof操作符来检查变量是一个数字还是一个字符串): +
- 你甚至可以用两个数字来这么操作——你可以通过用引号将数字包装成一个字符串。尝试以下方法 (我们使用 typeof 操作符来检查变量是一个数字还是一个字符串):
-let myDate = '19' + '67'; typeof myDate;- 如果您有一个数值变量,您想要将其转换为字符串,并且不改变其他地方,或者您想将一个字符串转换为一个数字而不改变其其他地方,那么您可以使用以下两个构造: +
- 如果您有一个数值变量,您想要将其转换为字符串,并且不改变其他地方,或者您想将一个字符串转换为一个数字而不改变其其他地方,那么您可以使用以下两个构造:
+ 这些结构在某些情况下是非常有用的,例如,如果一个用户将一个数字输入到一个表单文本字段中,这将是一个字符串,但是如果你想要将这个数字添加到某些东西中时,你需要它是一个数字,所以你可以通过- 这些结构在某些情况下是非常有用的,例如,如果一个用户将一个数字输入到一个表单文本字段中,这将是一个字符串,但是如果你想要将这个数字添加到某些东西中时,你需要它是一个数字,所以你可以通过
- 如果可以的话, {{jsxref("Number")}} 对象将把传递给它的任何东西转换成一个数字。
- 试一试: + 试一试:let myString = '123'; let myNum = Number(myString); typeof myNum;- 另一方面,每个数字都有一个名为 toString() 的方法,它将把它转换成等价的字符串。
- 试试这个: + 试试这个:let myNum = 123; let myString = myNum.toString(); typeof myString;Number()
来处理这个问题。我们在数字猜谜游戏中第54行就是这么做的。Number()
来处理这个问题。我们在数字猜谜游戏中第 54 行就是这么做的。结论
-这就是JavaScript中所涉及的字符串的基本内容。在下一篇文章中,我们将在此基础上,研究JavaScript中字符串的一些内置方法,以及如何使用它们来操纵我们的字符串,使之成为我们想要的形式。
+这就是 JavaScript 中所涉及的字符串的基本内容。在下一篇文章中,我们将在此基础上,研究 JavaScript 中字符串的一些内置方法,以及如何使用它们来操纵我们的字符串,使之成为我们想要的形式。
{{PreviousMenuNext("Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps")}}
diff --git a/files/zh-cn/learn/javascript/first_steps/test_your_skills_colon__variables/index.md b/files/zh-cn/learn/javascript/first_steps/test_your_skills_colon__variables/index.md index 50d819ab8de33a..4f1b9c93d1e65d 100644 --- a/files/zh-cn/learn/javascript/first_steps/test_your_skills_colon__variables/index.md +++ b/files/zh-cn/learn/javascript/first_steps/test_your_skills_colon__variables/index.md @@ -65,7 +65,7 @@ tags: {{ EmbedLiveSample('变量 1', '100%', 420, '', '', 'hide-codepen-jsfiddle') }} -> **标注:** [下载 任务1 的起始版本](https://github.com/roy-tian/learning-area/blob/master/javascript/introduction-to-js-1/tasks/variables/variables1-download.html),然后使用你自选的编辑器完成任务。 +> **标注:** [下载 任务 1 的起始版本](https://github.com/roy-tian/learning-area/blob/master/javascript/introduction-to-js-1/tasks/variables/variables1-download.html),然后使用你自选的编辑器完成任务。 ## 变量 2 @@ -107,11 +107,11 @@ section.appendChild(para); {{ EmbedLiveSample('变量 2', '100%', 360, '', '', 'hide-codepen-jsfiddle') }} -> **标注:** [下载 任务2 的起始版本](https://github.com/roy-tian/learning-area/blob/master/javascript/introduction-to-js-1/tasks/variables/variables2-download.html),然后使用你自选的编辑器完成任务。 +> **标注:** [下载 任务 2 的起始版本](https://github.com/roy-tian/learning-area/blob/master/javascript/introduction-to-js-1/tasks/variables/variables2-download.html),然后使用你自选的编辑器完成任务。 ## 变量 3 -现在是最后一个任务——现有代码中存在 2 处错误,请找出并修正,使输出窗口得到正确结果,即:“我是某某,20年后我?岁。” +现在是最后一个任务——现有代码中存在 2 处错误,请找出并修正,使输出窗口得到正确结果,即:“我是某某,20 年后我?岁。” 尝试更新下方互动编辑器中的代码来实现预期效果: @@ -154,7 +154,7 @@ section.appendChild(para2); {{ EmbedLiveSample('变量 3', '100%', 420, '', '', 'hide-codepen-jsfiddle') }} -> **标注:** [下载 任务3 的起始版本](https://github.com/roy-tian/learning-area/blob/master/javascript/introduction-to-js-1/tasks/variables/variables3-download.html),然后使用你自选的编辑器完成任务。 +> **标注:** [下载 任务 3 的起始版本](https://github.com/roy-tian/learning-area/blob/master/javascript/introduction-to-js-1/tasks/variables/variables3-download.html),然后使用你自选的编辑器完成任务。 ## 了解更多 @@ -163,8 +163,8 @@ section.appendChild(para2); 如果你期望对练习结果进行评估,或者遇到困难需要帮助,可以: 1. 可借助 [CodePen](https://codepen.io/)、[jsFiddle](https://jsfiddle.net/)、[Glitch](https://glitch.com/) 等在线编程实用工具完成任务。在那里你可以自行编写代码,也可以使用上文中所给的初始代码。 -2. 在 [MDN论坛学习区](https://discourse.mozilla.org/c/mdn/learn/) 寻求他人的评估和帮助。你发表的文章应包括: +2. 在 [MDN 论坛学习区](https://discourse.mozilla.org/c/mdn/learn/)寻求他人的评估和帮助。你发表的文章应包括: - 一个描述性的标题,比如《请为“变量 1”水平测试进行评估》 - 讲清你已经做出的努力,以及需要我们做什么,比如你遇到了困难并需要帮助,或者期望得到评估。 - - 一个链接指向你需要得到评估或帮助的实例,步骤1中三个在线编程工具之一均可。我们对希望得到帮助但由不提供代码的求助也很无奈。 + - 一个链接指向你需要得到评估或帮助的实例,步骤 1 中三个在线编程工具之一均可。我们对希望得到帮助但由不提供代码的求助也很无奈。 - 一个链接指向 MDN 测试的原始页面,在那里我们可以找到你需要获得帮助的原始信息。 diff --git a/files/zh-cn/learn/javascript/first_steps/useful_string_methods/index.html b/files/zh-cn/learn/javascript/first_steps/useful_string_methods/index.html index 0772bac10792e9..23158afc96ba52 100644 --- a/files/zh-cn/learn/javascript/first_steps/useful_string_methods/index.html +++ b/files/zh-cn/learn/javascript/first_steps/useful_string_methods/index.html @@ -16,16 +16,16 @@{{PreviousMenuNext("Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}-现在我们学习基本的字符串语法, 让我们开始思考一下我们可以对内置方法的字符串做什么有用的操作,例如查找文本字符串的长度,加入和分割字符串, 将字符串中的一个字符替换为另一个字符。
+现在我们学习基本的字符串语法, 让我们开始思考一下我们可以对内置方法的字符串做什么有用的操作,例如查找文本字符串的长度,加入和分割字符串,将字符串中的一个字符替换为另一个字符。
前提: -基本的电脑知识, 对HTML和CSS有一定的了解,最好是懂一点javascript知识。 +基本的电脑知识,对 HTML 和 CSS 有一定的了解,最好是懂一点 javascript 知识。 - @@ -33,11 +33,11 @@目的: +目的: 明白字符串这个对象,学会使用字符串的基本方法去处理字符串 把字符串当作对象
-我们曾经说过,现在我们重申一遍—在javascript中,一切东西都可以被当作对象。例如我们创建一个字符串。
+我们曾经说过,现在我们重申一遍—在 javascript 中,一切东西都可以被当作对象。例如我们创建一个字符串。
let string = 'This is my string';-一旦你的变量成为字符串对象实例, 你就可以有大量的原型和方法编辑它. 如果你进入{{jsxref("String")}}对象页并观察页面旁边的列表你就会明白这一点。
+一旦你的变量成为字符串对象实例,你就可以有大量的原型和方法编辑它。如果你进入{{jsxref("String")}}对象页并观察页面旁边的列表你就会明白这一点。
可能现在你的大脑开始迷糊了,不要担心! 在你的学习进程中你真的不需要过早地理解大部分这方面知识,但是接下来我们这儿要看的是你要经常使用的一些知识。
@@ -153,59 +153,59 @@Hidden code
获得字符串的长度
-这很简单 — 你可以很轻松的使用 {{jsxref("String.prototype.length", "length")}} 属性. 尝试输入以下的两行代码:
+这很简单 — 你可以很轻松的使用 {{jsxref("String.prototype.length", "length")}} 属性。尝试输入以下的两行代码:
let browserType = 'mozilla'; browserType.length;-这个结果应该返回一个数字:7,因为"mozilla"的长度为7个字符. 说字符串的长度有用是有很多原因的, 例如,你可能想算出一连串名字的长度,并用名字长度来作为名字排序的依据,亦或让一个用户知道他输入的用户名太长,已经超出了输入的字符串长度限制。
+这个结果应该返回一个数字:7,因为"mozilla"的长度为 7 个字符。说字符串的长度有用是有很多原因的,例如,你可能想算出一连串名字的长度,并用名字长度来作为名字排序的依据,亦或让一个用户知道他输入的用户名太长,已经超出了输入的字符串长度限制。
检索特定字符串字符
-在相关的注释中,您可以使用方括号表示法返回字符串中的任何字符 - 这意味着您可以在变量名的末尾包含方括号([ ])。 在方括号内,您可以包含要返回的字符的编号,例如,您要检索第一个字母,可以这样做:
+在相关的注释中,您可以使用方括号表示法返回字符串中的任何字符 - 这意味着您可以在变量名的末尾包含方括号([ ])。在方括号内,您可以包含要返回的字符的编号,例如,您要检索第一个字母,可以这样做:
browserType[0];-电脑从0开始,不是1! 要检索任何字符串的最后一个字符,我们可以使用下面这行,将这种技术与我们上面看到的length属性相结合起来:
+电脑从 0 开始,不是 1!要检索任何字符串的最后一个字符,我们可以使用下面这行,将这种技术与我们上面看到的 length 属性相结合起来:
browserType[browserType.length-1];-“mozilla”的长度为7,但由于计数从0开始,所以字符位置为6,因此需要长度为length-1。 例如,您可以使用它来查找一系列字符串的第一个字母,并按字母顺序排列。
+“mozilla”的长度为 7,但由于计数从 0 开始,所以字符位置为 6,因此需要长度为length-1。例如,您可以使用它来查找一系列字符串的第一个字母,并按字母顺序排列。
在字符串中查找子字符串并提取它
-
- 有时候你会想要找出一个较小的字符串是否存在于一个较大的字符串中(我们通常会说一个字符串中存在一个子字符串)。 这可以使用{{jsxref("String.prototype.indexOf()","indexOf()")}}方法来完成,该方法需要一个{{glossary("parameter")}} — 你想要搜索的子字符串。 尝试以下: +
- 有时候你会想要找出一个较小的字符串是否存在于一个较大的字符串中(我们通常会说一个字符串中存在一个子字符串)。这可以使用{{jsxref("String.prototype.indexOf()","indexOf()")}}方法来完成,该方法需要一个{{glossary("parameter")}} — 你想要搜索的子字符串。尝试以下:
+ 结果是 2,因为子字符串“zilla”从“mozilla”内的位置 2(0,1,2 —— 所以从第 3 个字符)开始。这样的代码可以用来过滤字符串。例如,假设我们有一个 Web 地址列表,但我们只想打印出包含“mozilla”的那些地址。browserType.indexOf('zilla');- 结果是2,因为子字符串“zilla”从“mozilla”内的位置2(0,1,2 —— 所以从第3个字符)开始。 这样的代码可以用来过滤字符串。 例如,假设我们有一个Web地址列表,但我们只想打印出包含“mozilla”的那些地址。-
- 这可以用另一种可能更有效的方式来实现。 尝试以下: +
- 这可以用另一种可能更有效的方式来实现。尝试以下:
-browserType.indexOf('vanilla');这应该会得到-1
的结果 —— 当在主字符串中找不到子字符串(在本例中为“vanilla”)时将返回-1
。
- 您可以使用它来查找不包含子串“mozilla”的所有字符串实例,或者如果使用否定运算符,请执行以下操作。 你可以这样做: + 您可以使用它来查找不包含子串“mozilla”的所有字符串实例,或者如果使用否定运算符,请执行以下操作。你可以这样做:if(browserType.indexOf('mozilla') !== -1) { // do stuff with the string }- 当你知道字符串中的子字符串开始的位置,以及想要结束的字符时,{{jsxref("String.prototype.slice()", "slice()")}}可以用来提取 它。 尝试以下: +
- 当你知道字符串中的子字符串开始的位置,以及想要结束的字符时,{{jsxref("String.prototype.slice()", "slice()")}}可以用来提取 它。尝试以下:
-browserType.slice(0,3);这时返回"moz"——第一个参数是开始提取的字符位置,第二个参数是提取的最后一个字符的后一个位置。所以提取从第一个位置开始,直到但不包括最后一个位置。(此例中)你也可以说第二个参数等于被返回的字符串的长度。
- 此外,如果您知道要在某个字符之后提取字符串中的所有剩余字符,则不必包含第二个参数,而只需要包含要从中提取的字符位置 字符串中的其余字符。 尝试以下: +
- 此外,如果您知道要在某个字符之后提取字符串中的所有剩余字符,则不必包含第二个参数,而只需要包含要从中提取的字符位置 字符串中的其余字符。尝试以下:
+ 这返回“zilla” —— 这是因为 2 的字符位置是字母 z,并且因为没有包含第二个参数,所以返回的子字符串是字符串中的所有剩余字符。browserType.slice(2);- 这返回“zilla” —— 这是因为2的字符位置是字母z,并且因为没有包含第二个参数,所以返回的子字符串是字符串中的所有剩余字符。-Note:
+slice()
的第二个参数是可选的 :如果没有传入这个参数,分片结束位置会在原始字符串的末尾。这个方法也有其他的选项;学习{{jsxref("String.prototype.slice()", "slice()")}}这页,来看看你还能发现什么其他作用。Note:
slice()
的第二个参数是可选的:如果没有传入这个参数,分片结束位置会在原始字符串的末尾。这个方法也有其他的选项;学习{{jsxref("String.prototype.slice()", "slice()")}}这页,来看看你还能发现什么其他作用。转换大小写
-字符串方法{{jsxref("String.prototype.toLowerCase()","toLowerCase()")}}和{{jsxref("String.prototype.toUpperCase()","toUpperCase()")}}字符串并将所有字符分别转换为小写或大写。 例如,如果要在将数据存储在数据库中之前对所有用户输入的数据进行规范化,这可能非常有用。
+字符串方法{{jsxref("String.prototype.toLowerCase()","toLowerCase()")}}和{{jsxref("String.prototype.toUpperCase()","toUpperCase()")}}字符串并将所有字符分别转换为小写或大写。例如,如果要在将数据存储在数据库中之前对所有用户输入的数据进行规范化,这可能非常有用。
让我们尝试输入以下几行来看看会发生什么:
@@ -215,9 +215,9 @@转换大小写
替换字符串的某部分
-您可以使用{{jsxref("String.prototype.replace()","replace()")}}方法将字符串中的一个子字符串替换为另一个子字符串。在基础的层面上, 这个工作非常简单。你当然可以用它做一些更高级的事情,但目前我们不会涉及到。
+您可以使用{{jsxref("String.prototype.replace()","replace()")}}方法将字符串中的一个子字符串替换为另一个子字符串。在基础的层面上,这个工作非常简单。你当然可以用它做一些更高级的事情,但目前我们不会涉及到。
-它需要两个参数 - 要被替换下的字符串和要被替换上的字符串。 尝试这个例子:
+它需要两个参数 - 要被替换下的字符串和要被替换上的字符串。尝试这个例子:
browserType.replace('moz','van');@@ -225,17 +225,17 @@替换字符串的某部分
主动学习的示例
-在本节中,我们会让您尽力编写一些字符串操作代码。 在下面的每个练习中,我们有一个字符串数组,一个循环,用于处理数组中的每个值,并将其显示在项目符号列表中。 您现在不需要了解数组或循环 - 这些将在以后的文章中解释。 所有你需要做的每一种情况都是写出将以我们想要的格式输出字符串的代码。
+在本节中,我们会让您尽力编写一些字符串操作代码。在下面的每个练习中,我们有一个字符串数组,一个循环,用于处理数组中的每个值,并将其显示在项目符号列表中。您现在不需要了解数组或循环 - 这些将在以后的文章中解释。所有你需要做的每一种情况都是写出将以我们想要的格式输出字符串的代码。
每个示例都附带一个“重置”按钮,您可以使用该按钮重置代码,如果您犯了错误,并且无法再次工作,并且显示解决方案按钮,您可以按下来看到一个潜在的答案,如果你真的卡住了。
过滤问候留言
-在第一个练习中,我们将简单介绍一下 - 我们有一系列的问候卡片消息,但我们希望对它们进行排序,以列出圣诞消息。 我们希望您在
+if(...)
结构中填写条件测试,以测试每个字符串,并将其打印在列表中,如果它是圣诞消息。在第一个练习中,我们将简单介绍一下 - 我们有一系列的问候卡片消息,但我们希望对它们进行排序,以列出圣诞消息。我们希望您在
if(...)
结构中填写条件测试,以测试每个字符串,并将其打印在列表中,如果它是圣诞消息。-
@@ -308,12 +308,12 @@- 首先考虑一下如何测试每种情况下的消息是否为圣诞消息。 所有这些消息中都有什么字符串,您可以使用什么方法来测试是否存在?
-- 然后,您需要编写 操作数1 操作符 操作数2 形式的条件测试。 左边的东西等于右边的东西吗? 或者在这种情况下,方法调用在左边返回的结果在右边?
+- 首先考虑一下如何测试每种情况下的消息是否为圣诞消息。所有这些消息中都有什么字符串,您可以使用什么方法来测试是否存在?
+- 然后,您需要编写 操作数 1 操作符 操作数 2 形式的条件测试。左边的东西等于右边的东西吗?或者在这种情况下,方法调用在左边返回的结果在右边?
- 提示:在这种情况下,测试方法调用是否不等于某个结果可能更有用。
Playable code
大写修正
-在这个练习中,我们有英国城市的名字,但是这个大写字母都搞砸了。 我们希望你改变它们,使它们都是小写字母,除了首字母。 一个很好的方法是:
+在这个练习中,我们有英国城市的名字,但是这个大写字母都搞砸了。我们希望你改变它们,使它们都是小写字母,除了首字母。一个很好的方法是:
@@ -383,7 +383,7 @@
- 将输入变量中包含的整个字符串转换为小写,并将其存储在新变量中。
- 在此新变量中获取字符串的第一个字母并将其存储在另一个变量中。
-- 将此最新变量用作子字符串,将小写字符串的第一个字母从小写更改为大写。 将此替换过程的结果存储在另一个新变量中。
+- 将此最新变量用作子字符串,将小写字符串的第一个字母从小写更改为大写。将此替换过程的结果存储在另一个新变量中。
- 让
result
变量的值与最终结果相等,而不是使用input
变量。Playable code 2
从原先部分得到新字符串
-在最后一个练习中,阵列包含一堆字符串,其中包含有关英格兰北部火车站的信息。 字符串是包含三字母站代码的数据项,后面是一些机器可读数据,后跟分号,后跟可读站名。 例如:
+在最后一个练习中,阵列包含一堆字符串,其中包含有关英格兰北部火车站的信息。字符串是包含三字母站代码的数据项,后面是一些机器可读数据,后跟分号,后跟可读站名。例如:
MAN675847583748sjt567654;Manchester Piccadilly@@ -469,6 +469,6 @@Playable code 3
结论
-你不能逃避的事实是在编程中处理单词和句子是非常重要的——特别是在JavaScript中,因为网站都是关于与人沟通的。 本文已经给出了您现在需要了解的关于操作字符串的基础知识。这将在未来进入更复杂的主题时为您服务。 接下来,我们将在短期内研究我们需要关注的最后一个主要的数据类型——数组。
+你不能逃避的事实是在编程中处理单词和句子是非常重要的——特别是在 JavaScript 中,因为网站都是关于与人沟通的。本文已经给出了您现在需要了解的关于操作字符串的基础知识。这将在未来进入更复杂的主题时为您服务。接下来,我们将在短期内研究我们需要关注的最后一个主要的数据类型——数组。
{{PreviousMenuNext("Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}
diff --git a/files/zh-cn/learn/javascript/first_steps/variables/index.html b/files/zh-cn/learn/javascript/first_steps/variables/index.html index 640faf01803023..f6667068fa1bec 100644 --- a/files/zh-cn/learn/javascript/first_steps/variables/index.html +++ b/files/zh-cn/learn/javascript/first_steps/variables/index.html @@ -13,30 +13,30 @@{{PreviousMenuNext("Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps")}}-在读完之前的一些文章之后,你现在应该大概知道了JavaScript是什么,你能用它干什么,它是怎么跟其他web技术(HTML,CSS)协同工作的,以及它有哪些主要特性。在本章节,我们将开始学习JavaScript的基础,了解如何使用 -- 变量。
+在读完之前的一些文章之后,你现在应该大概知道了 JavaScript 是什么,你能用它干什么,它是怎么跟其他 web 技术(HTML,CSS)协同工作的,以及它有哪些主要特性。在本章节,我们将开始学习 JavaScript 的基础,了解如何使用 -- 变量。
- 预备知识: -电脑基础知识,了解基本的 HTML 和 CSS,了解JavaScript是什么。 +预备知识: +电脑基础知识,了解基本的 HTML 和 CSS,了解 JavaScript 是什么。 - 目标: -熟悉JavaScript的变量使用 +目标: +熟悉 JavaScript 的变量使用 需要的工具
-在本章中,你将要输入一些代码来测试你对相关内容的理解。如果你是用的桌面浏览器,输入这些代码最好的地方是浏览器的JavaScript终端,(参考 什么是浏览器开发工具 查看如何使用这些工具)。
+在本章中,你将要输入一些代码来测试你对相关内容的理解。如果你是用的桌面浏览器,输入这些代码最好的地方是浏览器的 JavaScript 终端,(参考 什么是浏览器开发工具 查看如何使用这些工具)。
-当然,我们也提供了一个简单的JavaScript终端,嵌入在下文的页面中,以便你更容易的输入和测试这些代码。
+当然,我们也提供了一个简单的 JavaScript 终端,嵌入在下文的页面中,以便你更容易的输入和测试这些代码。
-变量是什么?
+变量是什么?
-一个变量,就是一个用于存放数值的容器。这个数值可能是一个用于累加计算的数字,或者是一个句子中的字符串。变量的独特之处在于它存放的数值是可以改变的。让我们看一个简单的例子:
+一个变量,就是一个用于存放数值的容器。这个数值可能是一个用于累加计算的数字,或者是一个句子中的字符串。变量的独特之处在于它存放的数值是可以改变的。让我们看一个简单的例子:
<button>Press me</button>@@ -84,7 +84,7 @@声明变量
let myName; let myAge;-在这里我们声明了两个变量
+myName
和myAge
. 那么现在尝试输入这些代码到你的浏览器终端或者下面提供的JavaScript终端 (你也可以在另一个独立的标签页或窗口 open this consol ). 此外,你也可以多声明几个变量.在这里我们声明了两个变量
myName
和myAge
. 那么现在尝试输入这些代码到你的浏览器终端或者下面提供的 JavaScript 终端 (你也可以在另一个独立的标签页或窗口 open this consol ). 此外,你也可以多声明几个变量。Hidden code
@@ -195,7 +195,7 @@Hidden code
{{ EmbedLiveSample('Hidden_code', '100%', 300, "", "", "hide-codepen-jsfiddle") }}
-提示: 在JavaScript中,所有代码指令都会以分号结尾 (
+;
) — 如果忘记加分号,你的单行代码可能执行正常,但是在多行代码在一起的时候就可能出错。所以,最好是养成主动以分号作为代码结尾的习惯。提示: 在 JavaScript 中,所有代码指令都会以分号结尾 (
;
) — 如果忘记加分号,你的单行代码可能执行正常,但是在多行代码在一起的时候就可能出错。所以,最好是养成主动以分号作为代码结尾的习惯。你可以通过使用变量的方式来验证这个变量的数值是否在执行环境中已经存在。例如,
@@ -203,7 +203,7 @@Hidden code
myName; myAge;-以上这两个变量并没有数值,他们是空的容器。当你输入变量名并回车后,你会得到一个
+undefined
的返回值。如果他们并不存在的话,那你就会得到一个报错信息。不信的话,可以尝试输入:以上这两个变量并没有数值,他们是空的容器。当你输入变量名并回车后,你会得到一个
undefined
的返回值。如果他们并不存在的话,那你就会得到一个报错信息。不信的话,可以尝试输入:scoobyDoo;@@ -213,35 +213,35 @@Hidden code
初始化变量
-一旦你定义了一个变量,你就能够初始化它. 方法如下,在变量名之后跟上一个“=”,然后是数值:
+一旦你定义了一个变量,你就能够初始化它。方法如下,在变量名之后跟上一个“=”,然后是数值:
myName = 'Chris'; myAge = 37;-现在回到控制台并且尝试输入这几行。每输入一条你都应该确认一下控制台输出的变量是不是你刚赋的值。 同样,你可以通过在控制台中输入变量的名称来返回该变量的值 — 再次尝试下这些:
+现在回到控制台并且尝试输入这几行。每输入一条你都应该确认一下控制台输出的变量是不是你刚赋的值。 同样,你可以通过在控制台中输入变量的名称来返回该变量的值 — 再次尝试下这些:
myName; myAge;-你可以像这样在声明变量的时候给变量初始化:
+你可以像这样在声明变量的时候给变量初始化:
let myName = 'Chris';这可能是大多数时间你都会使用的方式, 因为它要比在单独的两行上做两次操作要快。
-Note: 如果你写一个声明和初始化变量的多行JavaScript代码的程序,你可以在初始化变量之后再实际声明它,并且它仍然可以工作。这是因为变量的声明通常在其余的代码执行之前完成。这叫做顶置—阅读var hoisting来了解更多细节。
+Note: 如果你写一个声明和初始化变量的多行 JavaScript 代码的程序,你可以在初始化变量之后再实际声明它,并且它仍然可以工作。这是因为变量的声明通常在其余的代码执行之前完成。这叫做顶置—阅读var hoisting来了解更多细节。
var 与 let 的区别
-此时,您可能会想:“为什么我们需要两个关键字来定义变量?”,“为什么有
+var
和let
呢?"。此时,您可能会想:“为什么我们需要两个关键字来定义变量?”,“为什么有
-var
和let
呢?"。原因是有些历史性的。 回到最初创建 JavaScript 时,是只有
+var
的。 在大多数情况下,这种方法可以接受, 但有时在工作方式上会有一些问题——它的设计会令人困惑或令人讨厌 。 因此,let
是在现代版本中的 JavaScript 创建的一个新的关键字,用于创建与var
工作方式有些不同的变量,解决了过程中的问题。原因是有些历史性的。回到最初创建 JavaScript 时,是只有
-var
的。在大多数情况下,这种方法可以接受,但有时在工作方式上会有一些问题——它的设计会令人困惑或令人讨厌。因此,let
是在现代版本中的 JavaScript 创建的一个新的关键字,用于创建与var
工作方式有些不同的变量,解决了过程中的问题。下面解释几个简单的差异。 我们现在不会讨论所有的差异,但是当您了解有关 JavaScript 的更多信息时,您将开始发现它们(如果您现在真的想要阅读它们,请随时查看我们的参考页面)。
+下面解释几个简单的差异。我们现在不会讨论所有的差异,但是当您了解有关 JavaScript 的更多信息时,您将开始发现它们(如果您现在真的想要阅读它们,请随时查看我们的参考页面)。
-首先,如果你编写一个声明并初始化变量的多行 JavaScript 程序,你可以在初始化一个变量之后用
+var
声明它,它仍然可以工作。 例如:首先,如果你编写一个声明并初始化变量的多行 JavaScript 程序,你可以在初始化一个变量之后用
var
声明它,它仍然可以工作。例如:myName = 'Chris'; @@ -259,9 +259,9 @@
var 与 let 的区别
这是由于变量的提升,更多细节请阅读变量提升。
-但提升操作不再适用于
+let
。如果将上面例子中的var
替换成let
将不起作用并引起一个错误。 这是一件好事——因为初始化后再声明一个变量会使代码变得混乱和难以理解。但提升操作不再适用于
-let
。如果将上面例子中的var
替换成let
将不起作用并引起一个错误。这是一件好事——因为初始化后再声明一个变量会使代码变得混乱和难以理解。其次,当你使用
+var
时,可以根据需要多次声明相同名称的变量,但是let
不能。 以下将有效:其次,当你使用
var
时,可以根据需要多次声明相同名称的变量,但是let
不能。以下将有效:@@ -281,35 +281,35 @@var myName = 'Chris'; var myName = 'Bob';
var 与 let 的区别
出于这些以及其他原因,我们建议您在代码中尽可能多地使用
let
,而不是var
。因为没有理由使用var
,除非您需要用代码支持旧版本的 Internet Explorer (它直到第 11 版才支持let
,现代的 Windows Edge 浏览器支持的很好)。-Note: 我们目前正在更新课程以使用let而不是var。 忍耐一下!
+Note: 我们目前正在更新课程以使用 let 而不是 var。忍耐一下!
更新变量
-一旦变量赋值,您可以通过简单地给它一个不同的值来更新它。试试在你的控制台中输入下面几行:
+一旦变量赋值,您可以通过简单地给它一个不同的值来更新它。试试在你的控制台中输入下面几行:
myName = 'Bob'; myAge = 40;关于变量命名的规则
-你可以给你的变量赋任何你喜欢的名字,但有一些限制。 一般你应当坚持使用拉丁字符(0-9,a-z,A-Z)和下划线字符。
+你可以给你的变量赋任何你喜欢的名字,但有一些限制。一般你应当坚持使用拉丁字符 (0-9,a-z,A-Z) 和下划线字符。
- 你不应当使用规则之外的其他字符,因为它们可能引发错误,或对国际用户来说难以理解。
-- 变量名不要以下划线开头—— 以下划线开头的被某些JavaScript设计为特殊的含义,因此可能让人迷惑。
+- 变量名不要以下划线开头—— 以下划线开头的被某些 JavaScript 设计为特殊的含义,因此可能让人迷惑。
- 变量名不要以数字开头。这种行为是不被允许的,并且将引发一个错误。
- 一个可靠的命名约定叫做 "小写驼峰命名法",用来将多个单词组在一起,小写整个命名的第一个字母然后大写剩下单词的首字符。我们已经在文章中使用了这种命名方法。
- 让变量名直观,它们描述了所包含的数据。不要只使用单一的字母/数字,或者长句。
-- 变量名大小写敏感——因此
-myage
与myAge
是2个不同的变量。- 最后也是最重要的一点—— 你应当避免使用JavaScript的保留字给变量命名。保留字,即是组成JavaScript的实际语法的单词!因此诸如
+var
,function
,let和
for
等,都不能被作为变量名使用。浏览器将把它们识别为不同的代码项,因此你将得到错误。- 变量名大小写敏感——因此
+myage
与myAge
是 2 个不同的变量。- 最后也是最重要的一点—— 你应当避免使用 JavaScript 的保留字给变量命名。保留字,即是组成 JavaScript 的实际语法的单词!因此诸如
var
,function
,let和
for
等,都不能被作为变量名使用。浏览器将把它们识别为不同的代码项,因此你将得到错误。-Note: 你能从词汇语法—关键字找到一个相当完整的保留关键字列表来避免使用关键字当作变量。
好的命名示例:
+好的命名示例:
age myAge @@ -319,7 +319,7 @@-关于变量命名的规则
audio1 audio2错误与差的命名示例:
+错误与差的命名示例:
1 a @@ -337,23 +337,23 @@-变量类型
可以为变量设置不同的数据类型。本节我们将对其进行简短的介绍,在以后的文章中,你会更详细地了解它们。
-到目前为止我们已经认识了前2个,但是还有其他的。
+到目前为止我们已经认识了前 2 个,但是还有其他的。
Number
-你可以在变量中存储数字,不论这些数字是像30(也叫整数)这样,或者像2.456这样的小数(也叫做浮点数)。与其他编程语言不同,在 JavaScript 中你不需要声明一个变量的类型。当你给一个变量数字赋值时,不需要用引号括起来。
+你可以在变量中存储数字,不论这些数字是像 30(也叫整数)这样,或者像 2.456 这样的小数(也叫做浮点数)。与其他编程语言不同,在 JavaScript 中你不需要声明一个变量的类型。当你给一个变量数字赋值时,不需要用引号括起来。
let myAge = 17;String
-字符串是文本的一部分。当你给一个变量赋值为字符串时,你需要用单引号或者双引号把值给包起来,否则JavaScript将会把这个字符串值理解成别的变量名。
+字符串是文本的一部分。当你给一个变量赋值为字符串时,你需要用单引号或者双引号把值给包起来,否则 JavaScript 将会把这个字符串值理解成别的变量名。
let dolphinGoodbye = 'So long and thanks for all the fish';Boolean
-Boolean 的值有2种:true或false。它们通常被用于在适当的代码之后,测试条件是否成立。举个例子,一个简单的示例如下:
+Boolean 的值有 2 种:true 或 false。它们通常被用于在适当的代码之后,测试条件是否成立。举个例子,一个简单的示例如下:
let iAmAlive = true;@@ -361,21 +361,21 @@Boolean
let test = 6 < 3;-这是使用“小于”操作符(<)来测试6小于3。正如你所料的,将会返回
+false
,因为6并不小于3!在这个课程中,以后你将会学到许多有关操作符的知识。这是使用“小于”操作符(<)来测试 6 小于 3。正如你所料的,将会返回
false
,因为 6 并不小于 3!在这个课程中,以后你将会学到许多有关操作符的知识。Array
-数组是一个单个对象,其中包含很多值,方括号括起来,并用逗号分隔。尝试在您的控制台输入以下行:
+数组是一个单个对象,其中包含很多值,方括号括起来,并用逗号分隔。尝试在您的控制台输入以下行:
let myNameArray = ['Chris', 'Bob', 'Jim']; let myNumberArray = [10,15,40];-当数组被定义后,您可以使用如下所示的语法来访问各自的值,例如下行:
+当数组被定义后,您可以使用如下所示的语法来访问各自的值,例如下行:
myNameArray[0]; // should return 'Chris' myNumberArray[2]; // should return 40-此处的方括号包含一个索引值,该值指定要返回的值的位置。 您可能已经注意到,计算机从0开始计数,而不是像我们人类那样的1。
+此处的方括号包含一个索引值,该值指定要返回的值的位置。您可能已经注意到,计算机从 0 开始计数,而不是像我们人类那样的 1。
在以后的文章,你将更多地了解数组。
@@ -383,19 +383,19 @@Object
在编程中,对象是现实生活中的模型的一种代码结构。您可以有一个简单的对象,代表一个停车场,并包含有关其宽度和长度的信息,或者您可以有一个代表一个人的对象,并包含有关他们的名字,身高,体重,他们说什么语言,如何说 你好,他们,等等。
-尝试在您的控制台输入以下行:
+尝试在您的控制台输入以下行:
let dog = { name : 'Spot', breed : 'Dalmatian' };-要检索存储在对象中的信息,可以使用以下语法:
+要检索存储在对象中的信息,可以使用以下语法:
dog.name-我们现在不会看对象了 - 您可以在将来的模块中了解更多关于这些对象的信息.
+我们现在不会看对象了 - 您可以在将来的模块中了解更多关于这些对象的信息。
动态类型
-JavaScript是一种“动态类型语言”,这意味着不同于其他一些语言(译者注:如C、JAVA),您不需要指定变量将包含什么数据类型(例如number或string)
+JavaScript 是一种“动态类型语言”,这意味着不同于其他一些语言 (译者注:如 C、JAVA),您不需要指定变量将包含什么数据类型(例如 number 或 string)
例如,如果你声明一个变量并给它一个带引号的值,浏览器就会知道它是一个字符串:
@@ -408,11 +408,11 @@动态类型
myNumber = 500; // much better — now this is a number typeof myNumber尝试依次将上述代码输入您的控制台,看看结果是什么(无须输入//之后的注释)。 我们使用了一个名为
+typeof
的特殊的操作符 ——它会返回所传递给它的变量的数据类型。 第一次在上面的代码中调用它,它应该返回string,因为此时myNumber变量包含一个字符串'500'。 看看它第二次将返回什么。尝试依次将上述代码输入您的控制台,看看结果是什么(无须输入//之后的注释)。我们使用了一个名为
typeof
的特殊的操作符 ——它会返回所传递给它的变量的数据类型。第一次在上面的代码中调用它,它应该返回 string,因为此时 myNumber 变量包含一个字符串'500'。看看它第二次将返回什么。总结
-到目前为止,您应该了解了一些JavaScript变量以及如何创建它们。 在下一篇文章中,我们将更详细地关注数字,了解如何在JavaScript中使用基础数学。
+到目前为止,您应该了解了一些 JavaScript 变量以及如何创建它们。在下一篇文章中,我们将更详细地关注数字,了解如何在 JavaScript 中使用基础数学。
{{PreviousMenuNext("Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps")}}
diff --git a/files/zh-cn/learn/javascript/first_steps/what_is_javascript/index.html b/files/zh-cn/learn/javascript/first_steps/what_is_javascript/index.html index 4ab48c4a892a41..c4c06335667d0b 100644 --- a/files/zh-cn/learn/javascript/first_steps/what_is_javascript/index.html +++ b/files/zh-cn/learn/javascript/first_steps/what_is_javascript/index.html @@ -13,16 +13,16 @@{{NextMenu("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps")}}-欢迎来到 MDN 的 JavaScript 初学者课程!本节将在一定高度俯瞰 JavaScript,回答一些诸如“它是什么?”和“它能做什么?”的问题 。并使你熟悉 JavaScript 的用途。
+欢迎来到 MDN 的 JavaScript 初学者课程!本节将在一定高度俯瞰 JavaScript,回答一些诸如“它是什么?”和“它能做什么?”的问题。并使你熟悉 JavaScript 的用途。
- 预备知识: -计算机基础知识,初步理解 HTML 和 CSS 。 +预备知识: +计算机基础知识,初步理解 HTML 和 CSS。 - @@ -36,15 +36,15 @@目标: +目标: 初步了解 JavaScript,包括一些概念、用途、嵌入网站的方法。 广义的定义
-
- {{glossary("HTML")}}是一种标记语言,用来结构化我们的网页内容并赋予内容含义,例如定义段落、标题和数据表,或在页面中嵌入图片和视频。
-- {{glossary("CSS")}} 是一种样式规则语言,可将样式应用于 HTML 内容, 例如设置背景颜色和字体,在多个列中布局内容。
+- {{glossary("CSS")}} 是一种样式规则语言,可将样式应用于 HTML 内容,例如设置背景颜色和字体,在多个列中布局内容。
- {{glossary("JavaScript")}} 是一种脚本语言,可以用来创建动态更新的内容,控制多媒体,制作图像动画,还有很多。(好吧,虽然它不是万能的,但可以通过简短的代码来实现神奇的功能。)
这三层依次建立,秩序井然。以文本标签(text label)的简单示例。首先用 HTML 将文本标记起来,从而赋予它结构和目的:
+这三层依次建立,秩序井然。以文本标签 (text label) 的简单示例。首先用 HTML 将文本标记起来,从而赋予它结构和目的:
-<p>玩家1:小明</p>+<p>玩家 1:小明</p>-玩家1:小明
+玩家 1:小明
然后我们可以为它加一点 CSS 让它更好看:
@@ -84,7 +84,7 @@Beautiful name label
} </style></head> <body> -<p>玩家1:小明</p> +<p>玩家 1:小明</p> </body></html> @@ -98,7 +98,7 @@Beautiful name label
function updateName() { let name = prompt('输入一个新的名字:'); - para.textContent = '玩家1:' + name; + para.textContent = '玩家 1:' + name; } @@ -123,13 +123,13 @@Customizable name label
} </style></head> <body> -<p>玩家1:小明</p> +<p>玩家 1:小明</p> <script> const para = document.querySelector('p'); para.addEventListener('click', updateName); function updateName() { const name = prompt('输入一个新的名字:'); - para.textContent = '玩家1:' + name; + para.textContent = '玩家 1:' + name; } </script> </body></html> @@ -147,7 +147,7 @@它到底可以做什么?
@@ -184,7 +184,7 @@
- 在变量中储存有用的值。比如上文的示例中,我们请求客户输入一个新名字,然后将其储存到
-name
变量中。- 操作一段文本(在编程中称为“字符串”(string))。上文的示例中,我们取字符串 "玩家1:",然后把它和
+name
变量连结起来,创造出完整的文本标签,比如:"玩家1:小明"。- 操作一段文本(在编程中称为“字符串”(string))。上文的示例中,我们取字符串 "玩家 1:",然后把它和
name
变量连结起来,创造出完整的文本标签,比如:"玩家 1:小明"。- 运行代码以响应网页中发生的特定事件。上文的示例中,我们用一个 {{Event("click")}} 事件来检测按钮什么时候被点击,然后运行代码更新文本标签。
- 以及更多!
它到底可以做什么?
注:这些 API 较为高级,我们的课程中不会涉及,更多信息请参考:客户端 web API 模块.
-先稳住!你看到的只是冰山一角。你不可能学一天 JavaScript 就能构建下一个Facebook, 谷歌地图, 或者 Instagram。敬请「牢记初心,砥砺前行」。
+先稳住!你看到的只是冰山一角。你不可能学一天 JavaScript 就能构建下一个 Facebook, 谷歌地图,或者 Instagram。敬请「牢记初心,砥砺前行」。
JavaScript 在页面上做了什么?
@@ -196,7 +196,7 @@JavaScript 在页面
在 HTML 和 CSS 集合组装成一个网页后,浏览器的 JavaScript 引擎将执行 JavaScript 代码。这保证了当 JavaScript 开始运行之前,网页的结构和样式已经就位。
-这样很好,因为JavaScript 最普遍的用处是通过 DOM API(见上文)动态修改 HTML 和 CSS 来更新用户界面 (user interface)。如果 JavaScript 在 HTML 和 CSS 就位之前加载运行,就会引发错误。
+这样很好,因为 JavaScript 最普遍的用处是通过 DOM API(见上文)动态修改 HTML 和 CSS 来更新用户界面(user interface)。如果 JavaScript 在 HTML 和 CSS 就位之前加载运行,就会引发错误。
浏览器安全
@@ -216,7 +216,7 @@JavaScript 运行次序
function updateName() { let name = prompt('输入一个新的名字:'); - para.textContent = '玩家1:' + name; + para.textContent = '玩家 1:' + name; }这里我们选定一个文本段落(第 1 行),然后给它附上一个事件监听器(第 3 行),使得在它被点击时,
@@ -229,17 +229,17 @@updateName()
代码块(code block) (5 – 8 行)便会运行。updateName()
(这类可以重复使用的代码块称为“函数”)向用户请求一个新名字,然后把这个名字插入到段落中以更新显示。JavaScript 运行次序
解释代码 vs 编译代码
-作为程序员,你或许听说过这两个术语:解释(interpret)和 编译(compile)。在解释型语言中,代码自上而下运行,且实时返回运行结果。代码在由浏览器执行前,不需要将其转化为其他形式。代码将直接以文本格式(text form)被接收和处理。
+作为程序员,你或许听说过这两个术语:解释(interpret)和 编译 (compile)。在解释型语言中,代码自上而下运行,且实时返回运行结果。代码在由浏览器执行前,不需要将其转化为其他形式。代码将直接以文本格式(text form)被接收和处理。
相对的,编译型语言需要先将代码转化(编译)成另一种形式才能运行。比如 C/C++ 先被编译成汇编语言,然后才能由计算机运行。程序将以二进制的格式运行,这些二进制内容是由程序源代码产生的。
-JavaScript 是轻量级解释型语言。浏览器接受到JavaScript代码,并以代码自身的文本格式运行它。技术上,几乎所有 JavaScript 转换器都运用了一种叫做即时编译(just-in-time compiling)的技术;当 JavaScript 源代码被执行时,它会被编译成二进制的格式,使代码运行速度更快。尽管如此,JavaScript 仍然是一门解释型语言,因为编译过程发生在代码运行中,而非之前。
+JavaScript 是轻量级解释型语言。浏览器接受到 JavaScript 代码,并以代码自身的文本格式运行它。技术上,几乎所有 JavaScript 转换器都运用了一种叫做即时编译(just-in-time compiling)的技术;当 JavaScript 源代码被执行时,它会被编译成二进制的格式,使代码运行速度更快。尽管如此,JavaScript 仍然是一门解释型语言,因为编译过程发生在代码运行中,而非之前。
两种类型的语言各有优势,这个问题我们暂且不谈。
服务器端代码 vs 客户端代码
-你或许还听说过服务器端(server-side)和 客户端(client-side)代码这两个术语,尤其是在web开发时。客户端代码是在用户的电脑上运行的代码,在浏览一个网页时,它的客户端代码就会被下载,然后由浏览器来运行并展示。这就是客户端 JavaScript。
+你或许还听说过服务器端(server-side)和 客户端(client-side)代码这两个术语,尤其是在 web 开发时。客户端代码是在用户的电脑上运行的代码,在浏览一个网页时,它的客户端代码就会被下载,然后由浏览器来运行并展示。这就是客户端 JavaScript。
而服务器端代码在服务器上运行,接着运行结果才由浏览器下载并展示出来。流行的服务器端 web 语言包括:PHP、Python、Ruby、ASP.NET 以及...... JavaScript!JavaScript 也可用作服务器端语言,比如现在流行的 Node.js 环境,你可以在我们的 动态网页 - 服务器端编程 主题中找到更多关于服务器端 JavaScript 的知识。
@@ -284,7 +284,7 @@内部 JavaScript
-注: 如果示例不能正常工作,请依次检查所有步骤,并保证没有纰漏。原始文件是否以
+.html
为扩展名保存到本地了?</body>
标签前是否添加了 {{htmlelement("script")}} 元素?JavaScript 代码输入是否正确 ? JavaScript 是区分大小写的,而且非常精确,所以你需要准确无误地输入所示的句法,否则可能会出错。注: 如果示例不能正常工作,请依次检查所有步骤,并保证没有纰漏。原始文件是否以
.html
为扩展名保存到本地了?</body>
标签前是否添加了 {{htmlelement("script")}} 元素?JavaScript 代码输入是否正确? JavaScript 是区分大小写的,而且非常精确,所以你需要准确无误地输入所示的句法,否则可能会出错。diff --git a/files/zh-cn/learn/javascript/first_steps/what_went_wrong/index.html b/files/zh-cn/learn/javascript/first_steps/what_went_wrong/index.html index 72629c9a574762..96093ee9b89077 100644 --- a/files/zh-cn/learn/javascript/first_steps/what_went_wrong/index.html +++ b/files/zh-cn/learn/javascript/first_steps/what_went_wrong/index.html @@ -15,13 +15,13 @@{{PreviousMenuNext("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps")}}-上一节中你创建了“猜数字”游戏,但它可能没有正常工作。别担心,本节将为你提供一些简单的提示,来帮助你查找并修复JavaScript程序中的错误,从而让你远离困扰。
+上一节中你创建了“猜数字”游戏,但它可能没有正常工作。别担心,本节将为你提供一些简单的提示,来帮助你查找并修复 JavaScript 程序中的错误,从而让你远离困扰。
预备知识: -计算机基础知识,初步理解HTML和CSS,了解JavaScript。 +计算机基础知识,初步理解 HTML 和 CSS,了解 JavaScript。 目标: @@ -43,7 +43,7 @@错误类型
一个出错的示例
-让我们重回猜数字游戏,这次我们将故意引入一些错误。请到Github下载一份 number-game-errors.html (或 在线运行)。
+让我们重回猜数字游戏,这次我们将故意引入一些错误。请到 Github 下载一份 number-game-errors.html (或 在线运行)。
- 请分别在你的文本编辑器和浏览器中打开刚下载的文件。
@@ -68,10 +68,10 @@修复语法错误
-
@@ -95,10 +95,10 @@- 红色 “!” 表示这是一个错误。
+- 红色“!”表示这是一个错误。
- 一条出错信息,表示问题出在哪儿:“TypeError:guessSubmit.addeventListener is not a function”(类型错误:guessSubmit.addeventListener 不是函数)
-- 点击[详细了解]将跳转到一个 MDN 页面,其中包含了此类错误超详细的解释。
-- JavaScript 文件名,点击将跳转到开发者工具的“调试器”标签页。 如果你按照这个链接,你会看到错误突出显示的确切行。
+- 点击 [详细了解] 将跳转到一个 MDN 页面,其中包含了此类错误超详细的解释。
+- JavaScript 文件名,点击将跳转到开发者工具的“调试器”标签页。如果你按照这个链接,你会看到错误突出显示的确切行。
- 出错的行,以及导致错误的首个字符号。这里错误来自 86 行,第 3 个字符。
语法错误:第二轮
- 保存页面并刷新,可以看到出错信息不见了。
- 现在,如果尝试输入一个数字并按确定按钮,你会看到...另一个错误!
-- 此次出错信息为“TypeError:lowOrHi is null”(“类型错误:lowOrHi为null”),在第 78 行。 +
- 此次出错信息为“TypeError:lowOrHi is null”(“类型错误:lowOrHi 为 null”),在第 78 行。
注:-Null
是一个特殊值,意思是“什么也没有”,或者“没有值”。这表示lowOrHi
已声明并初始化,但没有任何有意义的值,可以说:它没有类型没有值。注:这条错误没有在页面加载时立即发生,是因为它发生在函数内部(+checkGuess() { ... }
块中)。函数内部的代码运行于一个外部代码相互独立的域内,后面函数的文章中将更详细地讲解。此时此刻,只有当代码运行至86行并调用checkGuess()
函数时,代码才会抛出出错信息。注:这条错误没有在页面加载时立即发生,是因为它发生在函数内部(checkGuess() { ... }
块中)。函数内部的代码运行于一个外部代码相互独立的域内,后面函数的文章中将更详细地讲解。此时此刻,只有当代码运行至 86 行并调用checkGuess()
函数时,代码才会抛出出错信息。- 请观察第 78 行代码:
-lowOrHi.textContent = '你猜高了!';@@ -148,10 +148,10 @@逻辑错误
randomNumber = Math.floor(Math.random()) + 1;- 为了检查问题是否来自这两行,我们要再次转到我们的朋友-控制台:在两行代码之后各插入下面的代码: +
- 为了检查问题是否来自这两行,我们要再次转到我们的朋友 - 控制台:在两行代码之后各插入下面的代码:
-console.log(randomNumber);- 保存并刷新,然后试玩,你会看到在控制台显示的随机数总是等于1。
+- 保存并刷新,然后试玩,你会看到在控制台显示的随机数总是等于 1。
修正逻辑错误
@@ -161,17 +161,17 @@修正逻辑错误
Math.random()-接下来,我们把调用
+Math.random()
的结果作为参数传递给Math.floor()
,它会舍弃小数部分返回与之最接近的整数。然后我们给这个结果加上1:接下来,我们把调用
Math.random()
的结果作为参数传递给Math.floor()
,它会舍弃小数部分返回与之最接近的整数。然后我们给这个结果加上 1:Math.floor(Math.random()) + 1-由于将一个 0 和 1 之间的随机小数的小数部分舍弃,返回的整数一定为 0,因此在此基础上加 1 之后返回值一定为 1。要在舍弃小数部分之前将它乘以100。便可得到 0 到 99 之间的随机数:
+由于将一个 0 和 1 之间的随机小数的小数部分舍弃,返回的整数一定为 0,因此在此基础上加 1 之后返回值一定为 1。要在舍弃小数部分之前将它乘以 100。便可得到 0 到 99 之间的随机数:
Math.floor(Math.random() * 100);-然后再加 1,便可得到一个 100 以内随机的自然数:
+然后再加 1,便可得到一个 100 以内随机的自然数:
Math.floor(Math.random() * 100) + 1;@@ -179,7 +179,7 @@修正逻辑错误
其它常见错误
-代码中还会遇到其他常见错误。 本节将指出其中的大部分。
+代码中还会遇到其他常见错误。本节将指出其中的大部分。
SyntaxError: missing ; before statement
@@ -223,7 +223,7 @@
(语法错误:语句缺少分号)SyntaxError: missing : after property id
+ (语法错误:属性 ID 后缺少冒号)
- (语法错误:属性ID后缺少冒号)JavaScript 对象的形式有错时通常会导致此类错误,如果把
@@ -264,7 +264,7 @@另请参阅
- 许多错误不能一一的在这里列出来,我们正在编写一个参考文档来详细说明它们的含义。请参阅 JavaScript 出错信息参考.
-- 如果你在阅读了本文之后遇到了一些错误但不知如何解决,你能够得到别人的帮助! 可以到 学习区 或者 Mozilla IRC 的 #mdn 聊天室来提问。告诉我们你遇到的错误是什么,我们会尽量帮助你。附加一段你的代码也是很有用的。
+- 如果你在阅读了本文之后遇到了一些错误但不知如何解决,你能够得到别人的帮助!可以到 学习区 或者 Mozilla IRC 的 #mdn 聊天室来提问。告诉我们你遇到的错误是什么,我们会尽量帮助你。附加一段你的代码也是很有用的。
{{PreviousMenuNext("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps")}}
diff --git a/files/zh-cn/learn/javascript/howto/index.html b/files/zh-cn/learn/javascript/howto/index.html index ffb163454dee8d..3b9a12a8a1c7da 100644 --- a/files/zh-cn/learn/javascript/howto/index.html +++ b/files/zh-cn/learn/javascript/howto/index.html @@ -1,5 +1,5 @@ --- -title: 在JavaSctript中解决问题 +title: 在 JavaSctript 中解决问题 slug: learn/JavaScript/Howto tags: - JavaScript @@ -9,7 +9,7 @@ ---{{LearnSidebar}}-以下链接指向您需要修复的日常常见问题的解决方案,以使您的JavaScript代码正确运行。
+以下链接指向您需要修复的日常常见问题的解决方案,以使您的 JavaScript 代码正确运行。
初学者常见的错误
@@ -81,15 +81,15 @@函数作用域
记住函数拥有自己的作用域——你不能从函数外部访问一个函数内的变量值,除非你在全局声明了该变量(即不在任何函数内),或者从函数外部获得它的返回值。
-在return语句之后运行代码
+在 return 语句之后运行代码
-还要记住,当你向一个函数外部返回一个值时,JavaScript解释器会退出这个函数——在return语句运行之后,没有声明任何代码。
+还要记住,当你向一个函数外部返回一个值时,JavaScript 解释器会退出这个函数——在 return 语句运行之后,没有声明任何代码。
-事实上,如果您在返回语句之后有代码,某些浏览器(如Firefox)会在开发人员控制台中给您一条错误消息。 Firefox在返回语句后给你提示“无法访问的代码”。
+事实上,如果您在返回语句之后有代码,某些浏览器(如 Firefox)会在开发人员控制台中给您一条错误消息。Firefox 在返回语句后给你提示“无法访问的代码”。
对象标记法与正常赋值
-当你在JavaScript中正常赋值时,使用等号:
+当你在 JavaScript 中正常赋值时,使用等号:
var myNumber = 0;@@ -105,22 +105,22 @@基本定义
@@ -132,18 +132,18 @@-
- JavaScript是什么?
-- 变量是什么?
-- 字符串是什么?
-- 数组是什么?
-- 循环是什么?
+- JavaScript 是什么?
+- 变量是什么?
+- 字符串是什么?
+- 数组是什么?
+- 循环是什么?
基本用例
常见
变量
-
- 如何声明一个变量?
-- 如何初始化一个变量的值?
-- 如何更新变量的值? (参见 赋值操作符)
-- JavaScript中有哪些数据类型?
-- '弱类型'是什么意思?
+- 如何声明一个变量?
+- 如何初始化一个变量的值?
+- 如何更新变量的值? (参见 赋值操作符)
+- JavaScript 中有哪些数据类型?
+- '弱类型'是什么意思?
数字
@@ -176,20 +176,20 @@字符串
数组
-
- 怎么创建数组?
-- 如何访问和修改数组中的元素? (包括多维数组)
-- 怎么获取数组的长度?
-- 怎么添加和移除数组中的元素?
-- 如何将一个字符串拆分为数组,或将数组拼接成一个字符串?
+- 怎么创建数组?
+- 如何访问和修改数组中的元素? (包括多维数组)
+- 怎么获取数组的长度?
+- 怎么添加和移除数组中的元素?
+- 如何将一个字符串拆分为数组,或将数组拼接成一个字符串?
JavaScript 调试
-
- 什么是错误的基本类型?
-- 什么是浏览器开发工具,如何使用它?
-- 怎么在JavaScript控制台打印值?
-- 怎么使用断点和其他JavaScript调试工具?
+- 什么是错误的基本类型?
+- 什么是浏览器开发工具,如何使用它?
+- 怎么在 JavaScript 控制台打印值?
+- 怎么使用断点和其他 JavaScript 调试工具?
For more information on JavaScript debugging, see Handling common JavaScript problems; also see Other common errors for a description of common errors.
@@ -273,7 +273,7 @@事件
- What is event delegation, and how does it work?
-面向对象的JavaScript
+面向对象的 JavaScript
- What are object prototypes?
diff --git a/files/zh-cn/learn/javascript/index.html b/files/zh-cn/learn/javascript/index.html index 299a3218ca648e..e85d7ff761f737 100644 --- a/files/zh-cn/learn/javascript/index.html +++ b/files/zh-cn/learn/javascript/index.html @@ -41,17 +41,17 @@模块
- 在这个模块中,我们继续介绍 JavaScript 的关键的基础功能,并逐渐将注意力转移到常见类型的代码块,比如条件语句、循环、函数、以及事件等。你应该已经遇到过这些概念,而这里我们将正式学习。
- JavaScript 对象初识
- 在 JavaScript 中,绝大多数东西都是对象;从作为 JavaScript 核心功能的字符串和数组,到建立在 JavaScript 之上的浏览器 API,无一不是对象。你甚至可以自己创建对象,将相关的函数和变量封装打包。想要进一步学习 JavaScript 语言知识、写出高效的代码的话,理解这种面向对象的特性是必不可少的。这个模块将帮助你了解“对象”,我们将详细介绍对象的设计思想和语法、如何创建对象,并解释 JSON 数据是什么、如何使用。
-- 异步JavaScript
+- 异步 JavaScript
- -
这个模块介绍异步JavaScript: 为什么重要,如何用它来处理 可能引起阻塞的操作(比如从服务器获取资源)
+这个模块介绍异步 JavaScript:为什么重要,如何用它来处理 可能引起阻塞的操作(比如从服务器获取资源)
- 客户端 Web API
- 为网站或应用编写客户端 JavaScript 脚本时,你很难不用到 Web API 接口。这些接口允许你一定程度上操纵网页所运行在的浏览器和操作系统、甚至来自其他网站和服务的数据。在这个模块中,我们将了解有哪些 API,并学习使用开发过程中最常见的 API。
-解决常见的JavaScript问题
+解决常见的 JavaScript 问题
-解决常见的JavaScript问题 提供一些链接,解释如何使用JavaScript来解决创建网页时非常常见的问题。
+解决常见的 JavaScript 问题 提供一些链接,解释如何使用 JavaScript 来解决创建网页时非常常见的问题。
另见
diff --git a/files/zh-cn/learn/javascript/objects/adding_bouncing_balls_features/index.html b/files/zh-cn/learn/javascript/objects/adding_bouncing_balls_features/index.html index eae0d06dc31cbc..5a485989c62e81 100644 --- a/files/zh-cn/learn/javascript/objects/adding_bouncing_balls_features/index.html +++ b/files/zh-cn/learn/javascript/objects/adding_bouncing_balls_features/index.html @@ -14,16 +14,16 @@{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}}-在此次测验中, 你需要将上一节中的“弹球”演示程序作为模板,添加一些新的有趣的功能。
+在此次测验中,你需要将上一节中的“弹球”演示程序作为模板,添加一些新的有趣的功能。
- 预备知识: +预备知识: 请确保完整学习本章所有内容后再开始测验。 - @@ -34,12 +34,12 @@目标: +目标: 测试你对 JavaScript 对象和面向对象结构的理解。 开始
请先下载 index.html、style.css 和 main.js 三个文件。
-注:也可以使用 JSBin 或 Glitch 这样的网站来进行测验。 你可以选择其中一个将HTML,CSS 和JavaScript 粘贴过去。 如果你的版本没有单独的 JavaScript / CSS 板块,可以把它们嵌入 HTML 页面内的
+<script>
/<style>
元素。注:也可以使用 JSBin 或 Glitch 这样的网站来进行测验。你可以选择其中一个将 HTML,CSS 和 JavaScript 粘贴过去。 如果你的版本没有单独的 JavaScript / CSS 板块,可以把它们嵌入 HTML 页面内的
<script>
/<style>
元素。项目简介
-我们的弹球 demo 很有趣, 但是现在我们想让它更具有互动性,我们为它添加一个由玩家控制的“恶魔圈”,如果恶魔圈抓到弹球会把它会吃掉。我们还想测验你面向对象的水平,首先创建一个通用
+Shape()
对象,然后由它派生出弹球和恶魔圈。最后,我们为 demo 添加一个计分器来记录剩下的球数。我们的弹球 demo 很有趣,但是现在我们想让它更具有互动性,我们为它添加一个由玩家控制的“恶魔圈”,如果恶魔圈抓到弹球会把它会吃掉。我们还想测验你面向对象的水平,首先创建一个通用
Shape()
对象,然后由它派生出弹球和恶魔圈。最后,我们为 demo 添加一个计分器来记录剩下的球数。程序最终会像这样:
@@ -315,11 +315,11 @@步骤
创建我们的新对象
-首先, 改变你现有的构造器
+Ball()
使其成为构造器Shape()
并添加一个新的构造器Ball()
:首先,改变你现有的构造器
Ball()
使其成为构造器Shape()
并添加一个新的构造器Ball()
:
- 构造器
-Shape()
应该像构造器Ball()
那样的方式定义x
,y
,velX
, 和velY
属性,但不包括color
和size
。- 还应该定义一个叫
+exists
的新属性,用来标记球是否存在于程序中 (没有被恶魔圈吃掉)。这应该是一个布尔型((true
/false
)。- 还应该定义一个叫
exists
的新属性,用来标记球是否存在于程序中(没有被恶魔圈吃掉)。这应该是一个布尔型((true
/false
)。- 构造器
Ball()
应该从构造器Shape()
继承x
,y
,velX
,velY
,和exists
属性。- 构造器
Ball()
还应该像最初的构造器Ball()
那样定义一个color
和一个size
属性。- 请记得给构造器
@@ -327,9 +327,9 @@Ball()
的prototype
和constructor
属性设置适当的值。创建我们的新对象
-
draw()
,update()
, 和collisionDetect()
方法定义应保持不变。你还需要为
+new Ball() { ... }
构造器添加第五个参数——exists
, 且值为true
。你还需要为
-new Ball() { ... }
构造器添加第五个参数——exists
,且值为true
。到这里, 尝试重新加载代码(运行程序),程序以及重新设计的对象都应该像之前那样工作。
+到这里,尝试重新加载代码(运行程序),程序以及重新设计的对象都应该像之前那样工作。
定义恶魔圈 EvilCircle()
@@ -363,11 +363,11 @@
draw()
-
checkBounds()
这个方法和
+Ball()
的update()
函数做相同的事情—— 查看恶魔圈是否将要超出屏幕的边界, 并且禁止它超出。 同样,你可以直接复制Ball.prototype.update
的定义, 但是你需要做一些修改:这个方法和
Ball()
的update()
函数做相同的事情—— 查看恶魔圈是否将要超出屏幕的边界, 并且禁止它超出。 同样,你可以直接复制Ball.prototype.update
的定义,但是你需要做一些修改:
- 删除最后两行 — 我们不想要在每一帧中自动的更新恶魔圈的位置,因为我们会以下面所述的方式移动它。
-- 在
+if()
语句中,如果检测为真(即小恶魔圈超出边界),我们不需要更新velX
/velY
;取而代之的是,我们想要修改x
/y
的值,使恶魔圈稍微地弹回屏幕。增加或减去 (根据实际判断)恶魔圈size
的值即可实现。- 在
if()
语句中,如果检测为真(即小恶魔圈超出边界),我们不需要更新velX
/velY
;取而代之的是,我们想要修改x
/y
的值,使恶魔圈稍微地弹回屏幕。增加或减去(根据实际判断)恶魔圈size
的值即可实现。@@ -391,7 +391,7 @@
setControls()
} }; -
setControls()
所以当一个按键按下时, 事件对象的 key 属性 就可以请求到按下的按键值。如果是代码中那四个指定的键值之一, 那么恶魔圈将会左右上下的移动。
+所以当一个按键按下时,事件对象的 key 属性 就可以请求到按下的按键值。如果是代码中那四个指定的键值之一,那么恶魔圈将会左右上下的移动。
译注:英文页面中使用了事件对象的 keyCode 属性,不推荐在新代码中使用该属性,应使用标准 key 属性代替。(详见介绍页面)
@@ -404,7 +404,7 @@
collisionDetect()
这个方法和
Ball()
'scollisionDetect()
方法很相似,所以你可以从它那里复制过来作为新方法的基础。但有一些不同之处:-
@@ -413,9 +413,9 @@- 在外层的
+if
语句中,你不需要再检验循环到的小球是否是当前collisionDetect()
所在的对象 — 因为它不再是一个小球了,它是恶魔圈! 而是检查小球是否存在 (你可以通过哪个属性实现这个呢?)。如果小球不存在,说明它已经被恶魔圈吃掉了,那么就不需要再检测它是否与恶魔圈碰撞了。- 在外层的
if
语句中,你不需要再检验循环到的小球是否是当前collisionDetect()
所在的对象 — 因为它不再是一个小球了,它是恶魔圈! 而是检查小球是否存在(你可以通过哪个属性实现这个呢?)。如果小球不存在,说明它已经被恶魔圈吃掉了,那么就不需要再检测它是否与恶魔圈碰撞了。- 在里层的
if
语句中,你不再需要在碰撞被检测到时去改变对象的颜色 — 而是需要将与恶魔圈发生碰撞的小球设置为不存在(再次提问,你觉得你该怎么实现呢?)。把恶魔圈带到程序中
现在我们已经定义了恶魔圈,我们需要让它显示到我们的屏幕中。为了做这件事,你需要修改一下
loop()
函数:-
- 首先,创建一个新的恶魔圈的对象实例 (指定必需的参数),然后调用它的
-setControls()
方法。 这两件事你只需要做一次,不需要放在loop的循环中。- 在你每一次遍历小球并调用
-draw()
,update()
, 和collisionDetect()
函数的地方进行修改, 使这些函数只会在小球存在时被调用。- 在每个loop的循环中调用恶魔圈实例的方法
+draw()
,checkBounds()
, 和collisionDetect()
。- 首先,创建一个新的恶魔圈的对象实例 (指定必需的参数),然后调用它的
+setControls()
方法。 这两件事你只需要做一次,不需要放在 loop 的循环中。- 在你每一次遍历小球并调用
+draw()
,update()
, 和collisionDetect()
函数的地方进行修改,使这些函数只会在小球存在时被调用。- 在每个 loop 的循环中调用恶魔圈实例的方法
draw()
,checkBounds()
, 和collisionDetect()
。计算得分
@@ -423,8 +423,8 @@计算得分
为了计算得分,需按照以下步骤:
-
- 在你的HTML文件中添加一个{{HTMLElement("p")}} 元素到 {{HTMLElement("h1")}} 元素的下面,其中包含文本 "还剩多少个球"。
-- 在你的CSS文件中,添加下面的代码到底部: +
- 在你的 HTML 文件中添加一个{{HTMLElement("p")}} 元素到 {{HTMLElement("h1")}} 元素的下面,其中包含文本 "还剩多少个球"。
+- 在你的 CSS 文件中,添加下面的代码到底部:
p { position: absolute; margin: 0; @@ -452,7 +452,7 @@提示
评定
-如果你将此评估作为有组织的课程的一部分,你可以将你的成果交给您的老师/导师进行评分。 如果你是自学的,通过在 Learning Area Discourse thread, 或者在 Mozilla IRC 的 #mdn IRC 频道上申请,你可以十分容易地得到评分指南。首先先尝试这个练习,作弊不会有任何收获。
+如果你将此评估作为有组织的课程的一部分,你可以将你的成果交给您的老师/导师进行评分。如果你是自学的,通过在 Learning Area Discourse thread, 或者在 Mozilla IRC 的 #mdn IRC 频道上申请,你可以十分容易地得到评分指南。首先先尝试这个练习,作弊不会有任何收获。
{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}}
diff --git a/files/zh-cn/learn/javascript/objects/basics/index.html b/files/zh-cn/learn/javascript/objects/basics/index.html index b721b3a570c7b9..cd876d263427ad 100644 --- a/files/zh-cn/learn/javascript/objects/basics/index.html +++ b/files/zh-cn/learn/javascript/objects/basics/index.html @@ -7,17 +7,17 @@{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}}-在这学习JavaScript的对象的首篇文章中,我们将会学习有关对象基础的语法,并且回顾一些之前学过的JavaScript的一些特点,使你明白你所使用过的一些功能实际上是由对象提供的。
+在这学习 JavaScript 的对象的首篇文章中,我们将会学习有关对象基础的语法,并且回顾一些之前学过的 JavaScript 的一些特点,使你明白你所使用过的一些功能实际上是由对象提供的。
@@ -26,17 +26,17 @@
- 前提: -基础计算机基础, 了解基础的HTML 和 CSS, 熟悉 JavaScript 基础 (基础知识看这里 First steps 和这里 Building blocks). +前提: +基础计算机基础,了解基础的 HTML 和 CSS, 熟悉 JavaScript 基础 (基础知识看这里 First steps 和这里 Building blocks). - 目标: -理解面向对象编程背后的基础理论, 怎样理解 JavaScript ("一切皆对象most things are objects"), 如何开始使用JavaScript对象. +目标: +理解面向对象编程背后的基础理论,怎样理解 JavaScript ("一切皆对象 most things are objects"), 如何开始使用 JavaScript 对象。 对象基础
对象是一个包含相关数据和方法的集合(通常由一些变量和函数组成,我们称之为对象里面的属性和方法),让我们通过一个例子来了解它们。
-首先, 将 oojs.html 文件复制到本地. 此文件包含非常少 — 一个供我们写源代码的 {{HTMLElement("script")}} 标签, 一个供我们输入示例指令的 {{HTMLElement("input")}} 标签,当页面被渲染时, 一些变量定义, 一个输出任何输入到{{HTMLElement("input")}}的内容输出到{{HTMLElement("p")}}标签的函数。我们用这个文件做为基础探索对象的基础语法.
+首先,将 oojs.html 文件复制到本地。此文件包含非常少 — 一个供我们写源代码的 {{HTMLElement("script")}} 标签,一个供我们输入示例指令的 {{HTMLElement("input")}} 标签,当页面被渲染时,一些变量定义,一个输出任何输入到{{HTMLElement("input")}}的内容输出到{{HTMLElement("p")}}标签的函数。我们用这个文件做为基础探索对象的基础语法。
-如同Javascript中的很多东西一样,创建一个对象通常先定义初始化变量。 尝试在您已有的文件中JavaScript代码下面输入以下内容, 保存刷新页面:
+如同 Javascript 中的很多东西一样,创建一个对象通常先定义初始化变量。 尝试在您已有的文件中 JavaScript 代码下面输入以下内容,保存刷新页面:
var person = {};-如果你在浏览器控制台输入person,然后按下Enter(确认)键,你会得到如下结果:
+如果你在浏览器控制台输入 person,然后按下 Enter(确认) 键,你会得到如下结果:
[object Object]-恭喜, 你刚创建了你的第一个对象. 干的漂亮! 但这是一个空对象,所以我们做不了更多的事情。像下面一样更新下我们的对象:
+恭喜,你刚创建了你的第一个对象。干的漂亮!但这是一个空对象,所以我们做不了更多的事情。像下面一样更新下我们的对象:
var person = { name : ['Bob', 'Smith'], @@ -52,7 +52,7 @@-对象基础
};保存刷新后, 尝试在你的浏览器控制台输入下面的内容:
+保存刷新后,尝试在你的浏览器控制台输入下面的内容:
person.name[0] person.age @@ -60,13 +60,13 @@-对象基础
person.bio() person.greeting()现在在你的对象里得到了一些数据和功能(functionality),现在可以通过简单的语法访问他们了!
+现在在你的对象里得到了一些数据和功能(functionality),现在可以通过简单的语法访问他们了!
-Note:如果做上面的东西遇到了麻烦,尝试拿你的代码与我们的版本做对比——对比 oojs-finished.html (也可以 看实际效果)。一个对于初学者很常见的错误是在最后一个成员后面多了一个逗号,这会引发错误。
所以发生了什么?一个对象由许多的成员组成,每一个成员都拥有一个名字(像上面的name、age),和一个值(如['Bob', 'Smith']、32)。每一个名字/值(name/value)对被逗号分隔开,并且名字和值之间由冒号(:)分隔,语法规则如下所示:
+所以发生了什么?一个对象由许多的成员组成,每一个成员都拥有一个名字(像上面的 name、age),和一个值(如 ['Bob', 'Smith']、32)。每一个名字/值(name/value)对被逗号分隔开,并且名字和值之间由冒号(:)分隔,语法规则如下所示:
var objectName = { member1Name : member1Value, @@ -74,15 +74,15 @@-对象基础
member3Name : member3Value }对象成员的值可以是任意的,在我们的person对象里有字符串(string),数字(number),两个数组(array),两个函数(function)。前4个成员是资料项目,被称为对象的属性(property),后两个成员是函数,允许对象对资料做一些操作,被称为对象的方法(method)
+对象成员的值可以是任意的,在我们的 person 对象里有字符串 (string),数字 (number),两个数组 (array),两个函数 (function)。前 4 个成员是资料项目,被称为对象的属性 (property),后两个成员是函数,允许对象对资料做一些操作,被称为对象的方法 (method)
-一个如上所示的对象被称之为对象的字面量(literal)——手动的写出对象的内容来创建一个对象。不同于从类实例化一个对象,我们会在后面学习这种方式。
+一个如上所示的对象被称之为对象的字面量 (literal)——手动的写出对象的内容来创建一个对象。不同于从类实例化一个对象,我们会在后面学习这种方式。
-当你想要传输一些有结构和关联的资料时常见的方式是使用字面量来创建一个对象,举例来说,发起一个请求到服务器以存储一些数据到数据库,发送一个对象要比分别发送这些数据更有效率,而且比起数组更为易用,因为你使用名字(name)来标识这些资料。
+当你想要传输一些有结构和关联的资料时常见的方式是使用字面量来创建一个对象,举例来说,发起一个请求到服务器以存储一些数据到数据库,发送一个对象要比分别发送这些数据更有效率,而且比起数组更为易用,因为你使用名字 (name) 来标识这些资料。
点表示法
-在上面的例子中,你使用了点表示法(dot notation)来访问对象的属性和方法。对象的名字表现为一个命名空间(namespace),它必须写在第一位——当你想访问对象内部的属性或方法时,然后是一个点(.),紧接着是你想要访问的项目,标识可以是简单属性的名字(name),或者是数组属性的一个子元素,又或者是对象的方法调用。如下所示:
+在上面的例子中,你使用了点表示法 (dot notation) 来访问对象的属性和方法。对象的名字表现为一个命名空间 (namespace),它必须写在第一位——当你想访问对象内部的属性或方法时,然后是一个点 (.),紧接着是你想要访问的项目,标识可以是简单属性的名字 (name),或者是数组属性的一个子元素,又或者是对象的方法调用。如下所示:
person.age person.interests[1] @@ -90,7 +90,7 @@点表示法
子命名空间
-可以用一个对象来做另一个对象成员的值。例如将name成员
+可以用一个对象来做另一个对象成员的值。例如将 name 成员
name : ['Bob', 'Smith'],@@ -120,7 +120,7 @@子命名空间
括号表示法
-另外一种访问属性的方式是使用括号表示法(bracket notation),替代这样的代码
+另外一种访问属性的方式是使用括号表示法 (bracket notation),替代这样的代码
person.age person.name.first@@ -130,7 +130,7 @@括号表示法
person['age'] person['name']['first']-这看起来很像访问一个数组的元素,从根本上来说是一回事儿,你使用了关联了值的名字,而不是索引去选择元素。难怪对象有时被称之为关联数组(associative array)了——对象做了字符串到值的映射,而数组做的是数字到值的映射。
+这看起来很像访问一个数组的元素,从根本上来说是一回事儿,你使用了关联了值的名字,而不是索引去选择元素。难怪对象有时被称之为关联数组 (associative array) 了——对象做了字符串到值的映射,而数组做的是数字到值的映射。
设置对象成员
@@ -156,16 +156,16 @@设置对象成员
括号表示法一个有用的地方是它不仅可以动态的去设置对象成员的值,还可以动态的去设置成员的名字。
-比如说,我们想让用户能够在他们的数据里存储自己定义的值类型,通过两个input框来输入成员的名字和值,通过以下代码获取用户输入的值:
+比如说,我们想让用户能够在他们的数据里存储自己定义的值类型,通过两个 input 框来输入成员的名字和值,通过以下代码获取用户输入的值:
var myDataName = nameInput.value var myDataValue = nameValue.value-我们可以这样把这个新的成员的名字和值加到person对象里:
+我们可以这样把这个新的成员的名字和值加到 person 对象里:
person[myDataName] = myDataValue-为了测试这个功能,尝试在你的代码里添加以下几行,就在person对象的右花括号的下面:
+为了测试这个功能,尝试在你的代码里添加以下几行,就在 person 对象的右花括号的下面:
var myDataName = 'height' var myDataValue = '1.75m' @@ -185,9 +185,9 @@-"this"的含义
alert('Hi! I\'m ' + this.name.first + '.'); }你也许想知道"this"是什么,关键字"this"指向了当前代码运行时的对象( 原文:the current object the code is being written inside )——这里即指person对象,为什么不直接写person呢?当你学到下一篇Object-oriented JavaScript for beginners文章时,我们开始使用构造器(constructor)时,"this"是非常有用的——它保证了当代码的上下文(context)改变时变量的值的正确性(比如:不同的person对象拥有不同的name这个属性,很明显greeting这个方法需要使用的是它们自己的name)。
+你也许想知道"this"是什么,关键字"this"指向了当前代码运行时的对象 ( 原文:the current object the code is being written inside )——这里即指 person 对象,为什么不直接写 person 呢?当你学到下一篇Object-oriented JavaScript for beginners文章时,我们开始使用构造器 (constructor) 时,"this"是非常有用的——它保证了当代码的上下文 (context) 改变时变量的值的正确性(比如:不同的 person 对象拥有不同的 name 这个属性,很明显 greeting 这个方法需要使用的是它们自己的 name)。
-让我们以两个简单的person对象来说明:
+让我们以两个简单的 person 对象来说明:
var person1 = { name : 'Chris', @@ -203,28 +203,28 @@-"this"的含义
} }在这里,person1.greeting()会输出:"Hi! I'm Chris.";person2.greeting()会输出:"Hi! I'm Brain.",即使greeting这个方法的代码是一样的。就像我们之前说的,this 指向了代码所在的对象(其实代码运行时所在的对象)。在字面量的对象里this看起来不是很有用,但是当你动态创建一个对象(例如使用构造器)时它是非常有用的,之后你会更清楚它的用途。
+在这里,person1.greeting() 会输出:"Hi! I'm Chris.";person2.greeting() 会输出:"Hi! I'm Brain.",即使 greeting 这个方法的代码是一样的。就像我们之前说的,this 指向了代码所在的对象 (其实代码运行时所在的对象)。在字面量的对象里 this 看起来不是很有用,但是当你动态创建一个对象(例如使用构造器)时它是非常有用的,之后你会更清楚它的用途。
你一直在使用对象
-当你使用过这些例子之后,你可能会发现你对点表示法并不陌生,这是因为我们在这个课程里一直在使用它,每次我们学习的示例使用浏览器内建的API和JavaScript的一些对象时,我们就在使用对象,因为,这些功能是由跟我们所看到的对象同样的结构来构建的,虽然比我们自己定义的要复杂许多。
+当你使用过这些例子之后,你可能会发现你对点表示法并不陌生,这是因为我们在这个课程里一直在使用它,每次我们学习的示例使用浏览器内建的 API 和 JavaScript 的一些对象时,我们就在使用对象,因为,这些功能是由跟我们所看到的对象同样的结构来构建的,虽然比我们自己定义的要复杂许多。
所以当我们这样使用字符串的方法时:
myString.split(',');-你正在使用一个字符串实例上可用的方法,你随时都可以在代码里使用字面量创建一个字符串,字符串会自动的被创建为字符串(
+String
)的实例,因此会有一些常见的方法和属性可用。你正在使用一个字符串实例上可用的方法,你随时都可以在代码里使用字面量创建一个字符串,字符串会自动的被创建为字符串 (
-String
) 的实例,因此会有一些常见的方法和属性可用。当你这样访问document对象时:
+当你这样访问 document 对象时:
var myDiv = document.createElement('div'); var myVideo = document.querySelector('video');-你正在使用
+Document
实例上可用的方法。每个页面在加载完毕后,会有一个Document的实例被创建,叫做document,它代表了整个页面的结构,内容和一些功能,比如页面的URL。同样的,这意味document有一些可用的方法和属性。你正在使用
-Document
实例上可用的方法。每个页面在加载完毕后,会有一个 Document 的实例被创建,叫做 document,它代表了整个页面的结构,内容和一些功能,比如页面的 URL。同样的,这意味 document 有一些可用的方法和属性。这同样适用许多其他内建的对象或API,你使用过有——
+Array
,Math
, 等。这同样适用许多其他内建的对象或 API,你使用过有——
-Array
,Math
,等。请注意内建的对象或API不会总是自动地创建对象的实例,举例来说,这个 Notifications API——允许浏览器发起系统通知,需要你为每一个你想发起的通知都使用构造器进行实例化。尝试在JavaScript终端里输入以下代码
+请注意内建的对象或 API 不会总是自动地创建对象的实例,举例来说,这个 Notifications API——允许浏览器发起系统通知,需要你为每一个你想发起的通知都使用构造器进行实例化。尝试在 JavaScript 终端里输入以下代码
var myNotification = new Notification('Hello!');@@ -236,8 +236,8 @@你一直在使用对象
总结
-恭喜,你已经阅读到了我们有关JavaScript对象的第一篇文章的末尾,你现在应该对如何在JavaScript中使用对象有了很好的认识,包括你自己创建一个简单的对象。你应该清楚对象有利于存储一些相关联的数据和函数,如果你尝试以分开的方式去保存person对象包含的所有的属性和方法,这是令人沮丧且效率低下的,而且会有很多的变量和函数之间同名的风险。对象使我们将一些信息安全地锁在了它们自己的包内,防止它们被损坏。
+恭喜,你已经阅读到了我们有关 JavaScript 对象的第一篇文章的末尾,你现在应该对如何在 JavaScript 中使用对象有了很好的认识,包括你自己创建一个简单的对象。你应该清楚对象有利于存储一些相关联的数据和函数,如果你尝试以分开的方式去保存 person 对象包含的所有的属性和方法,这是令人沮丧且效率低下的,而且会有很多的变量和函数之间同名的风险。对象使我们将一些信息安全地锁在了它们自己的包内,防止它们被损坏。
-在下一篇文章,我们将会了解面对对象编程(OOP)理论,和许多在JavaScript中使用的技巧。
+在下一篇文章,我们将会了解面对对象编程 (OOP) 理论,和许多在 JavaScript 中使用的技巧。
{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}}
diff --git a/files/zh-cn/learn/javascript/objects/classes_in_javascript/index.html b/files/zh-cn/learn/javascript/objects/classes_in_javascript/index.html index 568f21b126b45b..5537065db75412 100644 --- a/files/zh-cn/learn/javascript/objects/classes_in_javascript/index.html +++ b/files/zh-cn/learn/javascript/objects/classes_in_javascript/index.html @@ -7,7 +7,7 @@ - 原型 - 对象 - 继承 - - 面向对象JS + - 面向对象 JS translation_of: Learn/JavaScript/Objects/Inheritance original_slug: Learn/JavaScript/Objects/Inheritance --- @@ -20,11 +20,11 @@
- 预备知识: -基本的计算机素养,对 HTML 和 CSS 有基本的理解,熟悉 JavaScript 基础(参见 First steps 和 Building blocks)以及面向对象的JavaScript (OOJS) 基础(参见 Introduction to objects)。 +预备知识: +基本的计算机素养,对 HTML 和 CSS 有基本的理解,熟悉 JavaScript 基础(参见 First steps 和 Building blocks)以及面向对象的 JavaScript (OOJS) 基础(参见 Introduction to objects)。 - @@ -32,15 +32,15 @@目标: +目标: 理解在 JavaScript 中如何实现继承。 原型式的继承
-到目前为止我们已经了解了一些关于原型链的实现方式以及成员变量是如何通过它来实现继承,但是之前涉及到的大部分都是浏览器内置函数(比如
+String
、Date
、Number
和Array
),那么我们如何创建一个继承自另一对象的JavaScript对象呢?到目前为止我们已经了解了一些关于原型链的实现方式以及成员变量是如何通过它来实现继承,但是之前涉及到的大部分都是浏览器内置函数(比如
-String
、Date
、Number
和Array
),那么我们如何创建一个继承自另一对象的 JavaScript 对象呢?正如前面课程所提到的,有些人认为JavaScript并不是真正的面向对象语言,在经典的面向对象语言中,您可能倾向于定义类对象,然后您可以简单地定义哪些类继承哪些类(参考C++ inheritance里的一些简单的例子),JavaScript使用了另一套实现方式,继承的对象函数并不是通过复制而来,而是通过原型链继承(通常被称为 原型式继承 —— prototypal inheritance)。
+正如前面课程所提到的,有些人认为 JavaScript 并不是真正的面向对象语言,在经典的面向对象语言中,您可能倾向于定义类对象,然后您可以简单地定义哪些类继承哪些类(参考C++ inheritance里的一些简单的例子),JavaScript 使用了另一套实现方式,继承的对象函数并不是通过复制而来,而是通过原型链继承(通常被称为 原型式继承 —— prototypal inheritance)。
让我们通过具体的例子来解释上述概念
开始
-首先,将oojs-class-inheritance-start.html文件复制到您本地(也可以 在线运行 ),其中您能看到一个只定义了一些属性的
+Person()
构造器,与之前通过模块来实现所有功能的Person的构造器类似。首先,将oojs-class-inheritance-start.html文件复制到您本地(也可以 在线运行 ),其中您能看到一个只定义了一些属性的
Person()
构造器,与之前通过模块来实现所有功能的 Person 的构造器类似。function Person(first, last, age, gender, interests) { this.name = { @@ -82,7 +82,7 @@-定义 Teacher() 构造器函数
}这在很多方面看起来都和Person的构造器很像,但是这里有一些我们从没见过的奇怪玩意——
+call()
函数。基本上,这个函数允许您调用一个在这个文件里别处定义的函数。第一个参数指明了在您运行这个函数时想对“this
”指定的值,也就是说,您可以重新指定您调用的函数里所有“this
”指向的对象。其他的变量指明了所有目标函数运行时接受的参数。这在很多方面看起来都和 Person 的构造器很像,但是这里有一些我们从没见过的奇怪玩意——
call()
函数。基本上,这个函数允许您调用一个在这个文件里别处定义的函数。第一个参数指明了在您运行这个函数时想对“this
”指定的值,也就是说,您可以重新指定您调用的函数里所有“this
”指向的对象。其他的变量指明了所有目标函数运行时接受的参数。注:在这个例子里我们在创建一个新的对象实例时同时指派了继承的所有属性,但是注意您需要在构造器里将它们作为参数来指派,即使实例不要求它们被作为参数指派(比如也许您在创建对象的时候已经得到了一个设置为任意值的属性)
@@ -106,7 +106,7 @@定义 Teacher() 构造器函数
} -但是这只是重新定义了一遍属性,并不是将他们从Person()中继承过来的,所以这违背了我们的初衷。这样写也会需要更长的代码。
+但是这只是重新定义了一遍属性,并不是将他们从 Person() 中继承过来的,所以这违背了我们的初衷。这样写也会需要更长的代码。
从无参构造函数继承
@@ -146,9 +146,9 @@设置 Teacher()
- 现在,如果你保存并刷新,输入
-Teacher.prototype.constructor
应该会根据需要返回Teacher()
,此外,我们现在在继承Person()
!向 Teacher() 添加一个新的greeting()函数
+向 Teacher() 添加一个新的 greeting() 函数
-为了完善代码,您还需在构造函数
+Teacher()
上定义一个新的函数greeting()
。最简单的方法是在Teacher的原型上定义它—把以下代码添加到您代码的底部:为了完善代码,您还需在构造函数
Teacher()
上定义一个新的函数greeting()
。最简单的方法是在 Teacher 的原型上定义它—把以下代码添加到您代码的底部:Teacher.prototype.greeting = function() { var prefix; @@ -188,13 +188,13 @@范例尝试
我们在这里讲述的技巧并不是 JavaScript 中创建继承类的唯一方式,但是这个技巧也还不错,非常好地告诉了您如何在 JavaScript 中实行继承操作。
-您可能对在 JavaScript中使用其他方法来实行继承会感兴趣(参见 Classes)。我们没有覆盖那些内容,因为并不是每种浏览器都会支持这些方法。我们在这一系列文章中介绍的所有其他方法都会被 IE9 支持或者更老的浏览器支持,也有一些方法可以支持更老的浏览器。
+您可能对在 JavaScript 中使用其他方法来实行继承会感兴趣 (参见 Classes)。我们没有覆盖那些内容,因为并不是每种浏览器都会支持这些方法。我们在这一系列文章中介绍的所有其他方法都会被 IE9 支持或者更老的浏览器支持,也有一些方法可以支持更老的浏览器。
一个常用的方法是使用 JavaScript 语言库——最热门的一些库提供一些方法让我们更快更好地实行继承。比如 CoffeeScript 就提供一些类和扩展。
更多练习
-在我们的 OOP theory section 模块中, 我们也将学生类作为一个概念,继承了 Person 所有的属性和方法,也有一个不同的打招呼的方法(比老师的打招呼轻松随意一些)。您可以自己尝试一下如何实现。
+在我们的 OOP theory section 模块中,我们也将学生类作为一个概念,继承了 Person 所有的属性和方法,也有一个不同的打招呼的方法(比老师的打招呼轻松随意一些)。您可以自己尝试一下如何实现。
注:如果你编写时遇到困难,代码无法运行,那么可以查看我们的完成版本(也可查看 可运行的在线示例)。
@@ -268,7 +268,7 @@ECMAScript 2015 类
类语法继承
-上面我们创建了一个类来代表一个人。 它们具有一系列所有人共有的属性; 在本节中,我们将创建我们的专用
+Teacher
类,使其使用现代类语法从Person
继承。 这称为创建子类或子类化。上面我们创建了一个类来代表一个人。它们具有一系列所有人共有的属性;在本节中,我们将创建我们的专用
Teacher
类,使其使用现代类语法从Person
继承。这称为创建子类或子类化。要创建一个子类,我们使用 extends 关键字来告诉 JavaScript 我们想要的在我们的类的基础上的类。
@@ -281,7 +281,7 @@类语法继承
但这里有一个小问题。
-不同于老式的构造函数,其中
+new
运算符进行初始化this
到一个新分配的对象。这里不会为由 extends 关键字定义的类自动初始化 ,例如,子类。不同于老式的构造函数,其中
new
运算符进行初始化this
到一个新分配的对象。这里不会为由 extends 关键字定义的类自动初始化,例如,子类。因此运行上面的代码会报错:
@@ -290,7 +290,7 @@类语法继承
对于子类,对新分配对象的
-this
初始化始终依赖于父类构造函数,例如,你要扩展的类的构造函数。这里我们扩展了
+Person
类——Teacher
子类是Person
类的扩展。 所以对于Teacher
来说,this
的初始化是由Person
构造函数完成的。这里我们扩展了
Person
类——Teacher
子类是Person
类的扩展。所以对于Teacher
来说,this
的初始化是由Person
构造函数完成的。要调用父构造函数,我们必须使用
@@ -404,14 +404,14 @@super()
运算符,像这样:Getters and Setters
何时在 JavaScript 中使用继承?
-特别是在读完这段文章内容之后,您也许会想 "天啊,这实在是太复杂了". 是的,您是对的,原型和继承代表了JavaScript这门语言里最复杂的一些方面,但是JavaScript的强大和灵活性正是来自于它的对象体系和继承方式,这很值得花时间去好好理解下它是如何工作的。
+特别是在读完这段文章内容之后,您也许会想 "天啊,这实在是太复杂了". 是的,您是对的,原型和继承代表了 JavaScript 这门语言里最复杂的一些方面,但是 JavaScript 的强大和灵活性正是来自于它的对象体系和继承方式,这很值得花时间去好好理解下它是如何工作的。
-在某种程度上来说,您一直都在使用继承 - 无论您是使用WebAPI的不同特性还是调用字符串、数组等浏览器内置对象的方法和属性的时候,您都在隐式地使用继承。
+在某种程度上来说,您一直都在使用继承 - 无论您是使用 WebAPI 的不同特性还是调用字符串、数组等浏览器内置对象的方法和属性的时候,您都在隐式地使用继承。
就在自己代码中使用继承而言,您可能不会使用的非常频繁,特别是在小型项目中或者刚开始学习时 - 因为当您不需要对象和继承的时候,仅仅为了使用而使用它们只是在浪费时间而已。但是随着您的代码量的增大,您会越来越发现它的必要性。如果您开始创建一系列拥有相似特性的对象时,那么创建一个包含所有共有功能的通用对象,然后在更特殊的对象类型中继承这些特性,将会变得更加方便有用。
-注: 考虑到JavaScript的工作方式,由于原型链等特性的存在,在不同对象之间功能的共享通常被叫做 委托 - 特殊的对象将功能委托给通用的对象类型完成。这也许比将其称之为继承更为贴切,因为“被继承”了的功能并没有被拷贝到正在“进行继承”的对象中,相反它仍存在于通用的对象中。
+注:考虑到 JavaScript 的工作方式,由于原型链等特性的存在,在不同对象之间功能的共享通常被叫做 委托 - 特殊的对象将功能委托给通用的对象类型完成。这也许比将其称之为继承更为贴切,因为“被继承”了的功能并没有被拷贝到正在“进行继承”的对象中,相反它仍存在于通用的对象中。
在使用继承时,建议您不要使用过多层次的继承,并仔细追踪定义方法和属性的位置。很有可能您的代码会临时修改了浏览器内置对象的原型,但您不应该这么做,除非您有足够充分的理由。过多的继承会在调试代码时给您带来无尽的混乱和痛苦。
@@ -428,8 +428,8 @@参见
- ObjectPlayground.com - 一个非常有用的、用于了解对象的交互式学习网站。
-- Secrets of the JavaScript Ninja, 第6章 - 由John Resig和Bear Bibeault撰写的关于高级JavaScript概念和技术的好书。第6章很好地介绍了原型和继承的相关方面;您可以很容易地找到打印版本或在线副本。
-- You Don't Know JS: this & Object Prototypes - 凯尔·辛普森(Kyle Simpson)的一系列优秀的JavaScript手册,第5章对原型的解释比我们在这里做的更详细。我们在本系列针对初学者的文章中提出了简化的观点,而凯尔深入学习,并提供了更为复杂但更准确的图景。
+- Secrets of the JavaScript Ninja, 第 6 章 - 由 John Resig 和 Bear Bibeault 撰写的关于高级 JavaScript 概念和技术的好书。第 6 章很好地介绍了原型和继承的相关方面;您可以很容易地找到打印版本或在线副本。
+- You Don't Know JS: this & Object Prototypes - 凯尔·辛普森(Kyle Simpson)的一系列优秀的 JavaScript 手册,第 5 章对原型的解释比我们在这里做的更详细。我们在本系列针对初学者的文章中提出了简化的观点,而凯尔深入学习,并提供了更为复杂但更准确的图景。
{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}
diff --git a/files/zh-cn/learn/javascript/objects/index.html b/files/zh-cn/learn/javascript/objects/index.html index 04790e4adb1176..02d9563e9d999a 100644 --- a/files/zh-cn/learn/javascript/objects/index.html +++ b/files/zh-cn/learn/javascript/objects/index.html @@ -14,13 +14,13 @@ ---{{LearnSidebar}}-在 JavaScript 中,大多数事物都是对象, 从作为核心功能的字符串和数组,到建立在 JavaScript 之上的浏览器 {{Glossary("API", "API")}} 。你甚至可以自己创建对象,将相关的函数和变量高效地封装打包成便捷的数据容器。对于进一步学习 JavaScript 语言知识而言,理解这种面向对象(object-oriented, OO)的特性是必不可少的,所以,我们提供了这个模块来帮助你了解这一切。这里我们会先详细介绍对象的理论和语法,再介绍如何创建对象。
+在 JavaScript 中,大多数事物都是对象,从作为核心功能的字符串和数组,到建立在 JavaScript 之上的浏览器 {{Glossary("API", "API")}} 。你甚至可以自己创建对象,将相关的函数和变量高效地封装打包成便捷的数据容器。对于进一步学习 JavaScript 语言知识而言,理解这种面向对象(object-oriented, OO)的特性是必不可少的,所以,我们提供了这个模块来帮助你了解这一切。这里我们会先详细介绍对象的理论和语法,再介绍如何创建对象。
预备知识
开始这个模块之前,你应当已经对 HTML 和 CSS 有所了解。我们建议你通读 HTML 入门和 CSS 入门模块,再开始了解 JavaScript。
-详细了解 JavaScript 对象之前,你应当已经对 JavaScript 基础有所熟悉。尝试这个模块之前,请通读 JavaScript 第一步 和 JavaScript基础要件
+详细了解 JavaScript 对象之前,你应当已经对 JavaScript 基础有所熟悉。尝试这个模块之前,请通读 JavaScript 第一步 和 JavaScript 基础要件
注意:如果您无法在当前使用的电脑/平板/其他设备上创建自己的文件,可以使用在线编程网站如 JSBin 或 Glitch,来试验文章中的(大多数)代码。
diff --git a/files/zh-cn/learn/javascript/objects/json/index.html b/files/zh-cn/learn/javascript/objects/json/index.html index 019f71af95e158..eb32a3dba2601b 100644 --- a/files/zh-cn/learn/javascript/objects/json/index.html +++ b/files/zh-cn/learn/javascript/objects/json/index.html @@ -1,5 +1,5 @@ --- -title: 使用JSON +title: 使用 JSON slug: Learn/JavaScript/Objects/JSON tags: - Working with JSON data @@ -9,16 +9,16 @@{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}}-JavaScript对象表示法(JSON)是用于将结构化数据表示为JavaScript对象的标准格式,通常用于在网站上表示和传输数据(例如从服务器向客户端发送一些数据,因此可以将其显示在网页上)。您会经常遇到它,所以在本文中,我们向您提供使用JavaScript处理JSON的所有工作,包括访问JSON对象中的数据项并编写自己的JSON。
+JavaScript 对象表示法(JSON)是用于将结构化数据表示为 JavaScript 对象的标准格式,通常用于在网站上表示和传输数据(例如从服务器向客户端发送一些数据,因此可以将其显示在网页上)。您会经常遇到它,所以在本文中,我们向您提供使用 JavaScript 处理 JSON 的所有工作,包括访问 JSON 对象中的数据项并编写自己的 JSON。
- 前提: -计算机基础知识,HTML 和 CSS 基础 (see First steps and Building blocks) 和 JS 面向对象基础(see Introduction to objects)。 +前提: +计算机基础知识,HTML 和 CSS 基础 (see First steps and Building blocks) 和 JS 面向对象基础 (see Introduction to objects)。 - @@ -26,9 +26,9 @@目标: +目标: 理解 JSON 的数据储存工作原理,创建您的 JSON 对象。 什么是 JSON?
-{{glossary("JSON")}} 是一种按照JavaScript对象语法的数据格式,这是 Douglas Crockford 推广的。虽然它是基于 JavaScript 语法,但它独立于JavaScript,这也是为什么许多程序环境能够读取(解读)和生成 JSON。
+{{glossary("JSON")}} 是一种按照 JavaScript 对象语法的数据格式,这是 Douglas Crockford 推广的。虽然它是基于 JavaScript 语法,但它独立于 JavaScript,这也是为什么许多程序环境能够读取(解读)和生成 JSON。
-JSON可以作为一个对象或者字符串存在,前者用于解读 JSON 中的数据,后者用于通过网络传输 JSON 数据。 这不是一个大事件——JavaScript 提供一个全局的 可访问的 JSON 对象来对这两种数据进行转换。
+JSON 可以作为一个对象或者字符串存在,前者用于解读 JSON 中的数据,后者用于通过网络传输 JSON 数据。 这不是一个大事件——JavaScript 提供一个全局的 可访问的 JSON 对象来对这两种数据进行转换。
一个 JSON 对象可以被储存在它自己的文件中,这基本上就是一个文本文件,扩展名为
@@ -78,7 +78,7 @@.json
, 还有 {{glossary("MIME type")}} 用于application/json
.JSON 结构
] } -如果我们要加载对象进入 JavaScript 程序,以保存为一个名为
+superHeroes
对象为例,我们使用 . 或 [] 访问对象内的数据(关于. 和 []概念,见 对象基础 )。如:如果我们要加载对象进入 JavaScript 程序,以保存为一个名为
superHeroes
对象为例,我们使用 . 或 [] 访问对象内的数据(关于。和 [] 概念,见 对象基础 )。如:superHeroes.hometown superHeroes["active"]@@ -88,7 +88,7 @@JSON 结构
superHeroes["members"][1]["powers"][2]-
- 首先我们有变量名
+superHeroes
,储存对象 。- 首先我们有变量名
superHeroes
,储存对象。- 在对象中我们想访问
members
属性,所以我们使用["members"]
。members
包含有对象数组,我们想要访问第二个元素,所以我们使用[1]
。- 在对象内,我们想访问
@@ -96,7 +96,7 @@powers
属性,所以我们使用["powers"]
。JSON 结构
-注:我们已经在 JSONText.html 实例中让JSON 对象进入变量中使其可访问(见源代码)。尝试加载它并且在您的浏览器上访问对象数据。
+注:我们已经在 JSONText.html 实例中让 JSON 对象进入变量中使其可访问(见源代码)。尝试加载它并且在您的浏览器上访问对象数据。
JSON 数组
@@ -132,19 +132,19 @@其他注意事项
-
- JSON 是一种纯数据格式,它只包含属性,没有方法。
-- JSON要求在字符串和属性名称周围使用双引号。 单引号无效。
-- 甚至一个错位的逗号或分号就可以导致 JSON 文件出错。您应该小心的检查您想使用的数据(虽然计算机生成的 JSON 很少出错,只要生成程序正常工作)。您可以通过像 JSONLint 的应用程序来检验 JSON。
+- JSON 要求在字符串和属性名称周围使用双引号。单引号无效。
+- 甚至一个错位的逗号或分号就可以导致 JSON 文件出错。您应该小心的检查您想使用的数据 (虽然计算机生成的 JSON 很少出错,只要生成程序正常工作)。您可以通过像 JSONLint 的应用程序来检验 JSON。
- JSON 可以将任何标准合法的 JSON 数据格式化保存,不只是数组和对象。比如,一个单一的字符串或者数字可以是合法的 JSON 对象。虽然不是特别有用处……
- 与 JavaScript 代码中对象属性可以不加引号不同,JSON 中只有带引号的字符串可以用作属性。
主动学习 : 一个JSON 示例
+主动学习 : 一个 JSON 示例
-好了,让我们通过运行这个示例来展示我们如何利用JSON数据。
+好了,让我们通过运行这个示例来展示我们如何利用 JSON 数据。
开始吧
-首先,拷贝我们的 heroes.html 和 style.css 文件。后者包含了用于页面的简单的 CSS ,前者包含了简单的 HTML body。
+首先,拷贝我们的 heroes.html 和 style.css 文件。后者包含了用于页面的简单的 CSS,前者包含了简单的 HTML body。
<header> </header> @@ -158,21 +158,21 @@-开始吧
var section = document.querySelector('section');我们已经把 JSON 数据放在了GitHub 上面:https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json
+我们已经把 JSON 数据放在了 GitHub 上面:https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json
我们准备把它加载到我们的页面中,然后使用漂亮的 DOM 操作来展示它,就像这样:
-加载我们的JSON
+加载我们的 JSON
-为了载入 JSON 到页面中,我们将使用 一个名为
+XMLHTTPRequest
的API(常称为XHR)。这是一个非常有用的 JavaScript 对象,使我们能够通过代码来向服务器请求资源文件(如:图片,文本,JSON,甚至HTML片段),意味着我们可以更新小段内容而不用重新加载整个页面。这将有更多响应页面,听起来让人兴奋,但是这部分超出我们本部分的文章,所以就不多详述了。为了载入 JSON 到页面中,我们将使用 一个名为
XMLHTTPRequest
的 API(常称为 XHR)。这是一个非常有用的 JavaScript 对象,使我们能够通过代码来向服务器请求资源文件 (如:图片,文本,JSON,甚至 HTML 片段),意味着我们可以更新小段内容而不用重新加载整个页面。这将有更多响应页面,听起来让人兴奋,但是这部分超出我们本部分的文章,所以就不多详述了。-
-- 首先,我们将保存一个即将访问的 URL 作为变量。在您的 JavaScript 代码的底部添加下面的代码: +
- 首先,我们将保存一个即将访问的 URL 作为变量。在您的 JavaScript 代码的底部添加下面的代码:
-var requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';- 为了创建一个HTTP请求,我们需要创建一个HTTP请求对象,通过 new 构造函数的形式。在您最下面的代码中写入: +
- 为了创建一个 HTTP 请求,我们需要创建一个 HTTP 请求对象,通过 new 构造函数的形式。在您最下面的代码中写入:
var request = new XMLHttpRequest();- 现在我们需要使用
open()
函数打开一个新的请求,添加如下代码: @@ -198,13 +198,13 @@加载我们的JSON
这儿我们保存了相应我们请求的数据(访问
+response
属性) 于变量superHeroes
;这个变量现在含有 JSON!我们现在把superHeroes
传给两个函数,第一个函数将会用正确的数据填充<header>
,同时第二个函数将创建一个信息卡片,然后把它插入<section>
中。这儿我们保存了相应我们请求的数据 (访问
-response
属性) 于变量superHeroes
;这个变量现在含有 JSON!我们现在把superHeroes
传给两个函数,第一个函数将会用正确的数据填充<header>
,同时第二个函数将创建一个信息卡片,然后把它插入<section>
中。我们把代码包在事件处理函数中,当请求对象
+load
事件触发时执行代码(见onload
),这是因为请求对象load
事件只有在请求成功时触发;这种方式可以保证事件触发时request.response
是绝对可以访问的。我们把代码包在事件处理函数中,当请求对象
load
事件触发时执行代码 (见onload
),这是因为请求对象load
事件只有在请求成功时触发;这种方式可以保证事件触发时request.response
是绝对可以访问的。定位 header
-现在我们已经获得我们的JSON数据,让我们利用它来写两个我们使用的函数。首先,添加下面的代码于之前的代码下方:
+现在我们已经获得我们的 JSON 数据,让我们利用它来写两个我们使用的函数。首先,添加下面的代码于之前的代码下方:
function populateHeader(jsonObj) { var myH1 = document.createElement('h1'); @@ -260,7 +260,7 @@创建英雄信息卡片
接下来,我们使用一个循环来,遍历每个元素。对于每一个元素,我们:
-
- 创建几个元素: 一个
+<article>
,一个<h2>
, 三个<p>
s, 和一个<ul>。
- 创建几个元素:一个
<article>
,一个<h2>
, 三个<p>
s, 和一个<ul>。
- 设置
<h2>
为当前英雄的name
。- 使用他们的
secretIdentity
,age
, "Superpowers:" 介绍信息列表 填充三个段落来。- 保存
@@ -269,11 +269,11 @@powers
属性于另一个变量superPowers
,包含英雄的superpowers
列表。创建英雄信息卡片
-Note: 如有疑难,试试引用我们的 heroes-finished.html 代码(也可见 running live )。
+Note: 如有疑难,试试引用我们的 heroes-finished.html 代码 (也可见 running live )。
-Note: 如果您对访问 JSON对象的 点/括号标记 有困扰。获得文件 superheroes.json 并在您的编辑器中打开参考我们的 JS 代码将会有帮助。您还应该参考我们的 JavaScript object basics文章,了解关于点和括号符号的更多信息。
+Note: 如果您对访问 JSON 对象的 点/括号标记 有困扰。获得文件 superheroes.json 并在您的编辑器中打开参考我们的 JS 代码将会有帮助。您还应该参考我们的 JavaScript object basics文章,了解关于点和括号符号的更多信息。
对象和文本间的转换
@@ -282,11 +282,11 @@对象和文本间的转换
request.responseType = 'json';-但是有时候我们没有那么幸运,我们接收到一些 字符串作为 JSON 数据,然后我们想要将它转换为对象。当我们想要发送 JSON 数据作为信息,我们将需要转换它为字符串,我们经常需要正确的转换数据,幸运的是,这两个问题在web环境中是那么普遍以至于浏览器拥有一个内建的 JSON,包含以下两个方法。
+但是有时候我们没有那么幸运,我们接收到一些 字符串作为 JSON 数据,然后我们想要将它转换为对象。当我们想要发送 JSON 数据作为信息,我们将需要转换它为字符串,我们经常需要正确的转换数据,幸运的是,这两个问题在 web 环境中是那么普遍以至于浏览器拥有一个内建的 JSON,包含以下两个方法。
-
- -
parse()
: 以文本字符串形式接受JSON对象作为参数,并返回相应的对象。- +
stringify()
: 接收一个对象作为参数,返回一个对应的JSON字符串。- +
parse()
: 以文本字符串形式接受 JSON 对象作为参数,并返回相应的对象。stringify()
: 接收一个对象作为参数,返回一个对应的 JSON 字符串。您可以看看我们 heroes-finished-json-parse.html 示例的第一个操作 (见 source code) ,除了返回的是 text,这做了一件与我们之前一模一样的事情,然后使用
@@ -302,18 +302,18 @@parse()
来将他转换成为 JavaScript 对象。关键片段如下:对象和文本间的转换
showHeroes(superHeroes); } -正如您所想,
+stringify()
做相反的事情. 尝试将下面的代码输入您的浏览器 JS 控制台来看看会发生什么:正如您所想,
stringify()
做相反的事情。尝试将下面的代码输入您的浏览器 JS 控制台来看看会发生什么:var myJSON = { "name" : "Chris", "age" : "38" }; myJSON var myString = JSON.stringify(myJSON); myString-这儿我们创建了一个JavaScript 对象,然后检查了它包含了什么,然后用
+stringify()
将它转换成JSON字符串,最后保存返回值作为变量。然后再一次检查。这儿我们创建了一个 JavaScript 对象,然后检查了它包含了什么,然后用
stringify()
将它转换成 JSON 字符串,最后保存返回值作为变量。然后再一次检查。总结
-在这个文章中,我们给了您一个简单的示例来在自己的程序中使用 JSON,包括创建和处理 JSON,还有如何访问 JSON 内的数据。在下一篇文章中我们将开始关注JS中的面向对象内容。
+在这个文章中,我们给了您一个简单的示例来在自己的程序中使用 JSON,包括创建和处理 JSON,还有如何访问 JSON 内的数据。在下一篇文章中我们将开始关注 JS 中的面向对象内容。
参见
diff --git a/files/zh-cn/learn/javascript/objects/object_building_practice/index.html b/files/zh-cn/learn/javascript/objects/object_building_practice/index.html index 91d46bc9547364..462ae25883e526 100644 --- a/files/zh-cn/learn/javascript/objects/object_building_practice/index.html +++ b/files/zh-cn/learn/javascript/objects/object_building_practice/index.html @@ -19,11 +19,11 @@
- 预备知识: -基本的计算机知识,了解HTML与CSS的基本概念,熟悉JavaScript基本知识 (请参阅 入门 和 构建块结构)和面向对象的JavaScript (OOJS) 基础 (请参阅 对象基础)。 +预备知识: +基本的计算机知识,了解 HTML 与 CSS 的基本概念,熟悉 JavaScript 基本知识(请参阅 入门 和 构建块结构)和面向对象的 JavaScript(OOJS)基础(请参阅 对象基础)。 - @@ -176,7 +176,7 @@目标: +目标: 练习使用对象,在真实环境中应用面向对象开发技术。 Bouncing balls
{{ EmbedLiveSample('Bouncing_balls', '100%', 480, "", "", "hide-codepen-jsfiddle") }}
-这个实例将会利用 Canvas API 来在屏幕上画小球, 还会用到 requestAnimationFrame API 来使整个画面动起来 —— 我们并不要求你事先学习过这些 API 的相关知识,希望你完成这个练习之后会想去探索更多。这个过程中我们会用到一些漂亮的小东西并向你展示一些技巧,比如小球从墙上反弹,检查它们是否撞到了对方 (也就是碰撞检测)。
+这个实例将会利用 Canvas API 来在屏幕上画小球,还会用到 requestAnimationFrame API 来使整个画面动起来 —— 我们并不要求你事先学习过这些 API 的相关知识,希望你完成这个练习之后会想去探索更多。这个过程中我们会用到一些漂亮的小东西并向你展示一些技巧,比如小球从墙上反弹,检查它们是否撞到了对方(也就是碰撞检测)。
让我们开始吧
@@ -197,11 +197,11 @@让我们开始吧
const width = canvas.width = window.innerWidth; const height = canvas.height = window.innerHeight; -这个脚本使用变量代指了
+<canvas>
元素, 然后对其调用getContext()
从而我们获得一个开始画画的环境。存储以上操作结果的变量(ctx
)是一个对象,直接代指画布上的一块允许我们绘制 2D 图形的区域。这个脚本使用变量代指了
<canvas>
元素,然后对其调用getContext()
从而我们获得一个开始画画的环境。存储以上操作结果的变量(ctx
)是一个对象,直接代指画布上的一块允许我们绘制 2D 图形的区域。接下来,我们设置
-width
和height
变量,并且让画布元素的宽和高(分别使用canvas.width
和canvas.height
表示)等于浏览器的宽和高(也就是网页显示的区域 — 可以从 {{domxref("Window.innerWidth")}} 和 {{domxref("Window.innerHeight")}}参数获得)。你会看到我们在这里串联了多个赋值表达式在一起,这样能更快地设置变量——这是完全正确的。
+你会看到我们在这里串联了多个赋值表达式在一起,这样能更快地设置变量——这是完全正确的。
原始脚本最后的部分如下:
@@ -234,7 +234,7 @@为程序中的小球建立模型
这个构造器中定义了每个小球需要的参数:-
- +
x
和y
坐标 —— 小球在屏幕上最开始时候的坐标。坐标的范围从 0 (左上角)到浏览器视口的宽和高(右下角)。x
和y
坐标 —— 小球在屏幕上最开始时候的坐标。坐标的范围从 0(左上角)到浏览器视口的宽和高(右下角)。- 水平和竖直速度(
velX
和velY
)—— 我们会给每个小球一个水平和竖直速度。实际上,当我们让这些球开始运动时候,每过一帧都会给小球的x
和y
坐标加一次这些值。color
—— 每一个小球会有自己的颜色。- @@ -310,22 +310,22 @@
size
—— 每一个小球会有自己的大小 — 也就是小球的半径,以像素为单位。更新小球的数据
this.y += this.velY; } -函数的前四个部分用来检查小球是否碰到画布的边缘。如果碰到,我们反转小球的速度方向来让它向反方向移动。就比如说,如果小球正向上移动 (正
+velY
),然后垂直速度发生改变,小球就向下移动 (负velY
)。函数的前四个部分用来检查小球是否碰到画布的边缘。如果碰到,我们反转小球的速度方向来让它向反方向移动。就比如说,如果小球正向上移动(正
velY
),然后垂直速度发生改变,小球就向下移动(负velY
)。在这四部分中,我们:
- 检查小球的
-x
坐标是否大于画布的宽度(小球会从右边缘离开)。- 检查小球的
+x
坐标是否小于0(小球会从左边缘离开)。- 检查小球的
x
坐标是否小于 0(小球会从左边缘离开)。- 检查小球的
-y
坐标是否大于画布的高度(小球会从下边缘离开)。- 检查小球的
+y
坐标是否小于0(小球会从上边缘离开)。- 检查小球的
y
坐标是否小于 0(小球会从上边缘离开)。在每种情况下,我们都会加上小球的半径,因为
x
/y
坐标是小球中心的坐标,我们希望小球在其边界接触浏览器窗口的边界时反弹,而不是小球的一部分都不见了再返回。最后两行,我们将
-velX
的值加到x
的坐标上,将velY
的值加到y
坐标上 —— 每次调用这个方法的时候小球就移动这么多。暂时先这样做; 让我们继续做一些动画!
+暂时先这样做;让我们继续做一些动画!
让球动起来
@@ -387,7 +387,7 @@添加碰撞检测
现在会更加有趣,给我们的项目加上碰撞检测,从而小球会知道他们正在撞击其他的球。
-
- 首先在
update()
方法后添加以下方法 (即Ball.prototype.update
的下面)。 +- 首先在
update()
方法后添加以下方法(即Ball.prototype.update
的下面)。Ball.prototype.collisionDetect = function() { for (let j = 0; j < balls.length; j++) { @@ -424,19 +424,19 @@添加碰撞检测
概要
-我们希望你玩得开心,编写出你自己的随机弹跳球的例子,在整个程序中使用各种对象和面向对象的技术! 在你实际运用对象中能提供一些有用的帮助。
+我们希望你玩得开心,编写出你自己的随机弹跳球的例子,在整个程序中使用各种对象和面向对象的技术!在你实际运用对象中能提供一些有用的帮助。
对象文章就到这里了。现在剩下的就是在下一节的对象评估中测试你的技能。
另请参阅
-
- Canvas tutorial —— 2D canvas 初学者指南.
+- Canvas tutorial —— 2D canvas 初学者指南。
- requestAnimationFrame()
- 2D 碰撞检测
- 3D 碰撞检测
-- 纯 JavaScript 编写的 2D 消除游戏 —— 一个很好的2D游戏开发初学者教程.
-- Phaser 编写的 2D 消除游戏 —— JavaScript游戏库构建2D游戏的基础知识。
+- 纯 JavaScript 编写的 2D 消除游戏 —— 一个很好的 2D 游戏开发初学者教程。
+- Phaser 编写的 2D 消除游戏 —— JavaScript 游戏库构建 2D 游戏的基础知识。
{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}}
diff --git a/files/zh-cn/learn/javascript/objects/object_prototypes/index.html b/files/zh-cn/learn/javascript/objects/object_prototypes/index.html index f28d4ec8b21e53..480fdc35e08f0a 100644 --- a/files/zh-cn/learn/javascript/objects/object_prototypes/index.html +++ b/files/zh-cn/learn/javascript/objects/object_prototypes/index.html @@ -17,11 +17,11 @@
- 预备知识: -基本的计算机素养,对 HTML 和 CSS 有基本的理解,熟悉 JavaScript 基础(参见 First steps 和 Building blocks)以及面向对象的JavaScript (OOJS) 基础(参见 Introduction to objects)。 +预备知识: +基本的计算机素养,对 HTML 和 CSS 有基本的理解,熟悉 JavaScript 基础(参见 First steps 和 Building blocks)以及面向对象的 JavaScript (OOJS) 基础(参见 Introduction to objects)。 - @@ -31,19 +31,19 @@目标: +目标: 理解 JavaScript 对象原型、原型链如何工作、如何向 prototype
属性添加新的方法。基于原型的语言?
JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。
-准确地说,这些属性和方法定义在Object的构造器函数(constructor functions)之上的
+prototype
属性上,而非对象实例本身。准确地说,这些属性和方法定义在 Object 的构造器函数 (constructor functions) 之上的
prototype
属性上,而非对象实例本身。在传统的 OOP 中,首先定义“类”,此后创建对象实例时,类中定义的所有属性和方法都被复制到实例中。在 JavaScript 中并不如此复制——而是在对象实例和它的构造器之间建立一个链接(它是__proto__属性,是从构造函数的
prototype
属性派生的),之后通过上溯原型链,在构造器中找到这些属性和方法。-注意: 理解对象的原型(可以通过
+Object.getPrototypeOf(obj)
或者已被弃用的__proto__
属性获得)与构造函数的prototype
属性之间的区别是很重要的。前者是每个实例上都有的属性,后者是构造函数的属性。也就是说,Object.getPrototypeOf(new Foobar())
和Foobar.prototype
指向着同一个对象。注意:理解对象的原型(可以通过
Object.getPrototypeOf(obj)
或者已被弃用的__proto__
属性获得)与构造函数的prototype
属性之间的区别是很重要的。前者是每个实例上都有的属性,后者是构造函数的属性。也就是说,Object.getPrototypeOf(new Foobar())
和Foobar.prototype
指向着同一个对象。以上描述很抽象;我们先看一个例子。
-使用Javascript中的原型
+使用 Javascript 中的原型
-在javascript中,函数可以有属性。 每个函数都有一个特殊的属性叫作
+原型(prototype)
,正如下面所展示的。请注意,下面的代码是独立的一段(在网页中没有其他代码的情况下,这段代码是安全的)。为了最好的学习体验,你最好打开一个控制台 (在Chrome和Firefox中,可以按Ctrl+Shift+I来打开)切换到"控制台" 选项卡, 复制粘贴下面的JavaScript代码,然后按回车来运行.在 javascript 中,函数可以有属性。每个函数都有一个特殊的属性叫作
原型(prototype)
,正如下面所展示的。请注意,下面的代码是独立的一段 (在网页中没有其他代码的情况下,这段代码是安全的)。为了最好的学习体验,你最好打开一个控制台 (在 Chrome 和 Firefox 中,可以按 Ctrl+Shift+I 来打开) 切换到"控制台" 选项卡,复制粘贴下面的 JavaScript 代码,然后按回车来运行。function doSomething(){} console.log( doSomething.prototype ); @@ -54,7 +54,7 @@-使用Javascript中的原型
console.log( doSomething.prototype );正如上面所看到的,
+doSomething
函数有一个默认的原型属性,它在控制台上面呈现了出来. 运行这段代码之后,控制台上面应该出现了像这样的一个对象.正如上面所看到的,
doSomething
函数有一个默认的原型属性,它在控制台上面呈现了出来。运行这段代码之后,控制台上面应该出现了像这样的一个对象。{ constructor: ƒ doSomething(), @@ -69,14 +69,14 @@-使用Javascript中的原型
} }现在,我们可以添加一些属性到 doSomething 的原型上面,如下所示.
+现在,我们可以添加一些属性到 doSomething 的原型上面,如下所示。
function doSomething(){} doSomething.prototype.foo = "bar"; console.log( doSomething.prototype );-结果:
+结果:
{ foo: "bar", @@ -95,7 +95,7 @@使用Javascript中的原型
-
然后,我们可以使用 new 运算符来在现在的这个原型基础之上,创建一个
+doSomething
的实例。正确使用 new 运算符的方法就是在正常调用函数时,在函数名的前面加上一个new
前缀. 通过这种方法,在调用函数前加一个new
,它就会返回一个这个函数的实例化对象. 然后,就可以在这个对象上面添加一些属性. 看.然后,我们可以使用 new 运算符来在现在的这个原型基础之上,创建一个
doSomething
的实例。正确使用 new 运算符的方法就是在正常调用函数时,在函数名的前面加上一个new
前缀。通过这种方法,在调用函数前加一个new
,它就会返回一个这个函数的实例化对象。然后,就可以在这个对象上面添加一些属性。看。function doSomething(){} doSomething.prototype.foo = "bar"; // add a property onto the prototype @@ -105,7 +105,7 @@-使用Javascript中的原型
-
结果:
+结果:
@@ -126,7 +126,7 @@
使用Javascript中的原型
} }就像上面看到的,
+doSomeInstancing
的__proto__
属性就是doSomething.prototype
. 但是这又有什么用呢? 好吧,当你访问doSomeInstancing
的一个属性, 浏览器首先查找doSomeInstancing
是否有这个属性. 如果doSomeInstancing
没有这个属性, 然后浏览器就会在doSomeInstancing
的__proto__
中查找这个属性(也就是 doSomething.prototype). 如果 doSomeInstancing 的__proto__
有这个属性, 那么 doSomeInstancing 的__proto__
上的这个属性就会被使用. 否则, 如果 doSomeInstancing 的__proto__
没有这个属性, 浏览器就会去查找 doSomeInstancing 的__proto__
的__proto__
,看它是否有这个属性. 默认情况下, 所有函数的原型属性的__proto__
就是window.Object.prototype
. 所以 doSomeInstancing 的__proto__
的__proto__
(也就是 doSomething.prototype 的__proto__
(也就是Object.prototype
)) 会被查找是否有这个属性. 如果没有在它里面找到这个属性, 然后就会在 doSomeInstancing 的__proto__
的__proto__
的__proto__
里面查找. 然而这有一个问题: doSomeInstancing 的__proto__
的__proto__
的__proto__
不存在. 最后, 原型链上面的所有的__proto__
都被找完了, 浏览器所有已经声明了的__proto__
上都不存在这个属性,然后就得出结论,这个属性是undefined
.就像上面看到的,
doSomeInstancing
的__proto__
属性就是doSomething.prototype
. 但是这又有什么用呢?好吧,当你访问doSomeInstancing
的一个属性,浏览器首先查找doSomeInstancing
是否有这个属性。如果doSomeInstancing
没有这个属性,然后浏览器就会在doSomeInstancing
的__proto__
中查找这个属性 (也就是 doSomething.prototype). 如果 doSomeInstancing 的__proto__
有这个属性,那么 doSomeInstancing 的__proto__
上的这个属性就会被使用。否则,如果 doSomeInstancing 的__proto__
没有这个属性,浏览器就会去查找 doSomeInstancing 的__proto__
的__proto__
,看它是否有这个属性。默认情况下,所有函数的原型属性的__proto__
就是window.Object.prototype
. 所以 doSomeInstancing 的__proto__
的__proto__
(也就是 doSomething.prototype 的__proto__
(也就是Object.prototype
)) 会被查找是否有这个属性。如果没有在它里面找到这个属性,然后就会在 doSomeInstancing 的__proto__
的__proto__
的__proto__
里面查找。然而这有一个问题:doSomeInstancing 的__proto__
的__proto__
的__proto__
不存在。最后,原型链上面的所有的__proto__
都被找完了,浏览器所有已经声明了的__proto__
上都不存在这个属性,然后就得出结论,这个属性是undefined
.function doSomething(){} doSomething.prototype.foo = "bar"; @@ -139,7 +139,7 @@-使用Javascript中的原型
console.log("doSomething.prototype.prop: " + doSomething.prototype.prop); console.log("doSomething.prototype.foo: " + doSomething.prototype.foo);结果:
+结果:
doSomeInstancing.prop: some value doSomeInstancing.foo: bar @@ -180,8 +180,8 @@理解原型对象
- 浏览器首先检查,
-person1
对象是否具有可用的valueOf()
方法。- 如果没有,则浏览器检查
-person1
对象的原型对象(即Person
构造函数的prototype属性所指向的对象)是否具有可用的valueof()
方法。- 如果也没有,则浏览器检查
+Person()
构造函数的prototype属性所指向的对象的原型对象(即Object
构造函数的prototype属性所指向的对象)是否具有可用的valueOf()
方法。这里有这个方法,于是该方法被调用。- 如果没有,则浏览器检查
+person1
对象的原型对象(即Person
构造函数的 prototype 属性所指向的对象)是否具有可用的valueof()
方法。- 如果也没有,则浏览器检查
Person()
构造函数的 prototype 属性所指向的对象的原型对象(即Object
构造函数的 prototype 属性所指向的对象)是否具有可用的valueOf()
方法。这里有这个方法,于是该方法被调用。@@ -189,7 +189,7 @@理解原型对象
-注意:没有官方的方法用于直接访问一个对象的原型对象——原型链中的“连接”被定义在一个内部属性中,在 JavaScript 语言标准中用
+[[prototype]]
表示(参见 {{glossary("ECMAScript")}})。然而,大多数现代浏览器还是提供了一个名为__proto__
(前后各有2个下划线)的属性,其包含了对象的原型。你可以尝试输入person1.__proto__
和person1.__proto__.__proto__
,看看代码中的原型链是什么样的!注意:没有官方的方法用于直接访问一个对象的原型对象——原型链中的“连接”被定义在一个内部属性中,在 JavaScript 语言标准中用
[[prototype]]
表示(参见 {{glossary("ECMAScript")}})。然而,大多数现代浏览器还是提供了一个名为__proto__
(前后各有 2 个下划线)的属性,其包含了对象的原型。你可以尝试输入person1.__proto__
和person1.__proto__.__proto__
,看看代码中的原型链是什么样的!prototype 属性:继承成员被定义的地方
@@ -245,7 +245,7 @@prototype 属性:
constructor 属性
-每个实例对象都从原型中继承了一个constructor属性,该属性指向了用于构造此实例对象的构造函数。
+每个实例对象都从原型中继承了一个 constructor 属性,该属性指向了用于构造此实例对象的构造函数。
- 例如,在控制台中尝试下面的指令: diff --git a/files/zh-cn/learn/javascript/objects/test_your_skills_colon__object-oriented_javascript/index.html b/files/zh-cn/learn/javascript/objects/test_your_skills_colon__object-oriented_javascript/index.html index 5e265fbbede6e4..0f82e1b2d62f8e 100644 --- a/files/zh-cn/learn/javascript/objects/test_your_skills_colon__object-oriented_javascript/index.html +++ b/files/zh-cn/learn/javascript/objects/test_your_skills_colon__object-oriented_javascript/index.html @@ -1,5 +1,5 @@ --- -title: 测试你的技能:面向对象的Javascript +title: 测试你的技能:面向对象的 Javascript slug: Learn/JavaScript/Objects/Test_your_skills:_Object-oriented_JavaScript tags: - JavaScript @@ -13,7 +13,7 @@ ---
{{learnsidebar}}- +