为什么我不能将它作为变量传递给事件处理程序?

时间:2017-11-23 12:41:58

标签: javascript javascript-events this

我正在为一个类中的事件处理程序分配一个成员方法,我希望尽可能优雅地完成它。我认为这会起作用,但事实并非如此 - 为什么?

class MyMap{
    onMarkerClick(myMap, marker){
        // Do something with myMap and marker
    }

    init(){
        let newMarker = new google.maps.Marker({
            position: {lat: 0, lng: 0},
            map: this.map,
            title: 'New marker'
        });

        google.maps.event.addListener(newMarker, 'click', (function(myMap){ myMap.onMarkerClick(myMap, this); }(this)) );
    }
}    

“传统”self = this方法有效

class MyMap{
    onMarkerClick(myMap, marker){
        // Do something with myMap and marker
    }

    init(){
        let newMarker = new google.maps.Marker({
            position: {lat: 0, lng: 0},
            map: this.map,
            title: 'New marker'
        });

        var myMap = this;
        google.maps.event.addListener(newMarker, 'click', function(){ myMap.onMarkerClick(myMap, this); } );
    }
}

但我想避免那个讨厌的变量。如果我需要同时访问MyMap实例和google.maps.Marker实例,是否可以以其他方式完成?

2 个答案:

答案 0 :(得分:1)

首先,删除不必要的myMap参数 - 您使用class,以便当前对象 始终为this。将指向感兴趣对象的指针传递给属于同一对象的方法是一个很大的OOP" no-no",因为它隐含地为你完成了:

onMarkerClick(marker){
    // Do something with "this" and marker
}

完成后,您可以绑定事件监听器:

google.maps.event.addListener(newMarker, this.onMarkClick.bind(this, newMarker));

.bind调用的第一个参数将确保您当前的this实际上正确传递给事件处理程序(无论Google Maps API如何调用它)。

然后,第二个参数可让您访问标记。

利用ES6箭头功能的另一种方法" lexical this"是:

google.maps.event.addListener(newMarker, () => this.onMarkClick(newMarker));

答案 1 :(得分:-1)

由于您使用function关键字定义了一项功能,因此在定义时,它会在您的范围之外创建,这意味着this无法正常工作。

您可以使用() => {}定义来维持当前范围,但您不必使用self = this

google.maps.event.addListener(newMarker, 'click', () => { myMap.onMarkerClick(myMap, this); } );