JavaScriptの中のeval語句は味わいが浅いです.

5029 ワード

1.evalの初体験evalこの文は、どう言いますか?非常に使いやすいです.つまり、「本物そっくりに装うのがいい」ということです.文字列の入力を受けて、インタプリタに対応文字列の内容を入力するように文字列を実行することができます.信じない?これを見てください
//             
> eval("function a(m) {return m + 1}")
undefined
> a(10)
11

//             
> a = eval("(function(m) {return m + 1})")
[Function]
> a(10)
11

//       
> eval("1+2+3+4")
10

//            
> x = 1222222
1222222
> eval("x")
1222222

evalの中の値が文字列でない場合は、参加値を返します.
> eval(12)
12

//            
> eval(new String("console"))
[String: 'console']
これは確かによさそうです.Pythonのような動的言語がたくさんあります.Rubyにはこの関数があります.でも私もコードの中でその姿をめったに見ません.
ここに入ってくる文字列は語義に合っていなければなりません.でないと、文法エラーを報告します.
この方法の使用についてはずっと論争があります.私が見た次の二つの言い方.
1.安全性の考慮evalは危険です.このような状況を考えてみてください.もし私達が誤ってevalインターフェースを一部開放したら外に出ます.実は私達のユーザーにコードを実行する権利に相当します.ユーザーが意図的または意図的に、文法的なルールに合わない文字列の内容を一部evalに提供し、システムに異常を投げかける可能性があります.
2.最適化不足
現代のJS解釈器はほとんどのJS構文解析を最適化しているが、eval()を呼び出した関数を最適化しているのはそれほど多くない.
実は、ほとんどの場合、私たちはevalを選択する必要はありません.今は多くの代替案があります.
Don't use eval needlessly!
ここで例を挙げます.
ある時は、反復によって対象の各種属性を訪問したいかもしれませんが、事前に対象の属性がどれぐらい必要なのか分かりませんので、属性をコードに無理に編入することはできません.
var dict = {x: 1, y: 2}

//         
function getKey() {return 'x'}
var key = getKey();

console.log(eval("dict." + key));
私たちが事前に知らなかったら、私たちが訪問するキーは'x'です.上のコードを書き出すかもしれません.実は下のコードで代替できます.強制格はそんなに高くないですが、このような表現がもっとはっきりしていると思います.
var dict = {x: 1, y: 2}

//         
function getKey() {return 'x'}
var key = getKey();

console.log(dict[key]);
やむを得ない限り、エヴァは使わないほうがいいです.
またこのようなコードが書かれるかもしれないからです.これは資料からもらいました.代表性があります
function boo(a) {
    eval(a)
};

boo("return;");
このコードは大丈夫そうですが、実はこのエラーを報告します.
SyntaxError: Illegal return statement
これはなぜですか?evalは、実際のパラメータの文字列実行時のコンテキストと、eval関数を呼び出すコンテキスト環境が同じであるため、他の関数において実行されるステートメントではなく、別のステートメントとして理解される.(ちょっと分かりにくいかもしれませんが)eval("return;")は関数に入れないと意味がないです.だから直接文法エラーを報告します.
まだ分かりません
例を挙げてみます.台本を少し変えます.
function boo(a) {
    var a = "console.log('mj')";
    eval(a)
};

boo("return;");
このとき、関数はreturn;をプリントします.変数mjに別の値を与えるからです.この文字列aが実行するコンテキストは、実は"console.log('mg')"関数の中にあります.booの場合は、解釈器は、一つの関数の中にあるかどうかにかかわらず、普通のコンテキストスコープの上で単独でa = "return;"文を実行すると見なされてもよい.しかし、これは意味に合わない.
次にもう一つの癖になる例を見てみます.
var x = "global";
//   node                  var
y = "global";
var geval = eval;

//   f eval                        
function f() {
    var x = "local";
    eval("x += 'changed';");
    return x;
}

//   g geval                   
function g() {
    var y = "local";
    geval("y += 'changed';");
    return y;
}

console.log(f(), x);
console.log(g(), y);

最後の運転の結果は
localchanged global
globalchanged local 
return;関数が関数内部f変数に対してスティッチングされていることを示したが、x関数は大域変数gをスティッチングした.したがって、この2つの関数呼び出しyのコンテキストは異なる.
2.evalの厳格モード
ここではJavascriptの厳格なモードを少し取り上げます.シナリオの中で厳しいモードを開くと(今は多くのところでこのようにしています.より厳密なJavascriptコードを書くのを手伝ってくれます.)
通常モードでは、evalの文法は比較的緩やかである.厳しいモードでは主にこの2つの制限があります.
  • は、ローカルスコープ内で新しい変数と関数を定義することができない.しかし、元の局所変数の値を変更することができます.
  • 厳格モードにおいて、evalは予約ワードとみなされる.他の関数でeval関数を上書きすることはできません.さもなくば本当にめちゃくちゃです.
  • それとも簡単な例で説明しますか?
    function a() {
        var x = 2;
        eval("var y = 1");
        eval("var x = 12");
        console.log(x);
        console.log(y);
    }
    a();
    
    ここで印刷した結果、私たちは全部eval12を思い付くことができるはずです.私たちは厳しいモードでこのシナリオを試してみます.原則として、シナリオの最初に1を加えるだけで、厳密なモードを開くことができます.
    
    'use strict';
    function a() {
        var x = 2;
        eval("var y = 1");
        eval("var x = 12");
        console.log(x);
        console.log(y);
    }
    a();
    
    この時ノドでシナリオを再起動するとエラーが発生します.
    ReferenceError: y is not defined
    
    ここでは'use strict';を用いて局所変数evalを作成しましたが、既存の局所変数yを変更することができます.
    ああ、回りくどいです.最後の例は簡単です.厳しいモードでxの値をカバーしてみます.
    'use strict'
    eval = function() {};
    
    インタプリタが直接エラーを報告しました.
    SyntaxError: Unexpected eval or arguments in strict mode
    
    私たちは厳しいモードではこのようなことをしてはいけません.厳密なパターンは、私たちが解釈器の比較的に認可されたコードを書くのに役立ちます.eval.一部のものは直接にエラーを報告して注意してくれます.たとえば、 Javascript を介してローカル変数を削除したい場合、前に述べたように、結果deleteに直接戻りますが、厳密なモードでは、このような挙動の解釈器は直接に例外を投げます.一部の大牛はやはりシナリオを書く時はできるだけ厳格なモードで書くことを勧めてくれます.専門的なポイントのJavascriptコードを書くのに役立ちます.今後のメンテナンスアップグレードにも役立ちます.
    Happy Coding