Angular.js:$ evalはどのように機能し、なぜバニラevalと異なるのですか?


151

$scope.$evalディレクティブで頻繁に見られるあなたに興味があったので、ソースをチェックアウトしたところ、次のものが見つかりましたrootScope.js

  $eval: function(expr, locals) {
    return $parse(expr)(this, locals);
  },

$parseParseProviderin によって定義されてparse.jsいるように見えます。これは、独自のある種のミニ構文を定義しているようです(ファイルは900行です)。

私の質問は:

  1. 正確には何をし$evalていますか?なぜ独自のミニ解析言語が必要なのですか?

  2. 単純な古いJavaScript evalが使用されないのはなぜですか?


13
$ eval は、現在のスコープに対して/上のAngular式を評価します
Mark Rajcok 2013年

4
ところで$parse、めちゃくちゃ素晴らしいです。
Fresheyeball 2013

回答:


186

$eval$parseJavaScriptを評価しないでください。AngularJS を評価します。リンクされたドキュメントでは、式とJavaScriptの違いについて説明しています。

Q:$ evalは正確には何をしているのですか?なぜ独自のミニ解析言語が必要なのですか?

ドキュメントから:

式は、JavaScriptのようなコードスニペットであり、通常は{{式}}などのバインディングに配置されます。式は$ parseサービスによって処理されます。

これはJavaScriptのようなミニ言語であり、実行できるものを制限し(たとえば、3項演算子を除く制御フローステートメントはありません)、AngularJSの優れた機能(フィルターなど)を追加します。

Q:プレーンな古いJavaScript "eval"が使用されないのはなぜですか?

それは実際にはJavaScriptを評価していないからです。ドキュメントが言うように:

...任意のJavaScriptコードを実行したい場合は、それをコントローラーメソッドにしてメソッドを呼び出す必要があります。JavaScriptから角度式をeval()する場合は、$ eval()メソッドを使用します。

上記にリンクされているドキュメントには、より多くの情報があります。


$ evalは実際にはJavaScriptを評価していないと言っていましたが、$ eval( "{id: 'val'}")を実行すると、JSオブジェクトが取得されます。(Angular 1.0.8)
ガブリエル

7
@Yappli $evalはJavaScriptを評価しません。これは、JavaScriptのより安全なサブセットのような一種のAngularJS式を評価します。"{id: 'val'}"有効なAngularJS式であり、有効なJSオブジェクトを返す必要があります。式と通常のJSの違いについては、上記のリンクを参照してください。
Josh David Miller

1
いい答えですが、「制御フローステートメントがない」などが正確かどうかはわかりません。次のようなことができます... ng-click = "someVal?someFunc(someVal):noop"これは完全に有効な角度式です
Charlie Martin

@CharlieMartinドキュメントには「制御フローステートメントはありません」と明記されていますが、あなたの主張は有効です。ただし、ngClickでそれを行うことはお勧めしません。この種のロジックは、ほぼ確実にコントローラーに属しています。
Josh David Miller、

1
興味深いことに、3項演算子のサポートが意図的に追加されたため、github.com / angular / angular.js / blob / master / src / ng / … ng-clickは単なる例であり、同意します。そのロジックはコントローラーにあるはずですが、ブラケット表記での三項演算子の使用に問題はなく、角度のあるチームもそうでないか、サポートが追加されていなかったでしょう。訂正が行われたとすれば、それはこの回答の前にドキュメントで発生するはずです
チャーリーマーティン

22

テストから、

it('should allow passing locals to the expression', inject(function($rootScope) {
  expect($rootScope.$eval('a+1', {a: 2})).toBe(3);

  $rootScope.$eval(function(scope, locals) {
    scope.c = locals.b + 4;
  }, {b: 3});
  expect($rootScope.c).toBe(7);
}));

評価式にローカルを渡すこともできます。


2

ここの元の質問の1つは答えられなかったと思います。アンギュラアプリはChromeアプリとして機能せず、セキュリティ上の理由からeval()の使用が明示的に禁止されているため、バニラeval()は使用されていないと思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.