在从 API 获取数据之前使用 Javascript 中的变量

Use variables in Javascript before the data is fetched from an API

有这段javascript代码(来自神奇的CodingTrain系列!!):

我的问题如下:

我们在第 28 行将数据对象传递给 fetch-Post 请求。首先在第 17 行声明了两个变量 lat 和 lon,但没有初始化。然后它们被用于构建第 20 行中的数据对象最终传递到第 28 行中的获取函数。

我不明白的是这两个变量如何保存代码中已有的地理位置值。因为我们仅在下面的第 35-40 行中获取地理位置。这可能与异步和等待逻辑的工作方式有关,但我不确定。

01: <!DOCTYPE html>
02: <html lang="en">
03:   <head>
04:     <meta charset="UTF-8" />
05:     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
06:     <meta http-equiv="X-UA-Compatible" content="ie=edge" />
07:     <title>Document</title>
08:   </head>
09:   <body>
10:     <h1>Data Selfie App</h1>
11:     <p>
12:       latitude: <span id="latitude"></span>&deg;<br />
13:       longitude: <span id="longitude"></span>&deg;
14:     </p>
15:     <button id="submit">submit</button>
16:     <script>
17:       let lat, lon;
18:       const button = document.getElementById('submit');
19:       button.addEventListener('click', async event => {
20:         const data = { lat, lon };
21:         const options = {
22:           method: 'POST',
23:           headers: {
24:             'Content-Type': 'application/json'
25:           },
26:           body: JSON.stringify(data)
27:         };
28:         const response = await fetch('/api', options);
29:         const json = await response.json();
30:         console.log(json);
31:       });
32: 
33:       if ('geolocation' in navigator) {
34:         console.log('geolocation available');
35:         navigator.geolocation.getCurrentPosition(async position => {
36:           lat = position.coords.latitude;
37:           lon = position.coords.longitude;
38:           document.getElementById('latitude').textContent = lat;
39:           document.getElementById('longitude').textContent = lon;
40:         });
41:       } else {
42:         console.log('geolocation not available');
43:       }
44:     </script>
45:   </body>
46: </html>

github 回购的 link 是这样的:https://github.com/CodingTrain/Intro-to-Data-APIs-JS

他们的教程没有解释变量和变量作用域吗?

基本上当你有这样的代码时:

let someVar;
function a() {}
const someFunc = () => someVar;
// ...

因为 a(和 someFunc)在他们有权访问 someVar 时被定义,他们现在保持对该变量的永久访问权。

在您的情况下,let lat, lon; 下面的所有函数声明都可以随时读取和写入这些变量。 getCurrentPosition 最终 将值写入这些变量,然后供 'click' 侦听器使用。如果您足够快地成功按下按钮,在 getCurrentPosition 完成之前 (或者如果 navigator 不可用)lat/lon 仍然是 undefined.

另一个例子:

const funcs = [];
for (let i = 0; i < 3; i++) {
    funcs.push(() => i);
}
console.log(funcs.map(f => f()));

在循环中我创建了 3 个函数(i01 然后是 2)。后来我打电话给他们。即使 i 的作用域(for-循环的主体)结束并且变量“死了”,函数仍然可以访问它们,因为它们是在变量仍然存在并且可以访问时声明的他们。另请注意,每个函数如何访问 只是 声明时处于活动状态的 i 变量,而不是 earlier/later 迭代中的 i

19和31之间的代码:

button.addEventListener('click', async event => {
    // ...
});

... 将回调附加到事件。该回调将不会执行 now。它是将来会执行的代码,即当用户单击按钮时。

您可以将此代码块移动到第 44 行,它不会对代码逻辑有任何改变。

你可以在这个简化的代码中看到原理——一键式(点击它):

let button = document.querySelector("button");
let i = 0;

button.addEventListener("click", function () {
    console.log("i =", i);
});

i = 10; // This executes first!
<button>Click me</button>