如何测试directionsServiceService请求对象的相等性

时间:2013-09-28 20:11:25

标签: javascript jquery google-maps-api-3

我正在使用Google Maps API v3,我希望将我所做的API请求数量减少到最低限度。

对我来说,存储最后一个请求并测试下一个请求是否等于最后一个是有意义的,如果为真则忽略它:

var request = {
    origin: "John O'Groats",
    destination: "Land's End",
    waypoints: [{
        location: "Penrith",
        stopover: true
    }],
    travelMode: google.maps.DirectionsTravelMode.DRIVING
};
// Dont make a new request if same as last
if (request !== lastRequest) {
    lastRequest = request;
    directionsService.route(request, function(response, status) {

            ...

    }
}

以上没有用。

所以我尝试了JSON.stringify

if (JSON.stringify(request) !== JSON.stringify(lastRequest)) {

仍然没有骰子。

然后我尝试了underscore.js isEqual函数:

if (!_.isEqual(request, lastRequest)) {

再次无法工作。

以上所有都会返回错误的结果。我猜是因为wptsrequest对象中的另一个对象。

如何在javascript中测试这两个对象的相等性?

解决方案

Beetroot-Beetroot的回答让我走上正轨

  

因为只有一个对象然后尝试比较lastRequest   请求将始终产生真实 - 不能是其他任何东西。即使   对象的属性已更改,您仍将进行比较   改变了对象。

存储请求的字符串化版本以供以后测试解决了我的问题:

var request = {
    origin: "John O'Groats",
    destination: "Land's End",
    waypoints: [{
        location: "Penrith",
        stopover: true
    }],
    travelMode: google.maps.DirectionsTravelMode.DRIVING
},
    requestStr = JSON.stringify(request);
// Dont make a new request if same as last
if (requestStr !== lastRequest) {
    lastRequest = requestStr;
    directionsService.route(request, function(response, status) {

            ...

    }
}

2 个答案:

答案 0 :(得分:1)

如果表达式的两边都是同一个对象实例,那么=====运算符只会计算到true,因此您将无法直接使用这些运算符来比较对象的基于其属性的平等。

但是,您可以实现自己的等式检查算法,如果您愿意,可以通过使用DirectionRequest实例函数的equals伪类来使用更简单的OO方法。

function DirectionRequest(data) {
    this.origin = data.origin;
    this.destination = data.destination;
    this.waypoints = data.waypoints;
    this.travelMode = data.travelMode;
}

DirectionRequest.prototype.equals = function (request) {
    if (!(request instanceof this.constructor)) {
        return false;
    }

    //equality checking algorithm e.g.
    return this.origin === request.origin 
           && this.destination === request.destination;
};

var req1 = new DirectionRequest({
        origin: 'start', //just strings for the example
        destination: 'end',
        waypoints: 'wpts',
        travelMode: 'driving'
    }),
    req2 = new DirectionRequest({
        origin: 'start', //just strings for the example
        destination: 'end',
        waypoints: 'wpts',
        travelMode: 'driving'
    });

req1.equals(req2); //true
req1.equals({}); //false

编辑:

我已根据您的需求稍微修改了实现,请查看FIDDLE。对于waypoints,您不能简单地检查this.waypoints === request.waypoints是否与您一样,因为它只是检查数组实例是否是同一个对象。你最好只使用_.isEqual,这将在两个对象之间进行深度比较。

DirectionRequest.prototype.equals = function(request) {
    return _.isEqual(this, request);
};

答案 1 :(得分:0)

问题的根源在于lastRequest = request

Javascript对象是通过引用而不是值来分配的,因此lastRequest = request只是创建第二个符号(lastRequest),指向与原始符号(request)相同的对象。

因为只有一个对象,所以将lastRequestrequest进行比较的任何尝试都会产生true - 不能是其他任何东西。即使对象的属性已更改,您仍将比较已更改的对象与自身。

然而......

jQuery包含了很棒的实用程序$.extend(),它(以正确的方式使用)允许克隆javascript对象。

尝试:

lastRequest = $.extend({}, request);

现在将lastRequestrequest进行比较将始终产生false,因为requestlastRequest是不同的对象(无论其属性如何)。

但是......尝试你的stringify比较。它现在有很好的工作机会。