Hướng dẫn are nested functions bad practice javascript - là các hàm lồng nhau thực hành không tốt javascript

Này Peeps,

Tôi đã sử dụng JS một thời gian, nhưng gần đây tôi chỉ nên kiểm tra xem một trong những thói quen của tôi không phải là hình thức xấu khủng khiếp hay gây ra cho tôi các vấn đề về trí nhớ/hiệu quả, v.v.

Vì vậy, đây là vấn đề nan giải:

function setupExample(){

	var button1 = document.getElementById("button1");
	var button2 = document.getElementById("button2");
	var button3 = document.getElementById("button3");

	button1.addEventListener("click", toggleExampleOne);
	button2.addEventListener("click", toggleExampleTwo);
	button3.addEventListener("click", toggleExampleThree);

	function toggleExampleOne(){
		button1.classList.toggle("activated");
	}//END toggleExampleOne

	function toggleExampleTwo(event){
		event.srcElement.classList.toggle("activated");
	}//END toggleExampleTwo
	
}//END setupExample

function toggleExampleThree(event){
	event.srcElement.classList.toggle("activated")
}//END toggleExampleThree

Bây giờ, tôi sử dụng một cấu trúc như thế này khá thường xuyên - tôi có xu hướng sử dụng ví dụ 1 trong trường hợp này - nhưng mối quan tâm của tôi bây giờ là bằng cách tham chiếu các giá trị bên ngoài chức năng được gọi bởi sự kiện nhấp chuột, toàn bộ 'setupExample' sẽ được giữ trong bộ nhớ Khi tất cả những gì tôi thực sự cần là các chức năng chuyển đổi!

Ví dụ 2 hoặc 3 tốt hơn trong trường hợp này, hoặc tôi không lo lắng về không có gì và hoàn toàn không có sự khác biệt giữa ba?

Cảm ơn trước, nhìn trộm!

-P

Trong một bài tập về nhà gần đây, cuối cùng tôi đã gọi các chức năng của mình theo cách xấu xí

foo(bar(baz(moo, fab), bim(bam(ext, rel, woot, baz(moo, fab)), noob), bom, zak(bif)));
0, chương trình này đã hoạt động hoàn hảo nhưng tôi vẫn cảm thấy như mình đang làm gì đó sai.

Là những chức năng gọi như thế này thực hành xấu và nếu vậy: thay vào đó tôi nên làm gì?

Hướng dẫn are nested functions bad practice javascript - là các hàm lồng nhau thực hành không tốt javascript

BLRFL

Huy hiệu vàng 20k247 Huy hiệu bạc75 Huy hiệu đồng2 gold badges47 silver badges75 bronze badges

Hỏi ngày 17 tháng 4 năm 2016 lúc 11:06Apr 17, 2016 at 11:06

Hướng dẫn are nested functions bad practice javascript - là các hàm lồng nhau thực hành không tốt javascript

9

Điều này thực sự phụ thuộc vào số lượng làm tổ bạn sử dụng. Rốt cuộc, bạn được phép sử dụng kết quả chức năng trực tiếp trong các biểu thức để cải thiện khả năng đọc. Cả hai, mã không sử dụng các biểu thức lồng nhau (như mã trình biên dịch) và mã sử dụng quá nhiều biểu thức lồng nhau là khó đọc. Mã tốt cố gắng đạt được sự cân bằng giữa các thái cực.

Vì vậy, hãy nhìn vào một số ví dụ. Người bạn đã đưa ra trong câu hỏi của bạn có vẻ khá hợp pháp đối với tôi, vì vậy không có gì phải lo lắng ở đây. Tuy nhiên, một dòng như

foo(bar(baz(moo, fab), bim(bam(ext, rel, woot, baz(moo, fab)), noob), bom, zak(bif)));

Chắc chắn sẽ không được chấp nhận. Tương tự như vậy, mã như

double xsquare = x*x;
double ysquare = y*y;
double zsquare = z*z;
double xysquare = xsquare + ysquare;
double xyzsquare = xysquare + zsquare;
double length = sqrt(xyzsquare);

cũng sẽ không dễ đọc.

foo(bar(baz(moo, fab), bim(bam(ext, rel, woot, baz(moo, fab)), noob), bom, zak(bif)));
1 dễ hiểu hơn nhiều, mặc dù nó kết hợp tổng cộng sáu hoạt động khác nhau trong một biểu thức.

Lời khuyên của tôi là chú ý đến những biểu hiện mà bạn vẫn có thể phân tích trong đầu một cách dễ dàng. Thời điểm bạn cần có một cái nhìn thứ hai để nắm bắt những gì một biểu thức làm, đã đến lúc giới thiệu một biến bổ sung.

Đã trả lời ngày 17 tháng 4 năm 2016 lúc 20:35Apr 17, 2016 at 20:35

Hướng dẫn are nested functions bad practice javascript - là các hàm lồng nhau thực hành không tốt javascript

4

Khái niệm này dựa trên câu hỏi của bạn rất quan trọng, tôi cảm thấy nó cần một câu trả lời khác thay vì chỉ là một nhận xét (như tôi đã bắt đầu làm).

3 câu trả lời khác cho đến nay cung cấp một số điểm xem xét hữu ích về việc liệu một tình huống nhất định có xứng đáng bằng cách sử dụng những gì bạn gọi là "chức năng lồng nhau gọi" hay không. Nhưng có lẽ một điểm quan trọng hơn là ẩn trong các bình luận trong câu hỏi của bạn: Trong trường hợp bạn bỏ lỡ sự tinh tế trong những gì những người uyên bác đó đang gợi ý, Carl, bạn đã tự mình khám phá ra chủ đề thực sự được gọi là lập trình chức năng. Nếu bạn chưa bao giờ thấy thuật ngữ này, bạn có thể không nghĩ rằng đó thực sự là một "điều" trong nhận xét của @HighPerformAcemark.functional programming. If you have never seen the term, you might not have thought it was really a "thing" in @HighPerformanceMark's comment.

Nhưng thực sự nó là! Lập trình chức năng đã được viết trong nhiều thập kỷ, vì bài báo bán kết của John Hughes tại sao các vấn đề lập trình chức năng. Có một số ngôn ngữ là ngôn ngữ chức năng (nghĩa là chúng chỉ cho phép bạn viết theo kiểu lập trình chức năng), các ngôn ngữ như Erlang, Lisp, Ocaml hoặc Haskell. Nhưng có nhiều ngôn ngữ hơn là các ngôn ngữ bắt buộc/chức năng lai. Đó là, chúng là các ngôn ngữ bắt buộc theo truyền thống nhưng cũng cung cấp một số hỗ trợ cho lập trình chức năng, bao gồm Perl, C ++, Java, C#, và nhiều hơn nữa. Mục nhập của Wikipedia về lập trình chức năng cung cấp một phần đẹp cho thấy so sánh phong cách chức năng so với phong cách bắt buộc cho một số ngôn ngữ.

Có nhiều điều để nói về sự khác biệt giữa các kiểu bắt buộc và chức năng, nhưng điểm khởi đầu quan trọng là với lập trình chức năng, các chức năng hoặc phương pháp không có tác dụng phụ, làm cho nó nói chung dễ hiểu và gỡ lỗi hơn.

Để đọc thêm, bạn cũng có thể xem xét tại sao "tại sao vấn đề lập trình chức năng" quan trọng và một bài viết thú vị khác ở đây, tại sao ngôn ngữ chức năng?

Đã trả lời ngày 18 tháng 4 năm 2016 lúc 3:40Apr 18, 2016 at 3:40

Tôi nghĩ rằng nó tốt hay xấu phụ thuộc rất nhiều vào bối cảnh. Lý do chính có thể được coi là xấu là vì nó có thể làm cho mã khó đọc và gỡ lỗi hơn. Điều này đặc biệt đúng khi bạn đầu tiên học lập trình. Khi kỹ năng mã hóa và mã của bạn trở nên tiên tiến hơn, có những lúc điều này được chấp nhận.

Ví dụ, hãy xem xét một thông báo lỗi như thế này:

line 1492: missing argument "foo"

Làm thế nào để bạn biết nếu đối số bị thiếu là

foo(bar(baz(moo, fab), bim(bam(ext, rel, woot, baz(moo, fab)), noob), bom, zak(bif)));
2,
foo(bar(baz(moo, fab), bim(bam(ext, rel, woot, baz(moo, fab)), noob), bom, zak(bif)));
3 hoặc
foo(bar(baz(moo, fab), bim(bam(ext, rel, woot, baz(moo, fab)), noob), bom, zak(bif)));
4? Tùy thuộc vào ngôn ngữ, thông báo lỗi có thể cho bạn biết, nhưng nó có thể không.

Nếu đã phá vỡ các chức năng đó các cuộc gọi khác nhau và thông báo lỗi vẫn chỉ cho bạn vào dòng 1492, bạn sẽ biết ngay lập tức vấn đề nằm ở đâu:

1491: input = cashInput()
1492: parsed_value = cashParser(input)
1493: receipt = uglyReceipt(parsed_value)

Với các bước bị phá vỡ riêng biệt, việc gỡ lỗi dễ dàng hơn nhiều vì có thể đặt điểm dừng ở bất kỳ bước nào và bạn có thể dễ dàng tiêm các giá trị bằng cách thay đổi giá trị của các biến cục bộ.

Đã trả lời ngày 17 tháng 4 năm 2016 lúc 15:31Apr 17, 2016 at 15:31

Bryan Oakleybryan OakleyBryan Oakley

25K5 Huy hiệu vàng63 Huy hiệu bạc88 Huy hiệu Đồng5 gold badges63 silver badges88 bronze badges

Nó hoàn toàn không phải là một thực hành xấu nói chung. Các chức năng Call Chấp nhận các giá trị và một cách tạo ra một giá trị là bằng cách gọi một hàm khác.

Khi tôi thấy một biến được xác định, như:

parsed_value = cashParser(input)

... Tôi phải xem xét rằng

foo(bar(baz(moo, fab), bim(bam(ext, rel, woot, baz(moo, fab)), noob), bom, zak(bif)));
5 có thể được sử dụng nhiều lần và có lẽ tôi sẽ phải kiểm tra xem điều này có đúng hay không (nếu thay đổi của tôi phá vỡ thứ gì khác ở nơi khác?). Khi bạn bắt đầu thêm nhiều biến, nó có thể trở nên phức tạp hơn cho người đọc để theo dõi tất cả chúng và cách chúng có liên quan. Vì vậy, tôi cảm thấy nhẹ nhõm khi thấy:

receipt = uglyReceipt(cashParser(input))

... Bởi vì phạm vi/tuổi thọ của giá trị trung gian là rõ ràng. Bây giờ, như mọi khi, việc chia một biểu thức dài thành các câu lệnh riêng biệt có thể giúp ích, đặc biệt là nếu một tên biến có thể cho độ chính xác hơn về mục đích của một giá trị:

user_name = input()

Đã trả lời ngày 17 tháng 4 năm 2016 lúc 16:08Apr 17, 2016 at 16:08

Hướng dẫn are nested functions bad practice javascript - là các hàm lồng nhau thực hành không tốt javascript

Coredumpcoredumpcoredump

5,8151 Huy hiệu vàng20 Huy hiệu bạc27 Huy hiệu đồng1 gold badge20 silver badges27 bronze badges

Một số Pro và Con liên quan đến khả năng đọc và trải nghiệm gỡ lỗi đã được đưa ra. Một điều hiển nhiên nhất trong quan điểm của tôi vẫn còn thiếu: bằng cách xâu chuỗi các cuộc gọi lại với nhau, bạn sẽ chuyển cơ hội để kể câu chuyện logic.

Bằng cách gán kết quả trung gian cho các biến, bạn thể hiện ý nghĩa của chúng thông qua các định danh biến của bạn.

SendDoc(ReadFile(GetFilePath()), context.GetUsersByType(UserType.LoggedOn | UserType.Recent));

Đó là rất nhiều để đưa vào. Người đọc cần phân tích lại tuyên bố và đưa ra các giả định về những gì đang xảy ra hoặc không thể bị làm phiền vì nó quá nhiều. Rõ ràng một số tài liệu được gửi ...

string reportFilePath = GetFilePath;
Report report = ReadFile(reportFilePath);
Users[]  activeUsers = GetUsersByType(UserType.LoggedOn | UserType.Recent)
SendDoc(report, activeUsers);

Điều này làm cho nó dễ quản lý hơn với đầu: một báo cáo được đọc từ một tệp và được gửi đến người dùng đang hoạt động.

Nó cũng dễ dàng hơn để sửa đổi và một thay đổi sẽ dễ dàng hơn để làm theo. Nếu bạn cần thêm một bước sẽ là một hoặc nhiều dòng bổ sung hơn là tháo gỡ một lớp lót hoặc chèn thêm vào đó.

Đã trả lời ngày 25 tháng 12 năm 2021 lúc 13:06Dec 25, 2021 at 13:06

Hướng dẫn are nested functions bad practice javascript - là các hàm lồng nhau thực hành không tốt javascript

Martin Maatmartin MaatMartin Maat

16.6K3 Huy hiệu vàng26 Huy hiệu bạc53 Huy hiệu Đồng3 gold badges26 silver badges53 bronze badges

Các chức năng lồng nhau có được phép trong JavaScript không?

JavaScript cho phép làm tổ của các hàm và cấp cho hàm bên trong truy cập đầy đủ cho tất cả các biến và hàm được xác định bên trong hàm bên ngoài (và tất cả các biến và hàm khác mà hàm bên ngoài có quyền truy cập). and grants the inner function full access to all the variables and functions defined inside the outer function (and all other variables and functions that the outer function has access to).

Có ổn không khi có các chức năng bên trong các chức năng?

Thực sự tốt khi khai báo một chức năng bên trong một chức năng khác.Đây là những nhà trang trí tạo ra đặc biệt hữu ích.Tuy nhiên, theo nguyên tắc thông thường, nếu hàm này phức tạp (hơn 10 dòng), có thể là một ý tưởng tốt hơn để khai báo nó ở cấp độ mô -đun.. This is specially useful creating decorators. However, as a rule of thumb, if the function is complex (more than 10 lines) it might be a better idea to declare it on the module level.

Có tệ khi gọi một hàm bên trong một hàm không?

Gọi các chức năng trong các chức năng khác là một điều hoàn toàn bình thường và được mong đợi.Hầu như mọi chương trình sẽ liên quan đến việc đó.. Almost every program will involve doing that.

Các chức năng trợ giúp có nên được lồng nhau?

Bạn nên đặt nó ở phạm vi toàn cầu, vì một số lý do.Nesting một hàm trợ giúp vào người gọi làm tăng chiều dài của người gọi.Chiều dài chức năng hầu như luôn luôn là một chỉ số tiêu cực;Các chức năng ngắn dễ hiểu hơn, để ghi nhớ, gỡ lỗi và duy trì.Nesting a helper function into the caller increases the length of the caller. Function length is almost always a negative indicator; short functions are easier to understand, to memorize, to debug and to maintain.