2012-04-27 14 views
4

、ボイド、evalを、およびJavaScriptでのFunctionコンストラクタの違いは何ですか?

void(document.body.innerText += 'hi') 
 

 
eval(document.body.innerText +='\nbye') 
 

 
Function(document.body.innerText += '\n!!!') 
 

 
void(Function(function foo(){document.body.innerText += '\n>hi2'; return true}).toString())(); 
 

 
eval(Function(function foo(){document.body.innerText += '\nbye2'; return true}).toString())(); 
 

 
Function(Function(function foo(){document.body.innerText += '\n!!!2'; return true}).toString())();

これらの異なるステートメント内のコードを実行するための処理モデルは何ですか?

void(alert('hi')) 
undefined 

eval(alert('hi')) 
undefined 

Function(alert('hi')) 
function anonymous() { 
    undefined 
} 

eval(Function(function foo(){return true}).toString())(); 
TypeError: undefined is not a function 

void(Function(function foo(){return true}).toString())(); 
TypeError: string is not a function 

Function(Function(function foo(){return true}).toString())(); 
undefined 

答えて

3

this articleevalFunctionコンストラクタは、説明されている:内蔵eval機能

(...)グローバル、 発呼者の範囲内のコードを評価します。

Functionコンストラクタ によって作成された関数内で実行されるコードは、実際にはグローバルスコープで実行されません。しかし、それはおそらく混乱につながる何である、のいずれか ローカルスコープで実行されません。 Functionコンストラクタは、そのスコープチェーン(もちろん、機能の独自のアクティベーション オブジェクトで始まる)グローバルスコープが、 何で構成されて関数を作成します。 Functionコンストラクタを介して作成された関数に含まれるコードはない グローバルスコープに、その機能の範囲で評価します。 グローバルオブジェクトは、スコープチェーンで非常に次のオブジェクトがあるので、しかし、それは、ほとんどのコードがグローバルに実行しているかのようです。

そしてthis pageによると、voidはちょうどundefined返します

多くの言語で、voidは値を持たないタイプです。 JavaScriptでは、 voidは、オペランドを取り、undefinedを返す演算子です。この は役に立たず、非常に混乱します。 voidは避けてください。ここで

+3

グローバルスコープ内のコードを評価します。 –

1

評価の違いをまとめたものである:

  • void含む関数のスコープ
  • eval内のコードを評価するには、独自のスコープ内のコードを評価
  • Function含む関数のスコープ内の文字列を評価

と戻り差S:

  • voidは常に
  • Function匿名関数を返す

参照未定義

  • eval戻るに実行されるコードの戻り値を返し

  • +0

    'void'はグローバルスコープ内のコードを評価しません。 'void expr'は、' expr'だけで行うように 'expr'を評価し、現在のスコープで起こります。文字列をコードとして評価する 'eval'や' Function'のようなものではありません。 – Oriol

    0

    は、それはあなたが完全にこれらの機能を悪用していることは注目に値します。

    • voidは、何らかの式を評価し、未定義を返します。

      注:これは演算子であり、関数ではないので、オペランドをかっこで囲む必要はありません。

      これは、undefinedがシャドウされる可能性がある、または少ない文字を入力することを心配する場合にのみ、値を未定義にするのに便利です。代わりに

      var undef = void(document.body.innerText += 'hi') 
      

      活用

      document.body.innerText += 'hi'; 
      var undef = void 0; 
      

      そして、あなたが未定義取得する必要がない場合は、まったくvoidを使用していないの

    • evalは、文字列で呼び出されるはずです。その文字列をコードとして評価します。正確な動作は、それを厳格なモードか粗悪なモードのどちらで呼び出すか、それが直接か間接かどうかによって異なります。

      文字列で呼び出さないと、引数だけが返されます。あなたのケースでは

      eval(document.body.innerText += '\nbye')ます:

      1. 実行document.body.innerText += '\nbye'、例えば、新しい値を返します。 "hello\nbye"
      2. 結果のテキストをコードとして評価します。おそらくこれはスローされます。 Functionコンストラクタは、evalのような基本的

        var myvar = 0; 
         
        var bye = 123 
         
        eval(document.body.innerText += '\nbye'); 
         
        console.log(myvar); // 123
        myvar =

      3. :私はeval(document.body.innerText +='\nbye')はあなたが望むものではありませんが、ここでは(推奨されません)反例ではほぼ確信して

      文字列をすぐにコードとして評価する代わりに、関数を作成します。

      document.body.innerText += '\n!!!'は有効な文字列を返すことができないので、投げるだけです。

    • これらの機能のいくつかの奇妙な組み合わせがあります。

      Functionコンストラクタに関数を渡すと、文字化されます。 Functionコンストラクタは、引数のような関数を宣言するだけの無名関数を返します。それは無意味です。

      toStringに電話すると、これにより匿名機能が文字列化されます。

      次に、void(Function(function foo(){document.body.innerText += '\n>hi2'; return true}).toString())();はこの文字列化を呼び出そうとします。しかし、文字列は呼び出し可能ではありません。エラー。

      eval(Function(function foo(){document.body.innerText += '\nbye2'; return true}).toString())();は、ストリンジェナイテーションを評価します。ちょうどなぜ?しかし、関数の宣言は値を返さないので、あなたは呼び出し不能なundefinedを得るだけです。エラー。

      およびFunction(Function(function foo(){document.body.innerText += '\n!!!2'; return true}).toString())();は、fooをストリング化し、それを匿名関数に解析し、匿名関数をストリング化し、もう一度別の匿名関数に解析します。しないでください。最後に、そこにreturn文がないので、呼び出しはundefinedを返します。

    関連する問題