JS中if(a ==1 && a== 2 && a==3)判定為true的另類思考

花間酒發表於2018-02-04

故事來源

前陣子同事偶然在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');
}
複製程式碼
  • 執行結果

    JS中if(a ==1 && a== 2 && a==3)判定為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內物件之間的判定操作時運算子過載是非常常見的。

相關文章