故事来源
前阵子同事偶然在Q上给我发了一段文字
Is it ever possible that (a==1&&a==2&&a==3) could evaluate to true, in JavaScript?
作为一个从事过.C#代码的我来说,第一反应就想起了运算符重载(原谅我如此粗暴)。其实这个问题的答案可以用valueOf解决,网上也有各路神仙形形色色的解决办法。不过我还是思考了下如何通过运算符重载实现此问题。
解决方案
问题非常简单,我发现一个babel的plugin,可以间接实现运算符重载。https://github.com/gzz2000/babel-plugin-operator
使用方式
- 手写如下代码,按照上面github工程的说明操作就可以了,非常简单。
'bpo enable';
class Point {
operatorAdd = (b) => {
const a = this;
return new Point(a.x + b.x, a.y + b.y);
}
operatorMul = (b) => {
const a = this;
return new Point(a.x * b, a.y * b);
}
operatorEqual = (b) => {
return true;
}
};
let a = new Point();
if (a==1&&a==2&&a==3) {
console.log('true');
}
复制代码
-
执行结果
-
来看下经过babel转换的
dist/index.js
内容是啥(截取部分)var _Op = function () { 'bpo disable'; return { add: function add(a, b) { if (a.operatorAdd) return a.operatorAdd(b);else return a + b; }, sub: function sub(a, b) { if (a.operatorSub) return a.operatorSub(b);else return a - b; }, equal: function equal(a, b) { if (a.operatorEqual) return a.operatorEqual(b);else if (a.operatorNotEqual) return !a.operatorNotEqual(b);else if (b.operatorEqual) return b.operatorEqual(a);else if (b.operatorNotEqual) return !b.operatorNotEqual(a);else return a == b; }, notEqual: function notEqual(a, b) { if (a.operatorNotEqual) return a.operatorNotEqual(b);else if (a.operatorEqual) return !a.operatorEqual(b);else if (b.operatorNotEqual) return b.operatorNotEqual(a);else if (b.operatorEqual) return !b.operatorEqual(a);else return a != b; } }; }(); var Point = function Point() { var _this = this; _classCallCheck(this, Point); this.operatorAdd = function (b) { var a = _this; return new Point(_Op.add(a.x, b.x), _Op.add(a.y, b.y)); }; this.operatorMul = function (b) { var a = _this; return new Point(_Op.mul(a.x, b), _Op.mul(a.y, b)); }; this.operatorEqual = function (b) { return true; }; }; ; var a = new Point(); if (_Op.equal(a, 1) && _Op.equal(a, 2) && _Op.equal(a, 3)) { console.log('true'); } 复制代码
问题思考
原理其实很简单,熟悉的babel的童鞋一看就理解为何了。其实就是对源码进行了转换等操作。感兴趣对可以看看https://github.com/thejameskyle/babel-handbook/blob/master/translations/zh-Hans/plugin-handbook.md#toc-asts这篇文章,是介绍如何编写plugin的。在.net内对象之间的判定操作时运算符重载是非常常见的。