Tại sao nên tránh các toán tử tăng ((++ ++)) và giảm dần (trực tiếp) trong JavaScript?


357

Một trong những mẹo cho công cụ jslint là:

++ và -
Các toán tử ++ (tăng) và - (giảm) đã được biết là đóng góp cho mã xấu bằng cách khuyến khích sự khó khăn quá mức. Chúng chỉ đứng thứ hai sau kiến ​​trúc bị lỗi trong việc kích hoạt virus và các mối đe dọa bảo mật khác. Có một tùy chọn plusplus cấm sử dụng các toán tử này.

Tôi biết rằng các cấu trúc PHP như thế $foo[$bar++]có thể dễ dàng dẫn đến các lỗi khác nhau, nhưng tôi không thể tìm ra cách nào tốt hơn để kiểm soát vòng lặp hơn là một while( a < 10 ) do { /* foo */ a++; }hoặc for (var i=0; i<10; i++) { /* foo */ }.

Là jslint làm nổi bật chúng bởi vì có một số ngôn ngữ tương tự thiếu cú pháp " ++" và " --" hoặc xử lý nó khác nhau, hoặc có những lý do khác để tránh " ++" và " --" mà tôi có thể bị thiếu?


59
Vì vậy, người ta nên thực hiện mảng [index = index + 1] thay vì mảng [++ index] (nếu trước đây thậm chí được phép!). Thật là một tải hooey.
Lawrence Dol

34
Tôi chưa thấy Crockford do index = index + 1. Tôi đã thấy anh ta làm chỉ số + = 1. Tôi nghĩ đó là một sự thay thế hợp lý. Và thật tuyệt khi bạn muốn thay đổi sải chân thành thứ gì đó ngoài 1.
Nosredna

124
Cá nhân tôi không phải là một fan hâm mộ lớn của Crockford. Anh ta dường như coi bất cứ điều gì đã từng gây ra một lỗi trong mã của mình là xấu xa.
Paolo Bergantino

38
Trong JavaScript, bạn nên coi mọi lỗi là hơi xấu, vì không có tài liệu chính thức cũng như không có nhà cung cấp chứng chỉ cũng như bạn không học JS đúng cách trong trường Đại học. Crockford và Fireorms đã lấp đầy những lỗ hổng này trong giáo dục JavaScript.
stevek

40
++không gây ra lỗi. Sử dụng các cách ++"khó khăn" có thể dẫn đến lỗi, đặc biệt là nếu có nhiều người đang duy trì cơ sở mã, nhưng đó không phải là vấn đề với nhà điều hành, đó là vấn đề với lập trình viên. Tôi đã không học JS ở trường đại học (vì nó chưa tồn tại), nhưng vậy thì sao? Tôi đã làm C, trong đó tất nhiên có ++đầu tiên, nhưng điều đó cũng nhận được "vậy thì sao?" Tôi đã không đến trường đại học để học một ngôn ngữ cụ thể, tôi đã đi học các thực hành lập trình tốt mà tôi có thể áp dụng cho bất kỳ ngôn ngữ nào .
nnnnnn

Câu trả lời:


408

Quan điểm của tôi là luôn luôn sử dụng ++ và - một mình trên một dòng, như trong:

i++;
array[i] = foo;

thay vì

array[++i] = foo;

Bất cứ điều gì ngoài điều đó có thể gây nhầm lẫn cho một số lập trình viên và chỉ là không đáng theo quan điểm của tôi. Đối với các vòng lặp là một ngoại lệ, vì việc sử dụng toán tử gia tăng là thành ngữ và do đó luôn rõ ràng.


3
Vâng, đó là những gì tôi làm quá. Khó đi sai và người khác dễ dàng hiểu được bạn đang làm gì.
Nosredna

65
Điều đó dường như đang trở thành cốt lõi của vấn đề và sự nhầm lẫn của tôi. Được sử dụng một mình, i ++; là tinh thể rõ ràng. Giây phút bạn thêm mã khác xung quanh biểu thức cơ bản đó, tính dễ đọc và rõ ràng bắt đầu bị ảnh hưởng.
artlung

2
Đồng ý, nhưng nó không chỉ liên quan đến JavaScript
Tobias

5
Bạn không nói liệu bạn đang viết C hay C ++. Có thể cho rằng bạn nên sử dụng toán tử gia tăng tiền tố trong C ++, trong trường hợp ibiến sau này trở thành một lớp tổng hợp, trong trường hợp đó bạn không cần thiết phải tạo một đối tượng tạm thời. Tôi tìm thấy các toán tử postfix mặc dù thẩm mỹ hơn.
mc0e

2
Tôi thích phiên bản 1 dòng. Nó nhắc nhở một hoạt động ngăn xếp. đẩy là mảng [++ i] = foo, pop là bar = mảng [i--]. (Nhưng với mảng dựa trên 0, mảng [i ++] = foo và bar = mảng [- i] trông vẫn tốt hơn). Một điều nữa, tôi sẽ ghét nó nếu ai đó thêm mã bổ sung giữa i ++; và mảng [i] = foo;.
Florian F

257

Tôi thực sự bối rối bởi lời khuyên đó. Một phần trong tôi tự hỏi liệu nó có liên quan nhiều đến việc thiếu kinh nghiệm (nhận thức hay thực tế) với các lập trình viên javascript.

Tôi có thể thấy cách ai đó chỉ "hack" ở một số mã mẫu có thể phạm sai lầm vô tội với ++ và - nhưng tôi không hiểu tại sao một chuyên gia có kinh nghiệm sẽ tránh chúng.


7
Điểm hay Jon B. Đó là lý do tại sao nó làm phiền tôi như vậy. Crockford là một lập trình viên nghề nghiệp (đáng giá hàng thập kỷ), giao tiếp với nhiều ngôn ngữ trong nhiều thập kỷ và làm việc với JavaScript về cơ bản kể từ khi thành lập. Tôi không nghĩ lời khuyên của anh ấy đến từ "Tôi là một hacker thiếu kinh nghiệm và thiếu kinh nghiệm" - đó là lý do tại sao tôi đang cố gắng hiểu nó đến từ đâu.
artlung

14
@artlung Có lẽ nó liên quan nhiều hơn đến "Một hacker lười biếng và thiếu kinh nghiệm" có lẽ sẽ gây rối với mã này và tôi không muốn nhầm lẫn anh ta.
Chris Cudmore

9
Tôi hoàn toàn không đồng ý với câu trả lời của bạn. Theo tôi, đó không phải là 'Tôi có đủ kinh nghiệm để sử dụng nó không?' - nhưng 'Có rõ hơn hay không?' Nếu bên trong một vòng lặp for, hoặc một mình, nó rõ ràng - mọi người sẽ hiểu điều đó không có hại. Vấn đề xuất hiện khi đặt ++biểu thức phức tạp hơn trong wich ++ x khác với x ++, do đó dẫn đến một cái gì đó không dễ đọc. Ý tưởng của Crockford không phải là 'tôi có thể làm được không?' đó là về 'làm thế nào tôi có thể tránh được lỗi?'
ArtoAle

1
Đó là sở thích cá nhân ở điểm rõ ràng quan trọng đối với bạn hơn là sự gọn nhẹ. Điều này vượt xa việc có đủ kinh nghiệm để hiểu mã. Xem các câu trả lời khác cho các ví dụ khi nó rắc rối hơn giá trị của nó.
Frug

1
Tôi hoàn toàn đồng ý. Tại sao người khuyết tật bằng cách không sử dụng một phần của ngôn ngữ? Tôi tìm thấy những lý do chính đáng để sử dụng cả tăng và giảm trước và sau. Đối với tôi, một dòng như thế này là rõ ràng và súc tích ... if (--imagesLoading === 0) start (); Nếu bạn nghĩ rằng mã của bạn không rõ ràng, hãy sử dụng ý kiến!
xtempore

69

Có một lịch sử trong C khi làm những việc như:

while (*a++ = *b++);

để sao chép một chuỗi, có lẽ đây là nguồn gốc của mánh khóe quá mức mà anh ta đang đề cập.

Và luôn có câu hỏi về cái gì

++i = i++;

hoặc là

i = i++ + ++i;

thực sự làm Nó được định nghĩa trong một số ngôn ngữ và trong ngôn ngữ khác không có gì đảm bảo điều gì sẽ xảy ra.

Bỏ qua những ví dụ đó, tôi không nghĩ có gì thành ngữ hơn vòng lặp for sử dụng ++ để tăng. Trong một số trường hợp, bạn có thể thoát khỏi vòng lặp foreach hoặc vòng lặp while kiểm tra một ống dẫn khác. Nhưng việc sửa mã của bạn để thử và tránh sử dụng tăng dần là vô lý.


104
i = i ++ + ++ i; làm mắt tôi đau một chút - :)
Hugoware

3
Của tôi cũng thế. Ngay cả khi chúng không phải là cùng một biến, hãy nói rằng tôi có x = a ++ + ++ b; - sự kết hợp đó ngay lập tức làm cho x, a và b khó giữ hơn trong đầu tôi. bây giờ, nếu mỗi câu lệnh riêng biệt trên các dòng riêng biệt, như trong - a ++; ++ b; x = a + b; nó sẽ dễ dàng hơn để hiểu về cái nhìn đầu tiên.
artlung

10
Than ôi, (a ++; b ++; x = a = b) không cùng giá trị với (a ++ + ++ b).
Thomas L Holaday

8
@Marius: x = a+++b-> x = (a++)+b-> x = a + b; a++. Mã thông báo là tham lam.
Callum Rogers

14
Để đảm bảo an toàn cho công việc, hãy xóa các khoảng trắng trong ví dụ cuối cùng của bạn.
mc0e

48

Nếu bạn đọc JavaScript Các bộ phận tốt, bạn sẽ thấy rằng sự thay thế của Crockford cho i ++ trong vòng lặp for là i + = 1 (không phải i = i + 1). Điều đó khá sạch sẽ và dễ đọc, và ít có khả năng biến thành một thứ gì đó "khó hiểu".

Crockford đã không cho phép tự động tăng tốc và tự động phát hiện một tùy chọn trong jsLint. Bạn chọn có làm theo lời khuyên hay không.

Quy tắc cá nhân của riêng tôi là không làm bất cứ điều gì kết hợp với tự động hoặc tự động phát hiện.

Tôi đã học được từ nhiều năm kinh nghiệm trong C rằng tôi không bị tràn bộ đệm (hoặc chỉ số mảng ngoài giới hạn) nếu tôi tiếp tục sử dụng đơn giản. Nhưng tôi đã phát hiện ra rằng tôi sẽ bị tràn bộ đệm nếu tôi rơi vào thực tiễn "quá khó" khi làm những việc khác trong cùng một tuyên bố.

Vì vậy, đối với các quy tắc của riêng tôi, việc sử dụng i ++ làm gia số trong vòng lặp for là ổn.


Điểm tuyệt vời về tùy chọn "plusplus" chỉ là một tùy chọn. Dựa trên câu trả lời của bạn và các câu trả lời khác, tôi nghĩ rằng tôi đang hiểu rằng ++ tự nó hoặc một vòng lặp không phải là điều khó hiểu. Thứ hai bạn kết hợp ++ đó vào một câu lệnh khác mà câu lệnh r của bạn trở nên khó đọc và khó hiểu hơn trong ngữ cảnh.
artlung

6
tất cả mọi người được tràn bộ đệm. Ngay cả OpenSSH với nguồn mở của họ và nhiều bản sửa đổi của họ
Eric

11
@Eric Xem lại nhận xét năm tuổi của bạn: oh, bạn đã đúng như thế nào!
wchargein

27

Trong một vòng lặp, nó vô hại, nhưng trong một câu lệnh gán nó có thể dẫn đến kết quả không mong muốn:

var x = 5;
var y = x++; // y is now 5 and x is 6
var z = ++x; // z is now 7 and x is 7

Khoảng trắng giữa biến và toán tử cũng có thể dẫn đến kết quả không mong muốn:

a = b = c = 1; a ++ ; b -- ; c; console.log('a:', a, 'b:', b, 'c:', c)

Trong một đóng cửa, kết quả bất ngờ cũng có thể là một vấn đề:

var foobar = function(i){var count = count || i; return function(){return count++;}}

baz = foobar(1);
baz(); //1
baz(); //2


var alphabeta = function(i){var count = count || i; return function(){return ++count;}}

omega = alphabeta(1);
omega(); //2
omega(); //3

Và nó kích hoạt chèn dấu chấm phẩy tự động sau một dòng mới:

var foo = 1, bar = 2, baz = 3, alpha = 4, beta = 5, delta = alpha
++beta; //delta is 4, alpha is 4, beta is 6

nhầm lẫn preincrement / postincrement có thể tạo ra các lỗi off-by-one cực kỳ khó chẩn đoán. May mắn thay, chúng cũng hoàn thành không cần thiết. Có nhiều cách tốt hơn để thêm 1 vào một biến.

Người giới thiệu


13
Nhưng chúng không "bất ngờ" nếu bạn hiểu nhà điều hành. Nó giống như không bao giờ sử dụng ==bởi vì bạn không hiểu sự khác biệt giữa =====.
greg84

1
Chính xác. Có một câu hỏi C # làm suy giảm các giả định sai.
Paul Sweatte

Tôi nghĩ rằng quan điểm của Crockford là hầu hết các lập trình viên không hoàn toàn "hiểu người vận hành" ngay cả khi họ nghĩ họ làm vậy; do đó, có nguy hiểm trong việc sử dụng chúng vì khả năng hiểu lầm là rất cao. Xem bình luận của @ Paul về các giả định sai lầm, điều này thúc đẩy lập luận rằng mọi người thường hiểu sai về cách các toán tử tiền tố và hậu tố thực sự hoạt động. Điều đó nói rằng, tôi thừa nhận tôi thích sử dụng chúng, nhưng vì lợi ích của người khác, tôi cố gắng giới hạn việc sử dụng chúng trong các trường hợp thành ngữ (xem câu trả lời của cdmckay ).
gfullam

Liên kết khoảng trắng của bạn dường như bị phá vỡ.
Ruslan

Có gì khó khăn về ví dụ "khoảng trắng" của bạn? Tôi nhận được một đầu ra đơn giản của a: 2 b: 0 c: 1. Tôi cũng không thấy điều gì kỳ lạ hoặc bất ngờ trong ví dụ đầu tiên ("tuyên bố chuyển nhượng").
Ken Williams

17

Hãy xem xét các mã sau đây

    int a[10];
    a[0] = 0;
    a[1] = 0;
    a[2] = 0;
    a[3] = 0;
    int i = 0;
    a[i++] = i++;
    a[i++] = i++;
    a[i++] = i++;

kể từ khi i ++ được đánh giá hai lần đầu ra là (từ trình gỡ lỗi vs2005)

    [0] 0   int
    [1] 0   int
    [2] 2   int
    [3] 0   int
    [4] 4   int

Bây giờ hãy xem xét các mã sau đây:

    int a[10];
    a[0] = 0;
    a[1] = 0;
    a[2] = 0;
    a[3] = 0;
    int i = 0;
    a[++i] = ++i;
    a[++i] = ++i;
    a[++i] = ++i;

Lưu ý rằng đầu ra là như nhau. Bây giờ bạn có thể nghĩ rằng ++ i và i ++ giống nhau. Họ không phải

    [0] 0   int
    [1] 0   int
    [2] 2   int
    [3] 0   int
    [4] 4   int

Cuối cùng hãy xem xét mã này

    int a[10];
    a[0] = 0;
    a[1] = 0;
    a[2] = 0;
    a[3] = 0;
    int i = 0;
    a[++i] = i++;
    a[++i] = i++;
    a[++i] = i++;

Đầu ra là:

    [0] 0   int
    [1] 1   int
    [2] 0   int
    [3] 3   int
    [4] 0   int
    [5] 5   int

Vì vậy, chúng không giống nhau, trộn cả hai kết quả trong hành vi không trực quan. Tôi nghĩ rằng các vòng lặp đều ổn với ++, nhưng xem ra khi bạn có nhiều biểu tượng ++ trên cùng một dòng hoặc cùng một hướng dẫn


3
Cảm ơn đã làm thí nghiệm đó. Đặc biệt là mã "tìm kiếm đơn giản", nhưng bộ não của tôi khó có thể giữ được rất nhanh. Chắc chắn rơi vào loại "khó khăn".
artlung

28
Tôi dừng lại sau ví dụ đầu tiên. Bạn nói "Hãy xem xét các mã sau". Không, không ai viết mã đó. Đó là kẻ ngốc viết rằng những người không hoàn hảo, không phải là một ngôn ngữ.
Sam Harwell

4
Bạn đã chỉ ra rằng hai đoạn mã khác nhau tạo ra đầu ra khác nhau và điều này chứng tỏ nó xấu?
nickf

7
kết luận là "coi chừng khi bạn có nhiều biểu tượng ++ trên cùng một dòng hoặc cùng một hướng dẫn". Tôi không nghĩ bạn đã đọc nó
Eric

1
"vì i ++ được đánh giá hai lần" - sai! Sửa đổi một biến hai lần giữa các điểm chuỗi và sử dụng nó là không hợp lệ trong C ++ và dẫn đến hành vi không xác định. Vì vậy, trình biên dịch có thể làm bất cứ điều gì nó muốn. Các kết quả được trình bày ở đây là tình cờ của việc thực hiện trình biên dịch.
tbleher

16

Bản chất "trước" và "bài" của các toán tử tăng và giảm có thể có xu hướng gây nhầm lẫn cho những người không quen thuộc với chúng; đó là một cách mà họ có thể khó khăn


29
Đã đồng ý; Tuy nhiên, một chuyên gia có kinh nghiệm nên không bị nhầm lẫn.
Nate

1
Tôi nghĩ rằng điều này tương tự như hướng dẫn để tránh làm cho mọi thứ tĩnh hoặc toàn cầu. Không có gì sai với nó như là một cấu trúc lập trình, nhưng việc lạm dụng quá mức có thể dẫn đến mã xấu.
Joel Martinez

6
Câu hỏi không phải là liệu một lập trình viên giỏi có thể "làm việc theo cách của họ" thông qua logic hay không - lý tưởng mã tốt không yêu cầu bất kỳ công việc nào để hiểu. Tôi nghĩ rằng quan điểm của McWafflestix chỉ là bạn không nên viết mã rằng khi kiểm tra ngắn có thể dẫn đến việc thêm lỗi trong hai hoặc hai năm. Tôi biết tôi đã phạm tội khi thêm mã vào một thói quen mà tôi không hiểu đầy đủ :)
Mike

1
@Mike: yah, lưu ý cách tôi không chỉ định liệu các toán tử có thể gây khó khăn cho tác giả ban đầu của mã hoặc cho các nhà bảo trì sau này. Nói chung, chúng tôi cố gắng giả định rằng các lập trình viên gốc không sử dụng các cấu trúc mà họ không quen thuộc / thoải mái (đáng buồn thay, đây thường là một giả định không chính xác); tuy nhiên, sự quen thuộc đó chắc chắn không mở rộng cho các nhà bảo trì (và, như đã lưu ý ở trên, thậm chí có thể không mở rộng cho tác giả gốc).
Paul Sonier

Tôi cố gắng viết mã của mình cho các lập trình viên khác đọc, nhưng tôi không cố viết mã cho người mới bắt đầu đọc.
Luke H

16

Theo quan điểm của tôi, "Rõ ràng luôn tốt hơn ngầm." Bởi vì tại một số điểm, bạn có thể bị nhầm lẫn với tuyên bố gia tăng này y+ = x++ + ++y. Một lập trình viên giỏi luôn làm cho mã của mình dễ đọc hơn.


1
Không có gì ngầm định trong x ++ hoặc ++ y.
Florian F

1
Điều này có thể đọc được là khó khăn ... Tôi nghĩ rằng có một dòng cơ sở để mã của bạn phải đơn giản như thế nào và chúng tôi - là một cộng đồng - phải phát triển một chút và có thể đọc những gì bây giờ không thể đọc được, chẳng hạn như một lớp lót với những con chim nhạn lồng nhau, như cho phép nhiều thứ hơn để đá vào.
Hamza Ouaghad

14

Lý do quan trọng nhất để tránh ++ hoặc - là các toán tử trả về các giá trị và gây ra các tác dụng phụ cùng một lúc, khiến cho việc lập luận về mã trở nên khó khăn hơn.

Vì lợi ích của hiệu quả, tôi thích:

  • ++ i khi không sử dụng giá trị trả về (không tạm thời)
  • i ++ khi sử dụng giá trị trả về (không có gian hàng đường ống)

Tôi là một fan hâm mộ của ông Crockford, nhưng trong trường hợp này tôi phải không đồng ý. ++iít hơn 25% văn bản để phân tích cú pháp hơn i+=1 rõ ràng hơn.


13

Tôi đã xem video của Douglas Crockford về điều này và lời giải thích của anh ấy về việc không sử dụng tăng và giảm là

  1. Nó đã được sử dụng trong quá khứ trong các ngôn ngữ khác để phá vỡ các giới hạn của mảng và gây ra tất cả các cách cư xử xấu và
  2. Rằng các nhà phát triển JS khó hiểu và thiếu kinh nghiệm hơn không biết chính xác những gì nó làm.

Đầu tiên các mảng trong JavaScript có kích thước động và vì vậy, hãy tha thứ cho tôi nếu tôi sai, không thể phá vỡ giới hạn của một mảng và truy cập dữ liệu không nên truy cập bằng phương thức này trong JavaScript.

Thứ hai, chúng ta có nên tránh những thứ phức tạp không, chắc chắn vấn đề không phải là chúng ta có cơ sở này mà vấn đề là có những nhà phát triển ngoài đó tuyên bố làm JavaScript nhưng không biết các nhà khai thác này hoạt động như thế nào ?? Nó là đủ đơn giản. value ++, đưa cho tôi giá trị hiện tại và sau biểu thức thêm một giá trị vào nó, giá trị ++, tăng giá trị trước khi đưa cho tôi giá trị đó.

Biểu thức như một ++ + ++ b, rất đơn giản để làm việc nếu bạn chỉ cần nhớ ở trên.

var a = 1, b = 1, c;
c = a ++ + ++ b;
// c = 1 + 2 = 3; 
// a = 2 (equals two after the expression is finished);
// b = 2;

Tôi cho rằng bạn chỉ cần nhớ ai phải đọc qua mã, nếu bạn có một nhóm biết về JS thì bạn không cần phải lo lắng. Nếu không thì bình luận nó, viết nó khác đi, vv Hãy làm những gì bạn phải làm. Tôi không nghĩ rằng tăng và giảm vốn đã xấu hoặc tạo ra lỗi, hoặc tạo lỗ hổng, có thể chỉ dễ đọc hơn tùy thuộc vào đối tượng của bạn.

Btw, tôi nghĩ Douglas Crockford dù sao cũng là một huyền thoại, nhưng tôi nghĩ rằng anh ta đã gây ra nhiều nỗi sợ hãi cho một nhà điều hành không xứng đáng với điều đó.

Tôi sống để được chứng minh là sai mặc dù ...


10

Một ví dụ khác, đơn giản hơn một số khác với giá trị gia tăng đơn giản của giá trị gia tăng:

function testIncrement1(x) {
    return x++;
}

function testIncrement2(x) {
    return ++x;
}

function testIncrement3(x) {
    return x += 1;
}

console.log(testIncrement1(0)); // 0
console.log(testIncrement2(0)); // 1
console.log(testIncrement3(0)); // 1

Như bạn có thể thấy, không nên sử dụng tăng / giảm sau khi trả về, nếu bạn muốn toán tử này ảnh hưởng đến kết quả. Nhưng lợi nhuận không "bắt" toán tử tăng / giảm sau:

function closureIncrementTest() {
    var x = 0;

    function postIncrementX() {
        return x++;
    }

    var y = postIncrementX();

    console.log(x); // 1
}

Chỉ một trong số các chức năng của bạn nhận được x làm tham số
Calimero100582

8

Tôi nghĩ các lập trình viên nên thành thạo ngôn ngữ họ đang sử dụng; sử dụng nó rõ ràng; và sử dụng nó tốt. Tôi không nghĩ họ nên làm tê liệt ngôn ngữ họ đang sử dụng. Tôi nói từ kinh nghiệm. Tôi đã từng làm việc theo nghĩa đen bên cạnh một cửa hàng Cobol nơi họ không sử dụng ELSE 'vì nó quá phức tạp'. Reductio quảng cáo vô lý.


@downvoter Hấp dẫn. Bạn không nghĩ lập trình viên nên thành thạo ngôn ngữ? Bạn nghĩ rằng họ nên làm tê liệt ngôn ngữ? Đó là cái gì Không có lựa chọn thứ ba ở đây.
Hầu tước Lorne

1
và một upvote cho ví dụ về COBOL đó, khiến tôi càng vui hơn khi COBOL hầu hết đã chết trước khi tôi bắt đầu viết mã
Mark K Cowan

1
@MarkCowan Tôi không hiểu tại sao. Quan điểm của tôi là về sự hạn chế tùy tiện, không phải ngôn ngữ. Giai thoại không chỉ ra điều gì sai với Cobol. Điều cần thiết để chết là cửa hàng lập trình, và nó đã làm. Ghé thăm các ràng buộc của bất kỳ ngân hàng lớn nào và bạn sẽ thấy Cobol vẫn còn sống và tốt.
Hầu tước Lorne

2

Như đã đề cập trong một số câu trả lời hiện có (điều khó chịu là tôi không thể bình luận), vấn đề là x ++ ++ x đánh giá các giá trị khác nhau (trước so với sau khi tăng), không rõ ràng và có thể rất khó hiểu - nếu giá trị đó được sử dụng. cdmckay gợi ý khá khôn ngoan khi cho phép sử dụng toán tử gia tăng, nhưng chỉ theo cách mà giá trị trả về không được sử dụng, ví dụ như trên dòng riêng của nó. Tôi cũng sẽ bao gồm việc sử dụng tiêu chuẩn trong một vòng lặp for (nhưng chỉ trong câu lệnh thứ ba, có giá trị trả về không được sử dụng). Tôi không thể nghĩ ra một ví dụ khác. Bản thân tôi đã bị "cháy", tôi cũng muốn giới thiệu hướng dẫn tương tự cho các ngôn ngữ khác.

Tôi không đồng ý với tuyên bố rằng sự khắt khe quá mức này là do rất nhiều lập trình viên JS thiếu kinh nghiệm. Đây là loại văn bản chính xác điển hình của các lập trình viên "quá thông minh" và tôi chắc chắn rằng nó phổ biến hơn nhiều trong các ngôn ngữ truyền thống hơn và với các nhà phát triển JS có nền tảng về các ngôn ngữ như vậy.


1
Cảm ơn vi đa trả lơi. Bạn sẽ cần một giá trị danh tiếng từ 50 trở lên để bình luận. Xem: stackoverflow.com/faq
artlung

1
@artlung: Tôi biết điều đó và lý do căn bản đằng sau nó. Tôi chỉ nói rằng nó gây phiền nhiễu :)
Gần Privman

2

Theo kinh nghiệm của tôi, ++ i hoặc i ++ chưa bao giờ gây nhầm lẫn ngoài lần đầu tiên tìm hiểu về cách thức hoạt động của toán tử. Đó là điều cần thiết cho các vòng lặp cơ bản nhất và trong khi các vòng lặp được dạy bởi bất kỳ khóa học trung học hoặc đại học nào được dạy bằng các ngôn ngữ mà bạn có thể sử dụng toán tử. Cá nhân tôi thấy làm một cái gì đó giống như những gì bên dưới để nhìn và đọc tốt hơn một cái gì đó với một ++ nằm trên một dòng riêng biệt.

while ( a < 10 ){
    array[a++] = val
}

Cuối cùng, đó là một sở thích về phong cách và không phải là bất cứ điều gì nữa, điều quan trọng hơn là khi bạn thực hiện điều này trong mã của mình, bạn phải nhất quán để những người khác làm việc trên cùng một mã có thể làm theo và không phải xử lý cùng chức năng theo các cách khác nhau .

Ngoài ra, Crockford dường như sử dụng i- = 1, điều mà tôi thấy khó đọc hơn --i hoặc i--


2

2cents của tôi là họ nên tránh trong hai trường hợp:

1) Khi bạn có một biến được sử dụng trong nhiều hàng và bạn tăng / giảm nó trong câu lệnh đầu tiên sử dụng nó (hoặc cuối cùng, hoặc thậm chí tệ hơn ở giữa):

// It's Java, but applies to Js too
vi = list.get ( ++i );
vi1 = list.get ( i + 1 )
out.println ( "Processing values: " + vi + ", " + vi1 )
if ( i < list.size () - 1 ) ...

Trong các ví dụ như thế này, bạn có thể dễ dàng bỏ lỡ rằng biến được tự động tăng / giảm hoặc thậm chí loại bỏ câu lệnh đầu tiên. Nói cách khác, chỉ sử dụng nó trong các khối rất ngắn hoặc trong đó biến xuất hiện trong khối chỉ trên một vài câu lệnh gần.

2) Trong trường hợp có nhiều ++ và - về cùng một biến trong cùng một câu lệnh. Thật khó để nhớ những gì xảy ra trong những trường hợp như thế này:

result = ( ++x - --x ) * x++;

Các bài kiểm tra và bài kiểm tra chuyên nghiệp hỏi về các ví dụ như trên và thực sự tôi đã vấp phải câu hỏi này trong khi tìm tài liệu về một trong số chúng, nhưng trong cuộc sống thực, người ta không nên buộc phải suy nghĩ nhiều về một dòng mã.


1

Fortran có phải là ngôn ngữ giống C không? Nó không có ++ cũng không -. Đây là cách bạn viết một vòng lặp :

     integer i, n, sum

      sum = 0
      do 10 i = 1, n
         sum = sum + i
         write(*,*) 'i =', i
         write(*,*) 'sum =', sum
  10  continue

Phần tử chỉ số i được tăng theo quy tắc ngôn ngữ mỗi lần qua vòng lặp. Ví dụ: nếu bạn muốn tăng thêm một thứ gì đó ngoài 1, hãy đếm ngược theo hai, cú pháp là ...

      integer i

      do 20 i = 10, 1, -2
         write(*,*) 'i =', i
  20  continue

Python có giống C không? Nó sử dụng phạm vidanh sách hiểu và các cú pháp khác để bỏ qua nhu cầu tăng chỉ mục:

print range(10,1,-2) # prints [10,8.6.4.2]
[x*x for x in range(1,10)] # returns [1,4,9,16 ... ]

Vì vậy, dựa trên khám phá thô sơ này về chính xác hai lựa chọn thay thế, các nhà thiết kế ngôn ngữ có thể tránh ++ và - bằng cách dự đoán các trường hợp sử dụng và cung cấp một cú pháp thay thế.

Có phải Fortran và Python là một nam châm lỗi ít hơn so với các ngôn ngữ thủ tục có ++ và -? Tôi không có bằng chứng.

Tôi khẳng định rằng Fortran và Python giống như C vì tôi chưa bao giờ gặp ai đó thông thạo C, người không thể đoán chính xác 90% ý định của Fortran hoặc Python không bị che giấu.


1
Vâng, IFortran là từ những năm 1950, trong khi C là từ những năm 1970, vì vậy có lẽ không có gì để Fortran giống như C. Ví dụ về Python thiếu một cái gì đó giống như toán tử plusplus rất thú vị. Lặp lại các cấu trúc dữ liệu được xử lý đơn giản hơn trong Python, Python là JavaScript hướng đối tượng "khác biệt". Có lẽ lời khuyên của Crockford là về việc sử dụng cú pháp giống OO hơn cho phép lặp.
artlung
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.