使用带有javascript的逻辑运算符压缩if / else if语句

时间:2017-06-07 23:29:39

标签: javascript angularjs logical-operators

我正在学习AngularJS,尝试制作一个简单的计算器,我试图压缩这个 if / else if statement 到1-2行,使用Javascript逻辑运算符(&&||!

鉴于这个例子,我怎么能减少它? (如果你不理解 $scope ,请忽略它。它基本上是一个视图。所以当有人点击9时,计算器将在答案屏幕上显示9)

$scope.setOperand = function (operandEntered) {

    if ($scope.leftOperand === null) {
        $scope.leftOperand = operandEntered;
    } 
    else if ($scope.operator === null) {
        $scope.leftOperand = $scope.leftOperand + operandEntered;
    } 
    else if ($scope.rightOperand === null) {
        $scope.rightOperand = operandEntered;
    } 
    else if ($scope.answer === null) {
        $scope.rightOperand = $scope.rightOperand + operandEntered;
    }
 };

7 个答案:

答案 0 :(得分:1)

总是(尝试)聪明,但是当代码变得更长并且不再可重用时,抽象并不总能得到回报。 KISS

但如果你想要去,我会选择

function addTo(property, x, operand) { // "x" for lack of a more meaningful name
    const shouldAdd = $scope[property] === null || $scope[x] === null;
    if (shouldAdd)
        $scope[property] += operand; // assuming "operand" is a number
// or   $scope[property] = ($scope[property] || "") + operand; // when it's a string
    return shouldAdd;
}
$scope.setOperand = function (operandEntered) {
    addTo("leftOperand", "operator", operandEntered) || addTo("rightOperand", "answer", operandEntered);
 };

如果你更关心简洁而不是可读性,你甚至可以缩短帮助

function addTo(property, x, operand) {
    return ($scope[property] === null || $scope[x] === null) && (($scope[property] += operand), true);
}

答案 1 :(得分:1)

TLDR;

做出如下所有相同的假设,这将起作用,当然很简单:

$scope.setOperand = function (operand) {
    var prop = $scope['leftOperand'] === null ? 'leftOperand' : 'rightOperand';
    $scope[prop] = +$scope[prop] + operand;
};

关键是这一部分:+$scope[prop]这会将null转换为0,因此您最终会将其添加到一侧或另一侧,如果它是null或已经一个值(这是逻辑似乎做的)。 Bergi指出,nullnull两个值都没有得到处理,但我说计算应该在其他地方进行:

$scope.calc = function(){
    return eval(
        +$scope.leftOperand         // Cast if null to 0
        + ($scope.operator || '+')  // Default to add if null
        +$scope.rightOperand‌        // Cast if null to 0
    );
};

假设您有一个左/右操作数(并且您没有尝试执行多个操作):

var $scope = {
    operator: '-',
    answer: null,
    leftOperand: null,
    rightOperand: 3,
};

我们可以从:

开始
$scope.setOperand = function (operand) {
    var prop = ['leftOperand','rightOperand'].reduce(function(t, k) {
        return $scope[k] === null ? k : t;
    });
    $scope[prop] = +$scope[prop] + operand;
};

https://jsfiddle.net/w89dLrqw/

这是四行。我们可以删除一行带有一点hijinks:

$scope.setOperand = function (operand) {
    [['leftOperand','rightOperand'].reduce(function(t, k) {
        return $scope[k] === null ? k : t;
    })].map(function(prop){$scope[prop] = +$scope[prop] + operand});
};

https://jsfiddle.net/b63x7aag/

或者,如果你愿意:

$scope.setOperand = function (operand) {
    [['leftOperand','rightOperand'].reduce(function(t, k) {return $scope[k] === null ? k : t;})]
    .map(function(prop){$scope[prop] = +$scope[prop] + operand});
};

另一个(@bergi的道具):

$scope.setOperand = function (operand) {
    (function(prop){$scope[prop] = +$scope[prop] + operand})
    (['leftOperand','rightOperand'].reduce(function(t, k){return !+$scope[k] ? k : t}));
};

https://jsfiddle.net/mh1bvhcj/1/

最后两个看起来缩小了,而最后一个看起来是'倒立'#34;我无法用这种方式来看它是如何有用的,因为它占用的水平空间非常小。

我不明白else if ($scope.answer === null)的含义是什么,因为answer === null似乎不会影响操作数,据我所知。所以这可能会或可能不会起作用,这取决于它的含义。

答案 2 :(得分:0)

我重新考虑过 - 你可以用一种方式使它变得更好,而在另一种方式则更糟。

对于这样的每个表达式:

$scope.leftOperand = $scope.leftOperand + operandEntered;

您可以使用赋值运算符:

$scope.leftOperand += operandEntered;

稍微缩短它。

我重新考虑过了。假设你实际上正在进行字符串连接以根据输入的数字构建数字,我认为这就是你想要的(我确实跳过了'回答'条件,因为它不应该发生)。

$scope.setOperand = function (operandEntered) {
    var prop = ($scope.operator === null) ? 'leftOperand' : 'rightOperand';
    $scope[prop] = ($scope[prop] === null) ? operandEntered : $scope[prop]+operandEntered;
};

答案 3 :(得分:0)

有这样的可能性:

$scope.setOperand=(operandEntered)=>{
    $scope.leftOperand=($scope.leftOperand===null)? // if
        operandEntered
        : // else if v
        ($scope.operator===null)?
            $scope.leftOperand+operandEntered
            : // else v
            (()=>{
                $scope.rightOperand=($scope.rightOperand===null)? // if
                    operandEntered
                    : // else if v
                    ($scope.answer===null)?
                        $scope.rightOperand+operandEntered
                        : // else v
                        $scope.rightOperand;
                return $scope.leftOperand;
            })();
};

然后缩短到这个:

$scope.setOperand=(operandEntered)=>{$scope.leftOperand=($scope.leftOperand===null)?operandEntered:($scope.operator===null)?$scope.leftOperand+operandEntered:(()=>{$scope.rightOperand=($scope.rightOperand===null)?operandEntered:($scope.answer===null)?$scope.rightOperand+operandEntered:$scope.rightOperand;return $scope.leftOperand;})();};

完全按照你的要求,缩短每个if / else if语句。

答案 4 :(得分:0)

鉴于OP提供的更新代码,单个语句现在可以满足$scope.setOperand(),如下所示:

$scope.setOperand = function (operandEntered) {
          $scope.operator
          ? $scope.rightOperand += operandEntered 
          : $scope.leftOperand += operandEntered;
    };

简单的三元解决了OP最初关注的问题;见deno here

我无法通过“C”按钮清除显示,这可能是由于在codepen.io中配置事物的方式,其中location.reload()可能是不允许的。所以,我记下了那个按钮,如下:

$scope.setClear = function (a) {

          $scope.leftOperand = "";
          $scope.operator = "";
          $scope.rightOperand = "";
          $scope.answer = "";

    };

请参阅演示here

现在显示清除,无需等待页面重新加载。我做的另一个改变如下:

if (answer % 1 !== 0)

这可确保只有浮点值显示为小数。现在1 + 2等于3而不是3.00。 (咨询此资源:How do I check that a number is float or integer?

答案 5 :(得分:0)

----------------------------更新------------工作代码---- ---------------

** HTML **

<!DOCTYPE html>
<html lang="en-us" ng-app="calcApp" class="full-height">
<head>
    <title>Hello World</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <base href="/Tom-s-Journal/">
    <link rel='shortcut icon' type='image/x-icon' href='favicon.ico' />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <link rel="stylesheet" href="JournalCSS.css">
</head>


<body class="full-height overflow-hidden" ng-cloak>

    <div class="theCalculator" ng-controller="calcCtrl" id="outsideCalcEdge">
        <div class="calcButtonsrow" id="1stLine">
            <div id="answerScreen">
                <span>{{leftOperand}}</span> 
                <span>{{operator}}</span> 
                <span>{{rightOperand}}</span> 
                <span>{{clear}}</span>
            </div>
        </div>

        <div class="calcButtonsrow" title="brand" id="brand">
            <span id="calcBrand">*Basic Calculator*</span><br>
            <span id="kogoSoftwareLLC">Kogo Software LLC</span>
        </div>
        <div class="calcButtonsrow" id="2ndLine">
            <button class="number" id="7" ng-click="setOperand('7')">7</button>
            <button class="number" id="8" ng-click="setOperand('8')">8</button>
            <button class="number" id="9" ng-click="setOperand('9')">9</button>
            <button id="divideBySign" ng-click="setOperator('/')" class=" operator">/</button>
        </div>
        <div class="calcButtonsrow" id="3rdLine">
            <button class="number" id="4" ng-click="setOperand('4')">4</button>
            <button class="number" id="5" ng-click="setOperand('5')">5</button>
            <button class="number" id="6" ng-click="setOperand('6')">6</button>
            <button id="multiplySign" ng-click="setOperator('*')" class=" operator">*</button>
        </div>
        <div class="calcButtonsrow" id="4thLine">
            <button class="number" id="1" ng-click="setOperand('1')">1</button>
            <button class="number" id="2" ng-click="setOperand('2')">2</button>
            <button class="number" id="3" ng-click="setOperand('3')">3</button>
            <button id="minusSign" ng-click="setOperator('-')" class=" operator">-</button>

        </div>
        <div class="calcButtonsrow" id="5thLine">
            <button id="clear" ng-click="setClear('C')">C</button>
            <button class="number" id="0" ng-click="setOperand('0')">0</button>
            <button id="equalSign" ng-click="getAnswer('=')" 
            ng-disabled="!leftOperand || !operator || !rightOperand">=</button>
            <button id="plusSign" ng-click="setOperator('+')" class=" operator">+</button>
        </div>
    </div>


    <script 
    src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js">
</script>

<script src="calculator.js"></script>

</body>
</html>

<强> AngularJS

var calcApp = angular.module('calcApp', []);

calcApp.controller('calcCtrl', function ($scope) {
    $scope.leftOperand = "";
    $scope.operator = "";
    $scope.rightOperand = "";
    $scope.answer = "";


    $scope.setOperand = function (operandEntered) {
        if ($scope.operator){
            $scope.rightOperand += operandEntered;
        }
        else {
            $scope.leftOperand += operandEntered;
        };
    };
    $scope.setOperator = function (operatorEntered) {
        $scope.operator = operatorEntered;
    };

    $scope.getAnswer = function () {
        var result = $scope.leftOperand + $scope.operator + $scope.rightOperand;
        var answer = eval(result);
        if (answer % 2 !== 0){
            $scope.answer = answer.toFixed(2);
        }
        else {$scope.answer = answer;}

        $scope.leftOperand = $scope.answer;
        $scope.operator = "";
        $scope.rightOperand = "";
    };

    $scope.setClear = function (a) {
        $scope.clear = location.reload();
    };


});
    var windowProperties = "width=255,height=367,menubar=yes,location=no,resizable=no,scrollbars=no";
    var windowObjectReference = function openCalc() {
        window.open("/Tom-s-Journal/calculatorHTML.html", "calcWindow", windowProperties);
};

<强> CSS

@font-face {
    font-family: 'sickCalculatorFont';
    src: url('./calcFontFiles/digital-7.ttf');
}
#answerScreen {
    background-color: lightgray;
    border-style: inset;
    border-color: white;
    border-width:5px;
    font-family: 'sickCalculatorFont';
    font-size: 25px;
    font-weight: bold;
    height: 50px;
    padding-left: 3px;
    width: 215px;
}

button {
    border-radius: 10px;
    font-weight: bold;
    height: 50px;
    width: 50px;
}



#brand {
    color: #000;
    font-weight: bold;
    font-size: 11px;
    text-align: center;
}

.calcButtonsrow {
    padding: 5px;
}

#calcButtonsBox {
    border-style: groove;
}

#clear {
    background-color: #FFAAAA;
}

.overflow-hidden {
    overflow: hidden;
}
#divideBySign {
    border-radius: 10px;
    font-weight: bold;
    height: 50px;
    width: 50px;
}
#divideBySign:hover {
    background-color: #4CAF50;
    color: white;
}

#equalSign{
    color: #FA6800;
}

#kogoSoftwareLLC {
    color: grey;
    font-weight: bold;
}

#minusSign {
    border-radius: 10px;
    font-weight: bold;
    height: 50px;
    width: 50px;
}
#minusSign:hover {
    background-color: #4CAF50;
    color: white;
}

#modalCalcButt {
    height: 150px !important;
    width: 150px !important;
}

#multiplySign {
    border-radius: 10px;
    font-weight: bold;
    height: 50px;
    width: 50px;
}
#multiplySign:hover {
    background-color: #4CAF50;
    color: white;
}


.number:hover {
    background-color: yellow;
    color: black;
}

#outsideCalcEdge {
    border-style: solid;
    border-width: 3px;
    border-radius: 3px;
    margin-left: 2px;
    margin-bottom: 50px;
    padding: 10px;
    width: 250px;
}

.operator {
    color: white;
    background-color: #0E2F5C;
}

#plusSign {
    border-radius: 10px;
    font-weight: bold;
    height: 50px;
    width: 50px;
}
#plusSign:hover {
    background-color: #4CAF50;
    color: white;
}

.theCalculator {
    background-color: lightskyblue;
}

[disabled] {
    color: gray !important;
    /*            the id of #equalSign takes precedence over [disabled], !important over rides that*/
}

[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
    display: none !important;
}

答案 6 :(得分:0)

简短回答 - 所有代码都在我之前的回答中进一步说明。编辑,很高兴。

$scope.setOperand = function (operandEntered) {
        if ($scope.operator){
            $scope.rightOperand += operandEntered;
        }
        else {
            $scope.leftOperand += operandEntered;
        };
    };