1. ホーム
  2. javascript

[解決済み] Javascript: 演算子のオーバーローディング

2022-03-05 11:42:26

質問

JavaScriptを使い始めて数日経ちますが、定義したオブジェクトに対して演算子をオーバーロードしたいという状況になりました。

Googleで検索してみたところ、公式にはできないようですが、このアクションを実行するための長ったらしい方法を主張している人が何人かいるようです。

基本的にはVector2クラスを作り、以下のようなことができるようにしたいです。

var x = new Vector2(10,10);
var y = new Vector2(10,10);

x += y; //This does not result in x being a vector with 20,20 as its x & y values.

その代わり、こんなことをしなければならない。

var x = new Vector2(10,10);
var y = new Vector2(10,10);

x = x.add(y); //This results in x being a vector with 20,20 as its x & y values. 

Vector2クラスで演算子をオーバーロードする方法はありますか?これは単に醜く見えるだけなので。

どのように解決するのですか?

お分かりのように、JavaScriptは演算子のオーバーロードをサポートしていません。最も近いのは toString (インスタンスを文字列に強制する必要があるときに呼び出されます) と valueOf (を使用する場合など、数値に変換するために呼び出されます。 + を足し算に使う場合、あるいは多くの場合、連結に使う場合は + は連結の前に加算を行おうとします)、これはかなり限定的です。どちらも Vector2 オブジェクトを生成します。同じように Proxy (ES2015 で追加) では、オブジェクトのさまざまな操作 (プロパティへのアクセスも含む) を傍受できますが、やはり +=Vector インスタンスになります。


この質問に来る人の中で、結果として文字列や数値が欲しい人(代わりに Vector2 の例です。 valueOftoString . これらの例 しない は演算子のオーバーロードを示すもので、JavaScript に組み込まれたプリミティブへの変換処理を利用しているだけです。

valueOf

この例では、オブジェクトの val を経由してプリミティブに強制された場合、その応答として + :

function Thing(val) {
    this.val = val;
}
Thing.prototype.valueOf = function() {
    // Here I'm just doubling it; you'd actually do your longAdd thing
    return this.val * 2;
};

var a = new Thing(1);
var b = new Thing(2);
console.log(a + b); // 6 (1 * 2 + 2 * 2)

あるいは、ES2015の class :

class Thing {
    constructor(val) {
      this.val = val;
    }
    valueOf() {
      return this.val * 2;
    }
}

const a = new Thing(1);
const b = new Thing(2);
console.log(a + b); // 6 (1 * 2 + 2 * 2)

あるいは、コンストラクターなしのオブジェクトだけで

var thingPrototype = {
    valueOf: function() {
      return this.val * 2;
    }
};

var a = Object.create(thingPrototype);
a.val = 1;
var b = Object.create(thingPrototype);
b.val = 2;
console.log(a + b); // 6 (1 * 2 + 2 * 2)

toString

この例では、オブジェクトの val を経由してプリミティブに強制された場合などには、大文字に変換されます。 + :

function Thing(val) {
    this.val = val;
}
Thing.prototype.toString = function() {
    return this.val.toUpperCase();
};

var a = new Thing("a");
var b = new Thing("b");
console.log(a + b); // AB

あるいは、ES2015の class :

class Thing {
    constructor(val) {
      this.val = val;
    }
    toString() {
      return this.val.toUpperCase();
    }
}

const a = new Thing("a");
const b = new Thing("b");
console.log(a + b); // AB

あるいは、コンストラクターなしのオブジェクトだけで

var thingPrototype = {
    toString: function() {
      return this.val.toUpperCase();
    }
};

var a = Object.create(thingPrototype);
a.val = "a";
var b = Object.create(thingPrototype);
b.val = "b";
console.log(a + b); // AB