无法访问变量外部函数

时间:2013-03-20 19:43:05

标签: javascript global-variables closures

我有以下JS:

Meteor.startup(function () {
  map = L.map('map_canvas').locate({setView: true, maxZoom: 21});
  L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
      attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
  }).addTo(map);
    bounds = {};    
    map.on('locationfound', function(e){ 
      bounds.bottomLeftLat = map.getBounds()._southWest.lat;
      bounds.bottomLeftLng = map.getBounds()._southWest.lng;
      bounds.topRightLat = map.getBounds()._northEast.lat;
      bounds.topRightLng = map.getBounds()._northEast.lng;
      console.log(bounds);
    });
  console.log('outside function: '+bounds);
});

我的第一个console.log在控制台中正确输出4个对象属性及其值,但是外部函数日志输出一个空对象,当我尝试访问Meteor.startup之外的边界时,它不是甚至定义。我理解函数限制了变量的范围,但是如果在匿名函数之外定义了边界,没有&#39; var&#39;,它是不是被认为是全局的?

  1. 为什么我可以访问&#39; map&#39;但不是&#39;界限&#39;在Meteor.startup之外?
  2. 如何通过遵循更多智能模式(模块?)来重写此代码,以便我可以在脚本的其他部分中创建边界并在我尝试时成功添加四个属性?
  3. 编辑事件被触发 - 手动触发后,我仍然得到一个空对象:

    map.fire("locationfound");
    Object {type: "locationfound", target: e, bottomLeftLat: 50.05008477838258, bottomLeftLng: 0.384521484375, topRightLat: 51.63847621195153…}
     MainClient.js:12
    e {options: Object, _container: div#map_canvas.leaflet-container leaflet-fade-anim, _panes: Object, _mapPane: div.leaflet-map-pane, _tilePane: div.leaflet-tile-pane…}
    bounds
    Object {}
    

2 个答案:

答案 0 :(得分:2)

看到boundsconsole.log发生在locationfound事件的回调之前,所以当您尝试访问它时它仍为空。

所有初始化都会在locationfound事件第一次触发时发生,此时的日志将显示您期望的结果。

一些想法。

  1. 一般来说,声明没有var的变量是不受欢迎的。如果要全局访问它,请在全局上下文中使用var声明它,或者(理想情况下)使用命名空间变量并将所有全局变量声明为该属性。

  2. 如果要在修改后访问边界,可以调用要在回调中运行的函数

  3. 更新以澄清代码的行为

    以下是代码的执行方式。

    //This is the startup function for meteor.  It is passed a function, 
    //and executes that function when the code starts up
    Meteor.startup(function () {
        //You're now inside the function you passed to startup, and you initialize map
        //...
        bounds = {};    
        //here you call the `on` function on map, and bind a 
        //callback function to the locationfound event
        map.on('locationfound', function(e){ 
          //This code is inside the callback and will be executed when the event occurs 
    
          // code initializing bounds
    
          console.log(bounds); //this will show the full definition of bounds
          //callback ends here
        });
      //this is outside the callback but still inside startup, 
      //and occurs immediately after the call to map.on
      console.log('outside function: '+bounds); //bounds is still empty
    }); //end the startup function
    

    您需要了解的关键是on功能。它是一个传单函数,它接受2个参数,一个事件类型和一个回调函数,并将回调函数绑定到事件。然后回调函数在事件发生时运行,而不是之前运行。回调不会立即运行。而是代码继续执行,并在事件发生时执行回调代码。

    Documentation for on

答案 1 :(得分:1)

这就叫javascript event loop 'map'之外的代码可以访问bounds var但是你在defince mapfound事件后立即尝试访问它 - 这个边界只会在这个事件发生时初始化 - 所以你在控制台得到的只是您在“bounds =”{}“

之前定义的空对象

你所做的是正确的 - 你只能在locationfound事件中访问边界,因为只有你初始化它