2011-11-08 7 views
1

私は例えば、文字列に保存されている関数ソース:evalの中輸入数学の名前空間に()

var source="(function(){return Math.sin(x);})"; 

を持って、私はeval()に渡し、それが後の値です計算したい:

var f=eval(source); 
var v=f(); 

それは動作しますよくしかし、の接頭辞なしでMathの機能を使用したいと考えています。だから私はできるだろう:

var source="(function(){return sin(x);})"; 

これを達成する簡単な方法はありますか?私はすでにWebGLを使用しているので、古いブラウザと互換性がある必要はありません。

追加情報:私はeval()が悪いことを承知している

。私は関数グラファーを書いていますが、sourceは描画される予定のユーザーによって入力された関数です。それで、Math.という接頭辞を取り除きたいのです。

私はそれがきれいになるとは思っていませんが、私は自分のパーサを書くつもりはありません。多分もっと良い方法がありますか?

+0

コードを文字列として保存する理由はありますか?関数リテラルを変数に格納するだけで、評価を避けるのはなぜですか?あなたが「数学」をしたくない理由はありますか? –

+0

なぜ 'eval'を使っているのですか? 'var f = Math.sin'を保存して、既存の関数を1つだけラップするだけではならない場合は、無関係な関数を使用してください。あなたは車輪の上に蝶を壊している。そして、それは非常に醜い、危険な、起動するための遅い車輪です。 – delnan

+1

質問:「eval」とタイプしたときに震えましたか?そうでない場合は、別の解決策を見つけることを提案するかもしれません。もしそうなら、先に進んで、危険なものを使用するための*私のテストに合格しました。:) – Crisfole

答えて

6

あなたは範囲を拡張するために古代の、遅い、醜いwithキーワードを使用することができます。

var source="(function(){return sin(x);})"; 
with (Math) { 
    var f=eval(source); 
    var v=f(); 
} 

も参照してください:https://developer.mozilla.org/en/JavaScript/Reference/Statements/with

+0

+1しかし、ここではいくつかの追加の警告があります:evalを使用しないでください。後でコードを維持しようとすると多くの人が混乱を招くことを認識しないような、あいまいな構文なので、悪いことです。 – Quentin

+1

@Quentin: "eval" .replace( "a"、 "i") 'と完全に同意しますが、私はプログラムの背景を知らないので、より良い解決法を提案することは難しくなります。 'with 'の使い方は、5年以上前の' with(document.all){field.value = 1;}'のようなコードを思い出させます。醜い( 'document.all')と醜い(' with')の組み合わせ – Lekensteyn

3

あなたは、この目的のためにwithを使用することができます。

var source="(function(){return Math.sin(x);})"; 
with(Math){ 
    var f = eval(source); 
    var v = f(); 
} 

も参照:MDN: with

+0

@Bantharもしあなたが計算機の種類を作りたいのであれば、 'eval'を使うのは怠惰でしょう。あなたのアプリケーションがユーザー入力に 'eval'を使用すると、潜在的な問題が作成されます。 –

2

あなたがeval()を使用するつもりなら、多分あなたは、ユーザーが入力した機能を取り、いくつかのグローバル、大文字と小文字を区別しない代替品を行うことができますが:

var source = document.getElementById("someInputBox").value; 
source = source.replace(/sin/ig,"Math.sin"); 
source = nsource.replace(/cos/ig,"Math.cos"); 
source = source.replace(/sqrt/ig,"Math.sqrt"); 
source = source.replace(/pi/ig,"Math.PI"); 
source = source.replace(/^/ig,"Math.PI"); 
source = source.replace(/([a-z]|\d+(?:\.\d+)?)*\s*\^\s*([a-z]|\d+(?:\.\d+)?)/ig, "Math.pow($1, $2)"); 
result = eval(source); 

重要:Math.pow()交換ウォン」 5^(5-3^(2*2))のような先進的な表現のために働きます。あなたはそれらのためのより高度な戦略を見つける必要があります。このwebsiteには、に変換する可能性があるPHPの解があります。

1

evalの安全性と互換性についての討論を除いて、部分的な評価によってこのユースケースでのパフォーマンス上のペナルティを避けることができます。

fstring"x*cos(x)"ようなユーザ入力を含む文字列である場合、

with (Math) f=eval("(function(x) {return "+fstring+";})"); 

fstringのコードに基づいて機能fを作成します。 fは、グラフの電卓の出力を生成するために値の範囲に素早く適用することができます。 withによって名前空間の参照を行う場合のパフォーマンスの低下は、fが作成されたときに一度だけ発生します。