故事來源
前陣子同事偶然在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內物件之間的判定操作時運算子過載是非常常見的。