web-dev-qa-db-ja.com

eval()とnew Function()は同じものですか?

これら2つの機能は、舞台裏で同じことをしていますか? (単一ステートメント関数内)

var evaluate = function(string) {
    return eval('(' + string + ')');
}

var func = function(string) {
    return (new Function( 'return (' + string + ')' )());
}

console.log(evaluate('2 + 1'));
console.log(func('2 + 1'));
83
qwertymk

いいえ、それらはnot同じです。

  • eval()は、現在の実行スコープ内のJavaScript式として文字列を評価し、ローカル変数にアクセスできます。
  • new Function()は、文字列に保存されているJavaScriptコードを解析して、呼び出し可能な関数オブジェクトにします。コードは別のスコープで実行されるため、ローカル変数にアクセスできません。

次のコードを検討してください。

_function test1() {
    var a = 11;
    eval('(a = 22)');
    alert(a);            // alerts 22
}
_

new Function('return (a = 22);')()が使用された場合、ローカル変数aはその値を保持します。それにもかかわらず、Douglas Crockfordなどの一部のJavaScriptプログラマーは、 どちらも使用しないでください絶対に必要 であり、信頼できないデータでFunctionコンストラクターを評価/使用することは安全ではないと考えていますそして賢明ではありません。

107
PleaseStand

いや.

更新では、evaluatefuncの呼び出しで同じ結果が生成されます。しかし、彼らは間違いなく「舞台裏で同じことをしている」わけではありません。 func関数は新しい関数を作成しますが、すぐに実行しますが、evaluate関数はコードをその場で実行するだけです。

元の質問から:

var evaluate = function(string) {
    return eval(string);
}
var func = function(string) {
    return (new Function( 'return (' + string + ')' )());
}

これらにより、非常に異なる結果が得られます。

evaluate('0) + (4');
func('0) + (4');
6
palswim

new Functionは、再利用可能な関数を作成します。 evalは、指定された文字列を実行し、最後のステートメントの結果を返します。 Functionを使用してevalをエミュレートするラッパー関数を作成しようとしたため、質問の見当違いがあります。

彼らがカーテンの後ろでいくつかのコードを共有しているのは本当ですか?はい、ありそうです。まったく同じコードですか?いいえ、確かに。

楽しみのために、evalを使用して関数を作成する不完全な実装を次に示します。違いに光を当てることを願っています!

function makeFunction() {
  var params = [];
  for (var i = 0; i < arguments.length -  1; i++) {
    params.Push(arguments[i]);
  }
  var code = arguments[arguments.length -  1];


 // Creates the anonymous function to be returned
 // The following line doesn't work in IE
 // return eval('(function (' + params.join(',')+ '){' + code + '})');
 // This does though
 return eval('[function (' + params.join(',')+ '){' + code + '}][0]');
}

これと新しいFunctionの最大の違いは、Functionがレキシカルにスコープされないことです。したがって、クロージャー変数にアクセスできず、私の場合もそうです。

6
Juan Mendes

つまり、同じ結果が得られますか?はい...ですが、単に評価する(「JavaScriptのこの文字列を評価する」)方がはるかに簡単です。

以下を編集:

それは...これらの2つの数学の問題は同じですか?

1 + 1

1 + 1 + 1-1 + 1-1 * 1/1

2
Timothy Khouri

その例では、結果は同じです、はい。両方とも、渡された式を実行します。これが彼らをとても危険なものにしている。

しかし、彼らはこの状況の背後でさまざまなことをします。 new Function()を含むものは、舞台裏で、指定したコードから匿名関数を作成します。この関数は、関数が呼び出されたときに実行されます。

渡すJavaScriptは、匿名関数を呼び出すまで技術的には実行されません。これは、すぐにコードを実行し、それに基づいて関数を生成しないeval()とは対照的です。

1
Chris Laplante

ここの例で使用されている構文とその意味を指摘したいだけです。

 var func = function(string) {
     return (new Function( 'return (' + string + ')' )());
 }

function(...)()の最後に「()」があることに注意してください。この構文により、funcは新しい関数を実行し、文字列を返す関数ではなく文字列を返しますが、次を使用する場合:

 var func = function(string) {
     return (new Function( 'return (' + string + ')' ));
 }

これで、funcは文字列を返す関数を返します。

1
Jack D Menendez