72 votes

Calculer la valeur d'une chaîne de caractères en javascript, sans utiliser eval

Existe-t-il un moyen de calculer une formule stockée dans une chaîne de caractères en JavaScript sans utiliser eval ?

Normalement, j'aurais fait quelque chose comme

var apa = "12/5*9+9.4*2";
alert(eval(apa));

Alors, quelqu'un connaît-il des alternatives à eval ?

10voto

parapura rajkumar Points 16597

Si vous ne voulez pas utiliser eval, vous devrez utiliser une bibliothèque d'évaluateurs d'expressions existante.

http://silentmatt.com/javascript-expression-evaluator/

http://www.codeproject.com/KB/scripting/jsexpressioneval.aspx

Vous pouvez également en créer un vous-même :)

4voto

Paweł Points 1434

J'ai passé quelques heures à implémenter toutes les règles arithmétiques sans utiliser eval() et enfin j'ai publié un paquet sur npm string-math . Tout est dans la description. Profitez de

4voto

nikkypizza Points 21

Cette solution supprime également les espaces et vérifie l'absence de doublons entre les opérateurs.

par exemple ' 1+ 2 *2' // 5 mais ' 1 + +2* 2 ' // Error

function calcMe(str) {
  const noWsStr = str.replace(/\s/g, '');
  const operators = noWsStr.replace(/[\d.,]/g, '').split('');
  const operands = noWsStr.replace(/[+/%*-]/g, ' ')
                          .replace(/\,/g, '.')
                          .split(' ')
                          .map(parseFloat)
                          .filter(it => it);

  if (operators.length >= operands.length){
    throw new Error('Operators qty must be lesser than operands qty')
  };

  while (operators.includes('*')) {
    let opIndex = operators.indexOf('*');
    operands.splice(opIndex, 2, operands[opIndex] * operands[opIndex + 1]);
    operators.splice(opIndex, 1);
  };
  while (operators.includes('/')) {
    let opIndex = operators.indexOf('/');
    operands.splice(opIndex, 2, operands[opIndex] / operands[opIndex + 1]);
    operators.splice(opIndex, 1);
  };
  while (operators.includes('%')) {
    let opIndex = operators.indexOf('%');
    operands.splice(opIndex, 2, operands[opIndex] % operands[opIndex + 1]);
    operators.splice(opIndex, 1);
  };

  let result = operands[0];
  for (let i = 0; i < operators.length; i++) {
    operators[i] === '+' ? (result += operands[i + 1]) : (result -= operands[i + 1])
  }
  return result
}

Cette méthode s'avère plus performante que @vol7ron La solution de l'entreprise. Vérifiez ceci JSBenchmark

3voto

vol7ron Points 11270

Si vous cherchez un équivalent syntaxique à eval vous pouvez utiliser new Function . Il existe de légères différences en ce qui concerne le champ d'application, mais le comportement est essentiellement le même, y compris l'exposition à la plupart des mêmes risques de sécurité :

let str = "12/5*9+9.4*2"

let res1 = eval(str)
console.log('res1:', res1)

let res2 = (new Function('return '+str)())
console.log('res2:', res2)

2voto

Nico Points 13021

Vous ne pouvez pas, tout au plus vous pourriez faire quelque chose de rétorquant comme analyser les nombres et ensuite séparer les opérations avec un switch, et les faire. A part ça, j'utiliserais eval dans ce cas.

Cela ressemblerait à quelque chose comme (une mise en œuvre réelle sera un peu plus complexe, surtout si l'on considère l'utilisation des parenthèses, mais vous voyez l'idée)

    function operate(text) {
        var values = text.split("+");

        return parseInt(values[0]) + parseInt(values[1]);
    }

    alert(operate("9+2"));

Je pense néanmoins que le meilleur choix que vous puissiez faire est d'utiliser eval, étant donné que vous êtes en mesure de faire confiance à la source de la chaîne.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X