2

我正在使用 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)) {

再次无法正常工作。

以上所有返回错误的结果。我猜可能是因为wpts是对象中的另一个request对象。

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

解决方案

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

由于只有一个对象,因此任何将 lastRequest 与 request 进行比较的尝试都将始终产生 true - 不能是其他任何东西。即使对象的属性已更改,您仍将更改的对象与自身进行比较。

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

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) {

            ...

    }
}
4

2 回答 2

1

===or==运算符仅在表达式的两边是相同的对象实例时才会计算结果,true因此您将无法直接使用这些运算符根据它们的属性来比较对象的相等性。

但是,您可以实现自己的相等性检查算法,并且如果您愿意,可以通过使用带有实例函数的DirectionRequest伪类来使用稍微多一点的 OO 方法。equals

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像您所做的那样,因为它只会检查数组实例是否是同一个对象。您最好简单地使用_.isEqualwhich 将在两个对象之间进行深入比较。

DirectionRequest.prototype.equals = function(request) {
    return _.isEqual(this, request);
};
于 2013-09-28T20:50:49.643 回答
0

问题的根源在于lastRequest = request

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

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

然而 ...

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

尝试 :

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

现在比较lastRequest总是request会产生false,因为requestlastRequest是不同的对象(无论它们的属性如何)。

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

于 2013-09-29T02:57:43.613 回答