我正在学习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;
}
};
答案 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)
做出如下所有相同的假设,这将起作用,当然很简单:
$scope.setOperand = function (operand) {
var prop = $scope['leftOperand'] === null ? 'leftOperand' : 'rightOperand';
$scope[prop] = +$scope[prop] + operand;
};
关键是这一部分:+$scope[prop]
这会将null
转换为0,因此您最终会将其添加到一侧或另一侧,如果它是null
或已经一个值(这是逻辑似乎做的)。 Bergi指出,null
和null
两个值都没有得到处理,但我说计算应该在其他地方进行:
$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;
};
};