【问题标题】:Last defined prototype function always runs on object initialization最后定义的原型函数总是在对象初始化时运行
【发布时间】:2013-11-07 19:00:56
【问题描述】:

鉴于以下代码 (StoriesMap.js)...

// Initalization; Creates Map
var StoriesMap = function StoriesMap( id, location, tileset ) {
    this.map = L.map( id ).setView([ location.lat, location.lon ], location.zoom);

    // Add inital points to map
    this.populate( location );

    // Redraw on map movement
    this.map.on("viewreset", function( event ) {
        var location = {
            lat: event.target._animateToCenter.lat,
            lon: event.target._animateToCenter.lng,
            zoom: event.target._animateToZoom
        };

        this.redraw( location );
    });

    var mapTiles = L.tileLayer( tileset.url, { attribution: tileset.attribution, minZoom: 4, maxZoom: 12 } ).addTo( this.map );
}


// Put some points on the map
StoriesMap.prototype.populate = function populate( location ) {
    var priority = location.zoom - 3;

    if ( typeof points === "object" ) {
        var buffer = [];

        for ( var i in points ) {
            var point = points[i];

            if ( point.priority <= priority ) {
                var circle = L.circle([ point.lat, point.lon ], 100000, {
                    color: '#f03', fillColor: '#f03', fillOpacity: 0.5
                }).addTo( this.map );
            }
        }
    }

}

// Filters map contents
StoriesMap.prototype.filter = function filter( map, location ) {
    console.log( "filter" );
}

// Redraws map points
StoriesMap.prototype.redraw = function redraw( map, location ) {
    console.log ( this.map )

    for ( var i in map._layers ) {
        if ( map._layers[i]._path != undefined ) {
            try {
                map.removeLayer( map._layers[i] );
            }
            catch(e) {
                console.log("problem with " + e + map._layers[i]);
            }
        }
    }
}

StoriesMap.prototype.fake = function fake() {
    console.log("Always Called when object is Initialized");
}

当我运行时(从我的 html 中):

 var map = new Map();

我总是得到:

Always Called when object is Initialized

在我的控制台中。无论出于何种原因,我最后定义的原型被视为构造函数,我不确定为什么。我不希望在初始化对象时运行该函数,是否假定它是构造函数?我以前也遇到过这种情况,我的正常反应是创建一个名为“fake”的最后一个原型函数并将其留空,但是这个问题的正确解决方案是什么?

【问题讨论】:

  • 告诉我们/* code */。我无法重现那个。 jsfiddle.net/SLaks/arMV3
  • 以后有流浪()吗?
  • 所以您告诉我们,仅使用该代码,您就可以记录消息?诚实地? SSCCE @SLaks:好点。在最后一个原型方法之后可能有一个 IIFE。
  • 不,事实并非如此。可能还有一些其他代码调用了您的最后一个原型,所以请按照上面的要求向我们展示您的注释代码
  • @BlueSkies 我的意思是他描述的行为很奇怪,并不是没有发生(预期的)。

标签: javascript function object constructor prototype


【解决方案1】:

此代码在某些时候(可能在某种构建过程或缩小过程中)连接了其他代码。其他代码以带括号的语句开头:

StoriesMap.prototype.fake = function fake() {
    console.log("Always Called when object is Initialized");
}

// start of other code...
(...);

然而,JavaScript 将其解读为:

StoriesMap.prototype.fake = function fake() {
    console.log("Always Called when object is Initialized");
}(...);

所以StoriesMap.prototype.fake 不等于函数,而是立即调用函数,使用带括号的表达式作为参数。 StoriesMap.prototype.fake 设置为立即调用函数的返回值

只需在函数表达式的末尾加分号,就不会出现这种情况,因为括号内的语句和函数会用分号隔开:

StoriesMap.prototype.fake = function fake() {
    console.log("Always Called when object is Initialized");
};
(...);

JavaScript 的自动分号插入仅在缺少分号会导致违反语言语法时发生。与此类似的示例见底部ES 7.9.2

来源

a = b + c
(d + e).print()

不会被自动分号插入转换,因为第二行开始的带括号的表达式可以解释为函数调用的参数列表:

a = b + c(d + e).print()

在赋值语句必须以左括号开头的情况下,程序员最好在前面的语句末尾提供一个明确的分号,而不是依赖自动分号插入。

【讨论】:

  • 感谢您的澄清。进入 JS 多年,“自动分号插入”仍然令人困惑。
猜你喜欢
  • 2019-09-12
  • 2017-01-24
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多