【问题标题】:Javascript Object Literal Scope Issue?Javascript对象文字范围问题?
【发布时间】:2012-05-10 01:27:13
【问题描述】:

我很难理解为什么 this.$mapthis.markers 未定义。这是我正在使用的代码,我添加了 cmets,我希望这些变量提供一个值:

(function($) {
    'use strict';

    var A = {

        /**
         * Initialize the A object
         */
        init: function() {
            this.$map = this.renderMap();
            this.markers = this.getMarkers();

            this.renderMarkers();
        },

        renderMap: function() {

            var url = 'http://a.tiles.mapbox.com/v3/delewis.map-i3eukewg.jsonp';

            // Get metadata about the map from MapBox
            wax.tilejson(url, function(tilejson) {
                var map = new L.Map('map', {zoomControl: false});

                var ma = new L.LatLng(42.2625, -71.8028);

                map.setView(ma, 8);

                // Add MapBox Streets as a base layer
                map.addLayer(new wax.leaf.connector(tilejson));

                return function() {
                    return map;
                };
            });
        },

        renderMarkers: function() {
            var geojsonLayer = new L.GeoJSON(null, {
                pointToLayer: function (latlng){
                    return new L.CircleMarker(latlng, {
                        radius: 8,
                        fillColor: "#ff7800",
                        color: "#000",
                        weight: 1,
                        opacity: 1,
                        fillOpacity: 0.8
                    });
                }
            });

            geojsonLayer.addGeoJSON(this.markers); // this.markers is undefined
            this.$map.addLayer(geojsonLayer); // this.$map is undefined

        },

        getMarkers: function() {
            $.getJSON("/geojson/", function (data) {
                return data;
            });
        }
    };

    /**
     * A interactions
     */
    $(document).ready(function() {
        A.init()
    });

})(jQuery.noConflict());

我花了一天的大部分时间搜索,我认为我在这里遗漏了一些基本的东西,但我不明白。

【问题讨论】:

  • 因为您不能(可以说不应该)从 Ajax 调用返回值... Ajax 默认是异步。如果可以直接返回值,为什么还要传递回调?请阅读jQuery: Return data after ajax call success。这部分是范围问题,但主要是时间问题。
  • 看看getMarkers。该函数不返回值。您传递给$.getJSON 的回调确实如此,但该回调由(内部)$.getJSON 执行,因此它将值返回给$.getJSON,而不是调用getMarkers 的函数。此外,当收到响应并且当时getMarkers 已经完成(返回undefined)时,将执行回调。从字面上看(我假设)这里有成千上万个问题都是关于同一个问题的。
  • 必须有数千个,很容易。有一天,我在几个小时内统计了 8 个新的“异步事物不返回值”问题。假设每天发布大约 8 个这样的帖子,那么到目前为止,在网站的整个生命周期内,这将是大约 3 万个。
  • @GGG,我没有意识到这两种情况都是 ajax 调用。我傻吗?是的,它让我找错地方了。
  • @MarkLewis 您将回调传递给名称中带有“json”的函数这一事实应该是一个很大的暗示,即您正在调用的函数是异步的,并且您正在返回的事实来自回调的事情应该是一个危险信号。

标签: javascript jquery scope


【解决方案1】:

renderMapgetMarkers 方法都没有返回任何值,因此它们的返回值是 undefined

您似乎正在尝试从 ajax 请求初始化这些字段,这不一定是个好主意。

你可能应该做的是:

getMarkers: function(callback){
    var result = this;
    $.getJSON("url", function(jsonData){ 
        result.markers = jsonData; 
        if(callback) callback()
     });
},

这将在对象的字段可用时延迟初始化。

注意:AJAX 是异步,您不能依赖此回调快速设置成员,甚至永远不能(它可能会失败)。 这表明您需要对您的设计进行更多思考,并尝试更多地使用回调。

例如修改上面的getMarkersrenderMap 函数以获取在数据存储后调用的回调,然后将init更改为:

init: function(){
    var res = this;
    var post_init_callback = function(){
        if(res.$map != undefined && res.markers!=undefined){
            //this will only run after both ajax calls are complete
            res.renderMarkers();  
        }
    };
    this.getMarkers(post_init_callback);
    this.renderMap(post_init_callback);
},

【讨论】:

  • 所以我应该利用回调来处理数据,而不是尝试将数据返回给变量?在renderMap() 的情况下我如何返回map
  • 在渲染图的顶部添加var result = this;,并将return map也更改为result.$map = map;,查看我的编辑
  • 哇,你的评论让我意识到wax.tilejson 是一个ajax 调用。现在我明白了,我以为我有两种不同的情况。谢谢!
【解决方案2】:

这里的问题是你在另一个函数中调用了 return。您实际上所做的是将getMarkers(最简单的示例)定义为:

getMarkers: function() {
    $.getJSON('/geojson/', some_random_func);
}

此时 getMarkers 实际上并没有返回任何东西(ergo undefined)变得很明显。您的 renderMap 函数也是如此。同样在这种情况下,您的“some_random_func”被定义为function(data) { return data; },但它会将它返回到什么位置?事实上,some_random_func 是由 jQuery 本身调用的,AFAIK jQuery 根本不关心它的成功函数的返回值。

【讨论】:

  • 不是将数据返回给A.init()中的this.markers吗(即this.markers = this.getMarkers();)?
  • @Mark:函数getMarkers没有return语句,它怎么能返回任何东西?也许您对在getMarkers 中定义的函数感到困惑...该函数返回的值并不是由getMarkers 神奇地返回的(可能存在这种情况,但在JavaScript 中不是这样)。你可以做一个简单的测试:function foo() { function bar() { return 'bar';} bar(); }; alert(foo());给你什么?
  • @Felix,您的 cmets 帮助,谢谢。现在我只需要了解解决方案。
猜你喜欢
  • 1970-01-01
  • 2022-12-17
  • 2013-04-01
  • 2012-05-29
  • 2016-08-28
  • 1970-01-01
  • 1970-01-01
  • 2011-04-09
  • 1970-01-01
相关资源
最近更新 更多