Angular.js: $ eval hoạt động như thế nào và tại sao nó khác với vanilla eval?


151

Tôi tò mò về các $scope.$evalbạn thường thấy trong các chỉ thị, vì vậy tôi đã kiểm tra nguồn và tìm thấy những điều sau đây rootScope.js:

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

$parsedường như được định nghĩa bởi ParseProviderin parse.js, dường như xác định một số loại cú pháp nhỏ của chính nó (tệp dài 900 dòng).

Câu hỏi của tôi là:

  1. Chính xác thì $evalđang làm gì? Tại sao nó cần ngôn ngữ phân tích cú pháp nhỏ của riêng mình?

  2. Tại sao JavaScript cũ evalkhông được sử dụng?


13
$ eval đánh giá biểu thức Angular so với / trên phạm vi hiện tại .
Mark Rajcok

4
BTW $parselà tuyệt vời tuyệt vời.
Fresheyeball

Câu trả lời:


186

$eval$parsekhông đánh giá JavaScript; họ đánh giá các biểu thức AngularJS . Tài liệu được liên kết giải thích sự khác biệt giữa các biểu thức và JavaScript.

Q: Chính xác thì $ eval đang làm gì? Tại sao nó cần ngôn ngữ phân tích cú pháp nhỏ của riêng mình?

Từ các tài liệu:

Biểu thức là các đoạn mã giống như JavaScript thường được đặt trong các liên kết, chẳng hạn như {{biểu thức}}. Biểu thức được xử lý bởi dịch vụ phân tích $.

Đó là một ngôn ngữ nhỏ giống như JavaScript giới hạn những gì bạn có thể chạy (ví dụ: không có câu lệnh điều khiển luồng, ngoại trừ toán tử ternary) cũng như thêm một số ưu điểm của AngularJS (ví dụ: bộ lọc).

Q: Tại sao "eval" javascript cũ không được sử dụng?

Bởi vì nó không thực sự đánh giá JavaScript. Như các tài liệu nói:

Nếu ... bạn muốn chạy mã JavaScript tùy ý, bạn nên đặt nó làm phương thức điều khiển và gọi phương thức. Nếu bạn muốn eval () một biểu thức góc từ JavaScript, hãy sử dụng phương thức $ eval ().

Các tài liệu liên kết đến ở trên có nhiều thông tin hơn.


Bạn đã nói $ eval không thực sự đánh giá JavaScript nhưng nếu tôi làm $ eval ("{id: 'val'}") tôi sẽ nhận được một đối tượng JS. (Góc 1.0.8)
Gabriel

7
@Yappli $evalkhông đánh giá JavaScript; nó đánh giá các biểu thức AngularJS, giống như một tập hợp con an toàn hơn của JavaScript. "{id: 'val'}"là một biểu thức AngularJS hợp lệ và sẽ trả về một đối tượng JS hợp lệ. Xem liên kết ở trên để biết sự khác biệt giữa các biểu thức và JS thông thường.
Josh David Miller

1
Câu trả lời hay nhưng tôi không chắc chắn rằng "vd: không có câu lệnh điều khiển" nào là chính xác. Bạn có thể làm một cái gì đó như thế này ... ng-click = "someVal? SomeFunc (someVal): noop", đó là một biểu thức góc hoàn toàn hợp lệ
Charlie Martin

@CharlieMartin Tài liệu đặc biệt nói "không có báo cáo lưu lượng kiểm soát" , nhưng quan điểm của bạn là hợp lệ. Tuy nhiên, tôi chắc chắn sẽ không khuyên bạn nên làm điều đó trong một ngClick; loại logic đó gần như chắc chắn thuộc về bộ điều khiển.
Josh David Miller

1
Điều thú vị là các tài liệu nói rằng vì sự hỗ trợ cho toán tử ternary đã được thêm vào một cách có chủ ý ... github.com/angular/angular.js/blob/master/src/ng/ . Nhấp chuột chỉ là một ví dụ đơn giản và tôi đồng ý logic đó phải nằm trong bộ điều khiển, nhưng tôi không thấy có gì sai khi sử dụng toán tử ternary trong ký hiệu ngoặc và nhóm góc rõ ràng là không hoặc họ sẽ không hỗ trợ thêm. Tôi cho rằng nếu một sự điều chỉnh đã được thực hiện, thì nó sẽ xảy ra trong các tài liệu trước câu trả lời này
Charlie Martin

22

Từ bài kiểm tra,

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);
}));

Chúng tôi cũng có thể vượt qua người dân địa phương để đánh giá biểu hiện.


2

Tôi nghĩ rằng một trong những câu hỏi ban đầu ở đây đã không được trả lời. Tôi tin rằng vanilla eval () không được sử dụng vì khi đó các ứng dụng góc cạnh sẽ không hoạt động như các ứng dụng Chrome, điều này ngăn chặn rõ ràng eval () được sử dụng vì lý do bảo mật.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.