Tại sao việc đóng cửa lại quan trọng đối với JavaScript?


16

Biểu thức lambda của C # cũng có các bao đóng nhưng hiếm khi được thảo luận bởi các cộng đồng hoặc sách của C #. Tôi thấy nhiều người và sách JavaScript nói về sự đóng cửa của nó hơn là trong thế giới C #. Tại sao vậy?


3
Bởi vì JavaScript được coi là ngôn ngữ chức năng hạng nhất và C # là một ngôn ngữ OOP cổ điển. Mô hình khác nhau, phong cách lập trình khác nhau.
Raynos

1
Có chức năng hạng nhất làm cho ngôn ngữ trở thành ngôn ngữ chức năng. PHP (kể từ 5.3), python hoặc D có chức năng hạng nhất. Bạn có thể nói rằng chúng là ngôn ngữ chức năng? Chắc chắn là không, và javascript cũng vậy.
deadalnix

1
@deadalnix JavaScript là một ngôn ngữ đa mô hình. Nó chủ yếu hỗ trợ mô hình OO theo thủ tục, chức năng và nguyên mẫu. Đó không phải là ngôn ngữ chức năng thuần túy , nhưng bạn có thể dễ dàng viết javascript trong mô hình chức năng mà không cần bẻ cong ngôn ngữ. Tôi sẽ nói giống như của C # và python.
Raynos

3
@deadalnix, một ngôn ngữ cho phép bạn xác định tổ hợp Y là ngôn ngữ chức năng. Theo định nghĩa.
SK-logic

1
@deadalnix: Tôi cho rằng những gì nó đi xuống là câu hỏi về cách tiếp cận được thúc đẩy bởi ngôn ngữ. Có nhiều khung và nền tảng JavaScript (đáng chú ý là node.js và DOM (mô hình sự kiện)) phụ thuộc nhiều vào các hàm thứ tự đầu tiên. PHP có các tính năng cho phép cùng một kiểu lập trình, nhưng nếu bạn xem API tiêu chuẩn hoặc nhiều khung công tác, thì bạn sẽ thấy nó không thực sự là cốt lõi của ngôn ngữ.
back2dos

Câu trả lời:


5

Bởi vì javascript không có tính năng như không gian tên và bạn có thể gây rối khá dễ dàng với tất cả các loại đối tượng toàn cầu.

Vì vậy, điều quan trọng là có thể cô lập một số mã trong môi trường thực thi của chính nó. Đóng cửa là hoàn hảo cho điều đó.

Việc sử dụng bao đóng này không có ý nghĩa trong một ngôn ngữ như C # nơi bạn có không gian tên, lớp và vv để cô lập mã và không đặt mọi thứ trong phạm vi toàn cầu.

Một thực tế rất phổ biến đối với mã javascript là viết nó như thế này:

(function(){
    // Some code
})();

Như bạn có thể thấy, đây là một khai báo hàm ẩn danh, ngay sau đó là sự thực thi của nó. Do đó, mọi thứ được xác định trong hàm là không thể truy cập từ bên ngoài và bạn sẽ không làm rối phạm vi toàn cầu. Bối cảnh thực thi của hàm này sẽ vẫn tồn tại miễn là một số mã sử dụng nó, giống như các hàm lồng nhau được xác định trong ngữ cảnh này, mà bạn có thể chuyển như gọi lại hoặc bất cứ điều gì.

Javascript là một ngôn ngữ rất khác so với C #. Nó không hướng đối tượng, nó là định hướng nguyên mẫu. Điều này dẫn đến thực tiễn rất khác nhau ở cuối.

Dù sao, đóng cửa là tốt, vì vậy hãy sử dụng chúng, ngay cả trong C #!

EDIT: Sau một số thảo luận về trò chuyện của stackoverflow, tôi nghĩ rằng anwer này phải được ưu tiên.

Hàm trong mã mẫu không phải là một bao đóng. Tuy nhiên, fucntion này có thể định nghĩa các biến cục bộ và các hàm lồng nhau. Tất cả các hàm lồng nhau sử dụng các biến cục bộ này là các bao đóng.

Điều này là hữu ích để chia sẻ một số dữ liệu trên một tập hợp các chức năng mà không làm rối phạm vi toàn cầu. Đây là cách sử dụng phổ biến nhất của đóng trong javascript.

Việc đóng cửa mạnh mẽ hơn nhiều so với việc chỉ chia sẻ một số dữ liệu như thế này, nhưng hãy thực tế, hầu hết các lập trình viên không biết gì về lập trình hàm. Trong C #, bạn sẽ sử dụng lớp hoặc không gian tên cho các loại sử dụng này, nhưng JS không cung cấp chức năng này.

Bạn có thể làm nhiều cách hơn với việc đóng cửa hơn là chỉ bảo vệ phạm vi toàn cầu, nhưng đây là những gì bạn sẽ thấy trong mã nguồn JS.


9
Đó không phải là một đóng cửa. Bạn mô tả lợi thế của việc sử dụng các hàm để tạo phạm vi cục bộ.
Raynos

2
một bao đóng chỉ là một bao đóng nếu nó đóng trên các biến miễn phí. Cũng cảm ơn bạn đã cho tôi biết tôi không biết JavaScript hoạt động như thế nào :)
Raynos

2
thay vào đó, dùng đến việc làm suy yếu tôi bằng cách gọi cho tôi một người mới bắt đầu, vui lòng đưa ra các đối số thực tế trong phòng Trò chuyện JavaScript SO . Cuộc thảo luận này không thực sự thuộc về nơi này, nhưng tôi sẽ vui vẻ thảo luận về những quan niệm sai lầm của bạn trong cuộc trò chuyện SO.
Raynos

1
Bị hạ bệ. JavaScript là nhiều đối tượng hướng. Nó chỉ không dựa trên lớp nhưng chức năng như vậy dễ dàng được tác giả. Nó có các chức năng hạng nhất, tận dụng các bao đóng để làm cho nó phù hợp tự nhiên cho các mô hình hướng sự kiện nặng nề, và nguồn cảm hứng chính theo tác giả của nó, Brendan Eich, là Scheme. Tôi không thực sự chắc chắn bạn nghĩ ngôn ngữ chức năng là gì, nhưng điều thú vị là dường như bạn nghĩ rằng kế thừa dựa trên lớp là một cách quan trọng thay vì không còn hoàn toàn cần thiết khi bạn có thể chuyển các chức năng xung quanh và áp dụng chúng trong bối cảnh mới.
Erik Reppen

2
-1 cũng vậy. Điều này không mô tả đóng cửa, nó mô tả phạm vi.
Izkata

12

Có lẽ bởi vì việc triển khai phổ biến hướng đối tượng của JavaScript phụ thuộc vào các bao đóng. Hãy xem xét một ví dụ đơn giản:

function counter() {
   var value = 0;
   this.getValue = function() { return value; }
   this.increase = function() { value++; }
}

var myCounter = new counter();
console.log(myCounter.getValue());
myCounter.increase();
console.log(myCounter.getValue());

Các phương thức getValueincreasetrong thực tế đóng, đóng gói các biến value.


3
-1 "phụ thuộc vào việc đóng cửa" Điều đó rất chủ quan. Nó không.
Raynos

Raynos: quan tâm chỉ cho chúng tôi cách tạo và sử dụng các thành viên tư nhân mà không cần đóng cửa?
user281377

1
@ammoQ không có thứ gọi là riêng tư trong JavaScript. Ý bạn là "bởi vì mô phỏng OO cổ điển của JavaScript phụ thuộc vào việc đóng cửa". JavaScript OO là nguyên mẫu là một mô hình khác nhau. Đó là một câu trả lời hay cho câu hỏi, "Chúng tôi sử dụng các bao đóng trong JavaScript vì cần phải mô phỏng OO cổ điển"
Raynos

1
@keppla Ý tôi là "OO phụ thuộc vào việc đóng cửa" là chủ quan. Bạn không cần phải đóng cửa cho OO cả.
Raynos

2
bạn đang phơi bày tôi là người điếm tôi ...
user281377

4

Bởi vì nhiều thư viện làm cho JavaScript 'có thể chịu được' sử dụng chúng.

Hãy xem JQuery , Prototype hoặc MooTools , chỉ để đặt tên cho ba phổ biến. Mỗi thư viện đó cung cấp một eachphương thức cho các bộ sưu tập của họ như là cách lặp ưa thích, sử dụng hàm lặp. Hàm đó, khi truy cập các giá trị trong phạm vi bên ngoài, sẽ là một bao đóng:

[1,2,3].each(function(item) {
   console.log(item);
});

Và nó không dừng lại ở đó: Các cuộc gọi lại trong Ajax, xử lý sự kiện trong Ext.js, v.v.


1
Tại sao nó không phải là một đóng cửa? console.logđược xác định trong một phạm vi bên ngoài, do đó, consolemột 'biến miễn phí'. Và, tại sao, trong thực tế, một vòng lặp for, không có gì khác biệt, một thực tiễn xấu?
keppla

@Raynos: định nghĩa đóng của tôi là 'khối chứa biến miễn phí', nó không làm mất trạng thái đó, biến miễn phí xảy ra ở phạm vi trên cùng. Nhưng, để hỗ trợ quan điểm của tôi, hãy xem xét phương pháp này: pastie.org/2144689 . Tại sao điều này nên xấu?
keppla

Tôi vẫn nghĩ rằng "đóng cửa" đối với dữ liệu toàn cầu được coi là gian lận. Tôi đồng ý rằng việc truy cập dữ liệu lên chuỗi phạm vi là tốt, đơn giản là thực hành tốt để giảm thiểu quyền truy cập đó.
Raynos

Đồng ý về việc giảm thiểu truy cập
keppla

Cần lưu ý rằng với các trình vòng lặp mảng (forEach, map, less, v.v.) không có lý do gì để chúng bị đóng, chúng có tất cả trạng thái được truyền trực tiếp vào chúng. Tôi sẽ coi đó là một mô hình chống đối với họ sẽ bị đóng cửa
Raynos

3

Tôi đồng ý với các câu trả lời khác rằng mã hóa "tốt" với JavaScript phụ thuộc nhiều hơn vào các bao đóng. Tuy nhiên, bên cạnh đó, có lẽ chỉ là một câu hỏi về tính năng đã tồn tại bao lâu trong mỗi ngôn ngữ. JavaScript về cơ bản đã đóng cửa kể từ khi triển khai sớm nhất. Mặt khác, C # chỉ có chúng kể từ 3.0, được phát hành cùng với Visual Studio 2008.

Rất nhiều lập trình viên C # tôi chạy vào vẫn đang làm việc trên các dự án 2.0. Và ngay cả khi họ đang làm việc trong 3.0 hoặc 4.0, họ vẫn thường sử dụng thành ngữ 2.0. Tôi yêu sự khép kín; hy vọng chúng sẽ được sử dụng nhiều hơn trong C # khi khái niệm này lan truyền giữa các nhà phát triển C #.


2

Lý do chính là vì C # được gõ tĩnh và các chức năng chỉ có quyền truy cập vào một môi trường duy nhất, được xác định trước, cản trở tính hữu ích của việc đóng cửa.

Mặt khác, trong JavaScript, các bao đóng cho phép các hàm hoạt động như các phương thức khi được truy cập như một thuộc tính đối tượng và là các đối tượng hạng nhất, chúng cũng có thể được đưa vào các môi trường khác nhau cho phép các chương trình con hoạt động trong các bối cảnh khác nhau.


1
Gõ tĩnh phải làm gì với điều này? Đóng cửa là trực giao.

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.