JS - Как посчитать значение арифметического выражения из строки

414
01 июня 2017, 09:36

Пытаюсь сделать калькулятор. Работает он следующим образом:
При клике по цифре, она вписывается в переменную. При клике по знаку (+,-,*,/), они добавляются в ту же переменную что и цифра. В итоге получается к примеру:
var x = '18*2+3'
Я хочу сделать чтобы при нажатии по знаку равенства, уравнение находящееся в переменной x было решено, как к примеру, если бы это было просто:
var x = 18*2+3.
console.log(x);
Пробовал функцию Number и понял что делаю что-то не то.

Подскажите пожалуйста какими способами можно решить задачу и как можно автоматический увеличить высоту дива ('.example') при достижении определенного количества знаков?

$(function() { 
 
var numbers = 0; 
var example = 0; 
 
// Пот нажатии на кнопку с цифро, он появляется в нижнем "табло" калькулятора 
$('.numBtn').click(function() { 
	if (numbers.length >= 12) { 
		return; 
	} else { 
		if (numbers == 0) { 
			numbers = this.value; 
		} else { 
			numbers += this.value; 
		} 
	} 
	$('.calcIn').text(numbers); 
}) 
 
// При нажатии на знак +, - , * или /, цифра и нажатый знак урованения добавляются в переменную example. 
$('.funcBtn').click(function(){ 
	example += ($('.calcIn').text()) 
	$('.desk').text(example+=this.value); 
	numbers = 0 
	$('.calcIn').text(numbers) 
}) 
 
 
 
/*При нажатии на кнопку равно, результат примера находящегося в качестве строки в переменной example должен появиться в качестве текста в классе calcIn */ 
$('.equalBtn').click(function(){ 
//  
// 
$('.calcIn').text(result); 
}) 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script> 
 
<div class="simpleCalc"> 
 
		<div class="scoreboard"> 
      <div class="desk"> 0</div> 
			<div class="calcIn" id="text">0</div> 
      
		</div> 
		<table> 
			<input type="button" class="button bigButtonC cButton" value="C"> 
			<input type="button" class="button topBtn CEbtn" value="CE"> 
			<input type="button" class="button topBtn funcBtn" value="x2"> 
			<input type="button" class="button topBtn funcBtn" value="del"> 
			<input type="button" class="button topBtn funcBtn" value="÷"> 
 
			<input type="button" class="button secLineBtn numBtn" value="7"> 
			<input type="button" class="button secLineBtn numBtn" value="8"> 
			<input type="button" class="button secLineBtn numBtn" value="9"> 
			<input type="button" class="button secLineBtn funcBtn" value="×"> 
			<br> 
 
			<input type="button" class="button thirdLineBtn funcBtn" value="%"> 
			<input type="button" class="button thirdLineBtn numBtn" value="4"> 
			<input type="button" class="button thirdLineBtn numBtn" value="5"> 
			<input type="button" class="button thirdLineBtn numBtn" value="6"> 
			<input type="button" class="button thirdLineBtn funcBtn" value="−"> 
 
			<input type="button" class="button fourthLineBtn funcBtn" value="√"> 
			<input type="button" class="button fourthLineBtn numBtn" value="1"> 
			<input type="button" class="button fourthLineBtn numBtn" value="2"> 
			<input type="button" class="button fourthLineBtn numBtn" value="3"> 
			<input type="button" class="button bigButtonPlus funcBtn" value="+"> 
 
			<input type="button" class="button bottomLineBtn funcBtn" value="±"> 
			<input type="button" class="button bottomLineBtn commaBtn" value=","> 
			<input type="button" class="button bottomLineBtn numBtn" value="0"> 
			<input type="button" class="button bottomLineBtn equalBtn" value="="> 
 
		</table> 
	</div>

Answer 1

Добрый день! В вашем случае подойдет использование функции eval(), хотя ее использование крайне не рекомендуется в сообществе. Она создает из строки полноценное выражения для выполнения. Для простоты демонстрации я изменил ваш div в текстовый input (разница в коде только в том, что для инпутов нужно именять не .text(), а val()).

$('.equalBtn').click(function() {
    let equation = $('.desk').val();
    let result = eval(equation);
    $('.calcIn').text(result);
});

Насчет высоты. Высота элементов сама легко регулируется при помощи css, достаточно задать ширину для блочного элемента. В вашем случае, если ответ будет слишком длинный и в одно "слово", то следует применить свойство overflow-wrap, которое как раз решает эту задачу.

#text {
    width: 200px;
    overflow-wrap: break-word;
}

Для демонстрации я добавил кнопку с отображением числа пи.

Демо: https://jsfiddle.net/w96k/regbLvbf/1/

Answer 2

The eval() function evaluates JavaScript code represented as a string.

А увеличить размер элемента, это же обычный if:

if (символов_достаточно) element.style.height = '20px'; //например (или методами jquery)

НО!

eval() is a dangerous function, which executes the code it's passed with the privileges of the caller. If you run eval() with a string that could be affected by a malicious party, you may end up running malicious code on the user's machine with the permissions of your webpage / extension. More importantly, third party code can see the scope in which eval() was invoked, which can lead to possible attacks in ways to which the similar Function is not susceptible.

eval() is also generally slower than the alternatives, since it has to invoke the JS interpreter, while many other constructs are optimized by modern JS engines.

Корректнее (но не проще) написать свою функцию(ции), которая разбирает строку на токены и оперирует уже <числами> и <выражениями>, правильно определяет порядок вычислений.

Подробнее можно почитать по запросу "лексический анализатор" в поисковиках и в книжках по построению компиляторов.

READ ALSO
Передача объекта в функцию по клику

Передача объекта в функцию по клику

Получаю SyntaxError: missing ] after element list myFunc([object Object])

224
Адаптивная таблица

Адаптивная таблица

Задача - немного упростить процесс работы с таблицами на мобильных устройствахПростым превращением таблицы в блок не обойтись, так как при...

290
Передача нескольких параметров в ajax

Передача нескольких параметров в ajax

Суть в том: Есть форма, данные из которой ловит django view и, после нескольких операций, результат выводит с помощью render(request, '

286