在Javascript中使用equals和compareTo方法进行对象比较

sq1bmfud  于 2023-02-07  发布在  Java
关注(0)|答案(2)|浏览(250)

我正尝试使用equals和compareTo方法实现自定义的相等和关系运算。但是,我得到了错误的结果。请帮助我找出错误的地方。

var Person = function () {
this.age = null;
this.name = null;
};

Person.prototype.equals = function (that) {
    if (this.age === that.age) return true;
    else return false;
    };

Person.prototype.compareTo = function (that) {
    return this.age - that.age;
    };

var p1 = new Person();
var p2 = new Person();

p1.age = 10;
p2.age = 20;

document.writeln(p1 < p2); // this should be true but evaluates to false.
2w2cym1i

2w2cym1i1#

JavaScript没有运算符重载,>不调用对象上的任何方法,因此p1 < p2不会使用您的equalscompareTo
要进行比较,您可以用途:

document.writeln(p1.compareTo(p2) < 0);

也就是说,您可以实现valueOf并让它返回agevalueOf * 不 * 作为>的一部分在对象之间被调用:

function Person(age) {
    this.age = age;
    this.name = null;
}

Object.defineProperty(Person.prototype, "valueOf", {
    value: function () {
        return this.age;
    },
    writable: true,
    configurable: true,
});

或者在自ES 2015在未过时的浏览器中得到普遍支持以来编写的代码中:

class Person {
    constructor(age) {
        this.age = age;
        this.name = null;
    }

    valueOf() {
        return this.age;
    }
}

示例:

class Person {
    constructor(age) {
        this.age = age;
        this.name = null;
    }

    valueOf() {
        return this.age;
    }
}

const p1 = new Person(10);
const p2 = new Person(20);

console.log("p1 < p2: " + (p1 < p2)); // true
console.log("p1 > p2: " + (p1 > p2)); // false

请注意,p1 == p2p1 === p2将始终为false,即使age相同:

class Person {
    constructor(age) {
        this.age = age;
        this.name = null;
    }

    valueOf() {
        return this.age;
    }
}

const p1 = new Person(10); // Same age
const p2 = new Person(10); // Same age

console.log("p1 == p2:  " + (p1 == p2));  // false!
console.log("p1 === p2: " + (p1 === p2)); // false!

valueOf在JavaScript引擎需要将对象转换为原语时被调用;对于=====,它不会这样做,除非因为另一个操作数是原语,所以必须定义equals并显式调用它(p1.equals(p2)),或者强制比较原语(+p1 === +p2),这很容易出错。

pqwbnv8z

pqwbnv8z2#

回顾这个问题并使用node v18.13.0,我发现对象之间的关系运算符调用valueOf方法,如果不可用,则调用toString方法。可以构建String表示以允许比较大多数对象类型(假设您可以根据需要构建String表示)。
下面的示例通过注解进/出toStringvalueOf方法的两个版本来说明所有这些情况:

import assert from 'node:assert/strict';

export class ComparableDate {

    // private instance variables
    #year
    #month
    #date

    constructor(year, month, date) {
        this.#year = year;
        this.#month = month;
        this.#date = date;
    }

    // Relational operators > < invoke the toString method.
    // Observe that this fails for comparing dates in general
    // toString() {
    //     console.log("toString invoked");
    //     return ""+this.#year+"-"+this.#month+"-"+this.#date;
    // }

    // Zero-left padding, makes the string comparison work as expected
    toString() {
        console.log("toString invoked");
        return (""+this.#year).padStart(4,'0')+"-"+(""+this.#month).padStart(2,'0')+"-"+(""+this.#date).padStart(2,'0');
    }

    // valueOf called over toString if present
    valueOf() {
        console.log("valueOf invoked");
        return this.#date + this.#month*31 + this.#year*366;
    }

}

// Test dates
let d1 = new ComparableDate(2023,2,15);
let d2 = new ComparableDate(2023,10,31);

// Test cases
assert(d2>d1, `${d2} must be greater than ${d1}`);
assert(d1<d2, `${d1} must be less than ${d2}`);

相关问题