Javascript 变量在函数外部变得未定义

Javascript 变量在函数外部变得未定义,javascript,leaflet,Javascript,Leaflet,因此,我一直在使用moulate.js创建我家乡州疫苗接种站点的地图,并试图使用路由查找离用户最近的站点,但当我登录或尝试在函数外部调用该变量时,该变量不知何故变得未定义。我对js比较陌生,在python中使用folium时了解了传单。在python中,我认为您应该声明您正在更改一个全局变量,或者更好地使用return,但我不确定如何使用js和传单库实现这一点 var self_lat; var self_long; ... var mymap = L.map('mapid').setView(

因此,我一直在使用moulate.js创建我家乡州疫苗接种站点的地图,并试图使用路由查找离用户最近的站点,但当我登录或尝试在函数外部调用该变量时,该变量不知何故变得未定义。我对js比较陌生,在python中使用folium时了解了传单。在python中,我认为您应该声明您正在更改一个全局变量,或者更好地使用return,但我不确定如何使用js和传单库实现这一点

var self_lat;
var self_long;
...
var mymap = L.map('mapid').setView([34.7465, -92.2896], 6);
...
function onLocationFound(e) {
    console.log(e);
    self_lat =  e.latitude;
    self_long = e.longitude;
    L.marker([e.latitude, e.longitude], {icon: home_marker}).bindPopup("YOU ARE HERE!").addTo(mymap);
    console.log(typeof(e.latitude))
    console.log(typeof(e.longitude))
}

function onLocationError(e) {
    alert(e.message);
}
mymap.locate({setView: false, maxZoom: 16});
mymap.on('locationfound', onLocationFound);
mymap.on('locationerror', onLocationError);

...
L.Routing.control({
waypoints: [
L.latLng([self_lat, self_long]),
L.latLng([34.7465, -92.2896])
]
}).addTo(mymap);

如果
self\u lat
self\u long
不是全局变量,则通过仅传递
onLocationFound
的原型,正在
mymap
的上下文中调用该函数,而这些变量不存在,要解决此问题并将回调作为一个单独的函数,可以按如下方式调用它:

mymap.on('locationfound', (e) => onLocationFound(e));

要理解这里的问题,请在调用
L.Routing.control()
之前添加一个
console.log('Calling L.Routing.control()',self\u lat,self\u long)
调用(代码列表中有

你会注意到两件事:

  • 如您所知,
    self\u lat
    self\u long
    将在此处
    未定义。但是为什么呢
  • 您还将看到,在现有的
    console.log()
    调用之前调用了这个新的
    console.log()
    ,您可以在
    onLocationFound
    函数中记录这些值。这就是问题的根源
  • 与其他JavaScript库和本机JavaScript本身中的许多类似函数一样,传单的
    myMap.on(eventName,eventListener)
    函数是异步的。这意味着不会立即调用
    eventListener
    ——在本例中,
    onLocationFound
    。在
    myMap.on()
    调用本身返回后的某个时间调用它

    JavaScript中的所有异步回调/侦听器函数都是这样工作的。设置全局代码很少有用,因为问题是当各种代码位运行时

    在不了解其余代码的情况下,我可能建议的一种可能的修复方法是完全去掉
    self\u lat
    self\u long
    变量,并将
    L.Routing.control()
    调用移动到
    onLocationFound
    函数中,如下所示:

    var mymap=L.map('mapid').setView([34.7465,-92.2896],6);
    ...
    函数onLocationFound(e){
    控制台日志(e);
    L.标记(
    [e.纬度,e.经度],
    {图标:主标记}
    ).bindpoppop(“您在这里!”).addTo(mymap);
    路由控制({
    航路点:[
    L.纬度([e.纬度,e.经度],
    L.latLng([34.7465,-92.2896])
    ]
    }).addTo(mymap);
    }
    函数onLocationError(e){
    警报(e.message);
    }
    locate({setView:false,maxZoom:16});
    mymap.on('locationfound',onLocationFound);
    mymap.on('locationerror',onLocationError);
    
    下面是一个非常简单的例子,有助于说明。我们进行一个
    setTimeout()
    调用和三个
    console.log()
    调用:一个在回调之前,一个在回调之后,一个在回调内部。单击下面的运行按钮并记下日志消息的顺序:

    console.log('Before setTimeout');
    设置超时(
    函数(){
    log('Inside setTimeout callback');
    },
    1//1毫秒延迟
    );
    
    log('After setTimeout returns')
    map.on('locationFound',onLocationFound){…
    在这里的语法不正确。要么提供回调处理程序,要么提供回调函数,但你不能同时做这两件事。你能解释一下吗?你已经编辑了代码,所以你只提供了一个处理程序-这是一种方法(应该可以正常工作)。另一种方法是使用内联函数执行类似的操作(使用“箭头函数”):
    mymap.on('locationfound',()=>{/*dostuff here*/});
    在当前状态下不起作用。当我当前运行它时,它说self_lat和self_long仍然未定义。我尝试过它,但它似乎不起作用。当我当前运行它时,它说self_lat和self_long仍然未定义。嗯,奇怪,这意味着您的变量实际上是在不同的上下文中声明的,而不是您所处的上下文对映射进行判断,您是否使用任何框架来执行此操作,或者它只是一个普通的javascript文件?思考……您的问题可能与回调无关,但在L.路由部分,这可能是一个无辜的问题,在声明它们时,只需尝试为self_lat和self_long分配一个默认值,例如:var self_lat=0;var self_long=0;是的,发生的是值不会改变。啊,好的,谢谢。有什么方法可以使它同步或以其他方式保存它吗?我想使用路由控制来找到从您的位置到所有接种位置的距离和时间,并绘制最佳位置。JavaScript确实有办法发出远程请求就像这个同步的,但我不知道这个传单API是否支持它。无论如何,你不应该使用它,因为它会在等待服务器响应时锁定整个浏览器:如果服务器没有响应,用户甚至无法关闭页面。有一种方法可以让JavaScript代码感觉更像用Python编写的同步代码:
    async
    /
    wait
    。如果传单映射的
    on
    方法返回一个
    Promise
    ,这将非常容易实现。我仍然建议您熟悉老式技术,在事件侦听器函数中(或在调用的函数中,无论哪种方式,都是一样的)执行所有操作,因为它将有助于理解异步代码是如何工作的。