Trong cả hai JavaScript và Python, /=
là một "nhiệm vụ tăng cường" nhà điều hành, với khá nhiều ý nghĩa tương tự.
Trong JS:
var i = 10;
i /= 2;
... tương đương với:
var i = 10;
i = i/2;
Và, bằng Python:
i = 10
i /= 2
... là tương tự như vậy tương đương (không hoàn toàn giống hệt nhau, nhưng đóng đủ số) tới:
i = 10
i = i/2
Tuy nhiên, có một sự khác biệt rất lớn.
Trong JavaScript, gán là biểu thức — nó có giá trị và giá trị đó là giá trị được gán cho biến. Vì vậy:
var i = 10;
var j = i /= 2;
... là tương đương với:
var i = 10;
i /= 2;
var j = i;
Trong Python, chuyển nhượng là một tuyên bố. Nó không có giá trị, và không thể được sử dụng trong một biểu thức.Vì vậy:
i = 10
j = i /= 2
… tăng SyntaxError
.
Porting mã có sử dụng chuyển nhượng (augmented hay cách khác) ở giữa một biểu hiện thường đòi hỏi phá vỡ biểu hiện mà ra thành nhiều dòng và/hoặc tìm một cách để viết lại biểu thức để không đòi hỏi bất kỳ bài tập. (Nhưng thông thường, đó không phải là điều xấu, bởi vì các biểu thức ban đầu không dễ đọc lắm…)
Ví dụ, giả sử JS đánh giá toán hạng từ trái sang phải (mà tôi không chắc chắn được đảm bảo?):
def easeInQuad(x, t, b, c, d):
t /= d
return c*t*t+b
Tổng quát hơn, bạn làm như sau:
old_t = t
t /= d
và sau đó bạn thay thế bất kỳ trường hợp của t
trước đó t/=d
với old_t
, và để lại tất cả các trường từ t/=d
và sau đó một mình. May mắn thay, trong trường hợp này, không có trường hợp nào trước đó, vì vậy chúng tôi không cần công cụ đó old_t
.
Và nếu bạn nghĩ về nó, bạn có thể dễ dàng có được tác dụng tương tự mà không bao giờ thay đổi t
, trong một dòng, nhiều hơn nữa readably, trong bất kỳ trong các cách sau:
return c * (t/d) * (t/d) + b
return c * (t/d)**2 + b
return c * t*t/d*d + b
Một người nào đó nghĩ rằng trong C sẽ ngay lập tức phàn nàn rằng đây là tất cả "quá chậm". Sau khi tất cả, đầu tiên không một phân chia thêm, thứ hai không một số mũ thay vì một phép nhân, và thứ ba hiện hai phép nhân thay vì một. Horrors!
Tất nhiên bạn luôn có thể sử dụng một biến tạm thời:
t_over_d = t/d
return c * t_over_d * t_over_d + b
... nhưng một lần nữa, để một lập trình viên C, mà ngụ ý rằng bạn đang sử dụng một đăng ký có giá trị. Chắc chắn, mọi trình biên dịch được viết sau, nói, 1985 sẽ phát hiện rằng t
đã chết ngay khi t_over_d
xuất hiện và sử dụng lại cùng một thanh ghi, nhưng tại sao không buộc nó để sử dụng lại thanh ghi nếu có thể, đặc biệt nếu nó cũng tiết kiệm một vài lần nhấn phím ?
Trong JS hoặc Python, chi phí của phép nhân là một phần nhỏ của chi phí gọi hàm, và giải thích bytecode, và cứ thế bạn thậm chí không bao giờ chú ý đến nó. Trong khi đó, chi phí của việc rebinding một biến địa phương (đặc biệt là trong một phiên bản V8 kiểu hoặc PyPy kiểu JIT thông dịch viên) có thể là nhiều, cao hơn nhiều so với chi phí đi qua xung quanh một kết quả tạm thời chưa được đặt tên. Vì vậy, đây là một trường hợp mô hình sai lầm "tối ưu hóa" làm cho mã khó hiểu hơn, trong khi có thể làm chậm nó xuống thay vì tăng tốc nó, và trong một khu vực mà không thể là một nút cổ chai giá trị tối ưu anyway.
Kể từ gnibbler lớn lên câu hỏi liệu JavaScript thực sự không đảm bảo trật tự đánh giá này ...
Đầu tiên, JavaScript được định nghĩa là, một cách hiệu quả, "những gì Firefox không" (và "những gì SpiderMonkey làm", nhưng điều đó phải giống nhau - và nếu không, thì JavaScript sẽ làm 2 thứ, vậy là gấp đôi, đúng không?).Nhưng ECMAScript là được xác định theo tiêu chuẩn và đó là những tiêu chuẩn mà mọi triển khai JS (mặc dù tên) trả tiền cho dịch vụ môi và chúng tôi có thể giả định rằng ECMAScript 5.1 là tiêu chuẩn mà mọi triển khai tuân thủ (điều này đúng với điều kiện là " tất cả triển khai "có nghĩa là" Opera "). Bạn có thể tìm thấy nó here.
Vì vậy, trong ES 5.1: 11,5 chất nhân khai thác đảm bảo rằng kết quả của (t/=d)
sẽ được đánh giá trước t
, và 11.13.2 Compound Assignment đảm bảo rằng đánh giá t/=d
sẽ thiết lập giá trị của t
trước khi nó kết thúc. (Bạn phải đọc về những gì "đánh giá" có nghĩa là gì và những gì GetValue
một nghĩa là SetValue
, nhưng tôi chắc chắn điều này thực sự được đảm bảo.)
'a/= b' bằng 'a = a/b; '. –
Đó là viết tắt [* phân chia và gán * toán tử] (https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Assignment_Operators) – Bergi
Điều đáng chú ý là, trong khi Python cũng có '/ =' thực hiện phân chia và gán như JS, gán một _statement_ thay vì một _expression_ trong Python, vì vậy '-c * (t/= d) * (t-2) + b sẽ là một' Cú pháp Cú pháp ' . – abarnert