… なんてことは出来ませんよね。でも、二項演算子に見せかけるようにジタバタしてみましたよ。
まずは例題。
/** 集合の共通部分 */ function intersectionOfSets(a1, a2) { // 重複は除外されない return a1.filter(function(item) {return (a2.indexOf(item) > -1);}); } /** 2つのオブジェクトを、順序に依存しないでマージする */ function merge(o1, o2) { var ks1 = Object.keys(o1); var ks2 = Object.keys(o2); if (intersectionOfSets(ks1, ks2).length !== 0) { throw new Error("Can not merge"); } var r = {}; ks1.forEach(function(k){r[k] = o1[k];}); ks2.forEach(function(k){r[k] = o2[k];}); return r; }
mergeという関数は次のような感じ。
>>> merge({a:"foo", b:"bar"}, {x:1})Object { a="foo", b="bar", x=1}
>>> merge({a:"foo", b:"bar"}, {a:1})
Error: Can not merge
このmergeを、2引数の関数じゃなくて中置ニ項演算子のように扱いたいのです。
オブジェクトのメソッドにすると少しニ項演算子っぽくなります。
Object.prototype.merge = function(obj) { return merge(this, obj); };
>>> ({a:"foo", b:"bar"}).merge({x:1})Object { a="foo", b="bar", x=1}
でも、演算子と言えばワードよりは記号ですよね。次のようにしてみましょう。
Object.prototype.$$ = function(obj) { return merge(this, obj); };
({a:"foo", b:"bar"}) .$$ ({x:1})Object { a="foo", b="bar", x=1}
.$$ という、3文字の記号による演算子のように見えなくもありません。関数名に使えて記号っぽい文字というと、ドル記号('$')とアンダースコア('_')、英大文字を使って .X、.H、.V なんかも記号っぽいかもしれません。でも、'+' とか '>' なんかを関数名に含めることはできません。次のようにすれば使えなくもないですが。
Object.prototype['+'] = function(obj) { return merge(this, obj); };
>>> ({a:"foo", b:"bar"}) ['+'] ({x:1})Object { a="foo", b="bar", x=1}
['+'] という4文字をひとつの演算子とみなすわけです。… しかし、クォートされた '+' なら我慢できそうですが、['+'] は面倒で耐えられないかも。
特定の状況下で可読性を上げるためには、演算子定義があると便利だな、と感じます。