Tự đóng cửa ẩn danh: JavaScript chưa hoàn chỉnh?


18

Có phải thực tế là việc đóng chức năng tự tham chiếu ẩn danh rất phổ biến trong JavaScript cho thấy JavaScript là một đặc tả không đầy đủ? Chúng tôi thấy rất nhiều điều này:

(function () { /* do cool stuff */ })();

và tôi cho rằng tất cả mọi thứ là một vấn đề của hương vị, nhưng điều này không giống như một loại bùn, khi tất cả những gì bạn muốn là một không gian tên riêng tư? JavaScript không thể triển khai các gói và các lớp thích hợp?

So sánh với ActionScript 3, cũng dựa trên ECMAScript, nơi bạn nhận được

package com.tomauger {
  import bar;
  class Foo {
     public function Foo(){
       // etc...
     }

     public function show(){
       // show stuff
     }

     public function hide(){
       // hide stuff
     }
     // etc...
  }
}

Tương phản với các kết quả mà chúng tôi thực hiện trong JavaScript (điều này, từ tài liệu tác giả plugin jQuery ):

(function( $ ){

  var methods = {
    init : function( options ) { // THIS },
    show : function( ) { // IS   },
    hide : function( ) { // GOOD },
    update : function( content ) { // !!! }
  };

  $.fn.tooltip = function( method ) {

    // Method calling logic
    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
    }    

  };

})( jQuery );

Tôi đánh giá cao rằng câu hỏi này có thể dễ dàng biến thành một câu nói hay về sở thích và phong cách lập trình, nhưng tôi thực sự rất tò mò muốn nghe các lập trình viên dày dạn cảm nhận về điều này như thế nào và liệu nó có cảm thấy tự nhiên không, như học các ngôn ngữ khác nhau của ngôn ngữ mới, hay không , giống như một cách giải quyết cho một số thành phần ngôn ngữ lập trình cơ bản mà không được thực hiện?


22
"Không thể JavaScript triển khai ... các lớp thích hợp?" Không. Nó đã có nguyên mẫu thích hợp. Nguyên mẫu không thua kém các lớp. Họ khác nhau. Mọi người đã thử thêm các lớp vào JavaScript vào nhiều thời điểm và khá không thành công.
Rein Henrichs

5
@Rein: Nhưng bằng cách nào đó ActionScript đã quản lý nó ...
Mason Wheeler

8
@Tom không có "các lớp tích hợp". Không có thứ gọi là một lớp trong ngôn ngữ nguyên mẫu . Bạn tiếp tục xáo trộn hai mô hình.
Rein Henrichs

1
Cá nhân tôi thấy tính năng ngôn ngữ hàm ẩn danh linh hoạt hơn các lớp. Tuy nhiên tôi thích lập trình chức năng trong đó thành ngữ này là phổ biến.
dietbuddha

1
Đối với những người khác, ở đây: brianodell.net/?page_id=516 là một mồi tuyệt vời về JavaScript như một ngôn ngữ nguyên mẫu.
Tom Auger

Câu trả lời:


9

Tôi cho rằng tất cả mọi thứ là một vấn đề của hương vị, nhưng điều này không giống như một loại bùn, khi tất cả những gì bạn muốn là một không gian tên riêng tư? JavaScript không thể triển khai các gói và các lớp thích hợp?

Hầu hết các ý kiến ​​đều tranh luận về huyền thoại rằng "nguyên mẫu là lớp người nghèo", vì vậy tôi sẽ chỉ nhắc lại rằng OO dựa trên nguyên mẫu không thua kém bất kỳ cách nào đối với OO dựa trên lớp.

Điểm khác "một loại bùn khi tất cả những gì bạn muốn nó là một không gian tên riêng tư". Bạn có thể ngạc nhiên khi biết rằng Scheme sử dụng cùng loại bùn chính xác để xác định phạm vi. Điều đó đã không dừng lại để trở thành ví dụ điển hình về phạm vi từ vựng được thực hiện tốt.

Tất nhiên, trong Scheme, 'kydge' được ẩn đằng sau các macro ....


1
Bạn không đưa ra bằng chứng nào để sao lưu khẳng định của mình rằng Scheme là ví dụ chính về phạm vi từ vựng được thực hiện tốt, hoặc điều này có liên quan đến cách Scheme sử dụng các hàm để xác định phạm vi.
DeadMG

Không thể nói với Scheme là một ví dụ điển hình nhưng một ví dụ về đồng sáng lập JS Brendan Eich thảo luận về Scheme đóng vai trò trong thiết kế của JS ở đây: readwrite.com/2011/07/22/javascript-was-no-accident
Erik Reppen

7

Trước hết, một vài điều:

  1. Một cách khác để xem JavaScript là 1 triệu và 1 điều bạn có thể làm với chức năng như một cấu trúc. Đó là tất cả nếu bạn tìm kiếm nó. Nó không bao giờ xa chức năng.

  2. Điều đó tác giả trình cắm thêm jQuery là khủng khiếp. Tôi không biết tại sao họ lại ủng hộ điều đó. Các tiện ích mở rộng $ phải là công cụ sử dụng chung mà $ đã có các phương thức tiện ích hoàn chỉnh không được xây dựng tốt. Đây là một công cụ chuẩn hóa DOM-API. Nó được sử dụng tốt nhất được chôn trong các đồ vật của riêng bạn. Tôi không thấy sự hấp dẫn của việc sử dụng nó như một kho lưu trữ thư viện UI đầy đủ.

Các gói trên Web phía khách hàng là vô nghĩa

Điều cá nhân tôi không thích về các gói trên web phía khách hàng là về cơ bản chúng tôi đang giả vờ rằng chúng tôi đang làm một việc mà chúng tôi thực sự không làm. Trong một bài viết .NET webforms và gobs-of-horrifying-Stuff-that-never-pans-out-from-our-Java-friends, tôi thà nghĩ về một đống HTML với các tài nguyên được liên kết như những gì nó thực sự là và không cố gắng xoa dịu các nhà phát triển ứng dụng hệ điều hành mới chống lại việc học bằng cách giả vờ đó là một cái gì đó khác. Trong JS trên web phía máy khách, không có gì bị chặn "nhập khẩu" khi làm điều gì đó khủng khiếp với Ajax hoạt động trong sự thờ ơ của bộ nhớ đệm trình duyệt, điều mà vâng, nhiều người đã cố gắng làm. Tất cả những gì quan trọng đối với trình duyệt là nó đã được tải vào và diễn giải hoặc không. Chúng tôi không có thêm mã được lưu trữ trên máy khách ở đâu đó có sẵn để sử dụng "chỉ trong trường hợp" vì những lý do tốt # 1 là tôi vừa mô tả một phụ thuộc bổ trợ trình cắm và trình duyệt cho các ứng dụng web vì hiện tượng nhìn chung không hoạt động tốt lắm. Chúng tôi muốn có web ngay bây giờ. Không phải sau khi Adobe hay Sun hoàn thành cập nhật lần thứ ba trong tuần này.

Ngôn ngữ có những gì nó cần cho cấu trúc

Các đối tượng JS có tính đột biến cao. Chúng ta có thể phân nhánh các không gian tên ở bất kỳ mức độ nào mà chúng ta thấy hữu ích để làm như vậy và nó rất dễ thực hiện. Nhưng vâng, đối với bất cứ điều gì có thể sử dụng lại, bạn phải bám vào thư mục gốc của bất kỳ thư viện nào trên không gian toàn cầu. Tất cả các phụ thuộc đều được liên kết và tải cùng một lúc, vì vậy quan điểm của việc làm gì khác là gì? Điểm tránh không gian tên toàn cầu không phải là bất cứ điều gì xấu. Đó là quá nhiều thứ xấu vì bạn có nguy cơ va chạm không gian tên hoặc vô tình ghi đè các tính năng ngôn ngữ cốt lõi.

Chỉ vì nó phổ biến không có nghĩa là chúng ta đang làm đúng

Bây giờ khi bạn thấy tất cả điều này trên một ứng dụng web phía khách hàng:

(function(){
//lots of functions defined and fired and statement code here
})()

Vấn đề không phải là chúng ta thiếu công cụ để cấu trúc một ứng dụng, vấn đề là mọi người không định giá cấu trúc. Đối với các trang web vứt bỏ tạm thời 2-3 trang tại một cơ quan thiết kế, tôi thực sự không có vấn đề gì với điều đó. Nơi nó trở nên xấu xí là khi bạn phải xây dựng một thứ gì đó có thể bảo trì và dễ đọc và dễ sửa đổi.

Nhưng khi bạn đến nơi chỉ cần thực hiện tất cả các đối tượng và nhà máy có thể sử dụng lại và có thể một hoặc hai bình tạm thời mới có thể len ​​lỏi vào quá trình đó, thật tiện lợi.

Nhưng có triển khai JS với các gói / mô-đun

Hãy nhớ rằng trong Node.js, nơi những thứ như vậy có ý nghĩa hơn nhiều, chúng có các mô-đun. JS, giả sử chúng ta có thể tránh uber-config-hell gây khó khăn cho các ngôn ngữ khác, là điều duy nhất trong phương trình và mỗi tệp được thực thi là phạm vi riêng biệt của nó. Nhưng trên một trang web, liên kết một tệp js tự nó là câu lệnh nhập. Việc nhập nhiều hơn một cách nhanh chóng chỉ là lãng phí thời gian và tài nguyên vì việc lấy tài nguyên đòi hỏi nhiều nỗ lực hơn là chỉ cần thêm liên kết vào tệp khi bạn cần chúng biết rằng chúng sẽ được lưu trong bộ nhớ cache nếu một trang khác cần lại chúng. Vì vậy, đang cố gắng phân tách không gian toàn cầu bằng cách làm bất cứ điều gì khác ngoài việc tạo các nhà máy đối tượng bộ điều hợp như jQuery hoặc các đối tượng truyền thống hơn bao gồm một tập hợp lớn các nhiệm vụ trong một miền nhất định trong khi chiếm một vị trí trên toàn cầu. Cóhttp://wiki.ecmascript.org/doku.php?id=harmony:modules

Vì vậy, không có gì sai với những người tự động sử dụng để tránh ô nhiễm không gian tên toàn cầu khi có lý do chính đáng để sử dụng những thứ đó (thường xuyên hơn là không có). Và chúng ta có các thuộc tính tương đương riêng tư liên tục trong các đối tượng của mình (chỉ cần xác định một var trong hàm tạo và không hiển thị nó như một thuộc tính).

Thực tế là chúng ta CÓ THỂ làm những việc như vậy, tuy nhiên, thật tuyệt vời. Việc sử dụng nhiều là một dấu hiệu cho thấy các nhà phát triển JS vẫn đang trưởng thành, nhưng đó không phải là lỗ hổng trong ngôn ngữ đối với bất kỳ ai không cố gắng áp dụng một mô hình vào web phía khách hàng mà không có ý nghĩa ở đây.


Đối với người bỏ phiếu, bạn có thể giải thích tại sao không? Khi ai đó viết nhiều như vậy tôi nghĩ rằng anh ấy xứng đáng được giải thích!
Songo

+1 câu trả lời tốt, không chắc tại sao lại bỏ phiếu trước.
vui mừng

Tuyệt vời viết lên và quan điểm tuyệt vời. Tôi cũng thích "chỉ vì đó là một trope không có nghĩa là nó đúng." Tôi nghĩ vấn đề của tôi là tôi cảm thấy thoải mái hơn với các ngôn ngữ chặt chẽ hơn, điều này (IMO) giúp phát triển hiệu quả theo một số cách. JavaScript có vẻ thực sự mơ hồ với không nhiều kiểm tra và số dư được xây dựng: bạn có thể làm bất cứ điều gì bạn muốn, do đó cảnh quan ngoài kia là một mớ hỗn độn của các thành ngữ và thực tiễn. Thật khó để tìm ra cách "đúng" để tiếp cận cấu trúc mã hóa của bạn. Mặc dù tôi đồng ý rằng đối với những công việc 1 lần nhanh chóng, đây không phải là một mối quan tâm lớn.
Tom Auger

1
IMO, có rất nhiều điều bạn có thể làm với rất nhiều sợi dây ngoài việc tự treo cổ và bạn học cách viết mã mạnh mẽ nhanh hơn từ việc tự treo thỉnh thoảng xảy ra ít khi bạn phát triển thói quen tốt hơn, nhưng tôi sẽ không giả vờ tất cả mọi người hoặc một ứng cử viên lý tưởng cho mọi công việc. Tôi nghi ngờ rằng bạn càng tìm hiểu về nó, tuy nhiên, bạn sẽ càng dễ chịu hơn. Tôi cảm thấy như mình bị thiếu một nửa bộ não khi cố gắng thực hiện mọi thứ bằng ngôn ngữ mà không có chức năng hoặc đối tượng hạng nhất linh hoạt / có thể thay đổi như của JS.
Erik Reppen

4

Một điều khác bạn đang thiếu là javscript phải tương thích ngược. Nếu bạn cố gắng giới thiệu cú pháp gói, nó thực sự có thể phá vỡ web theo một số cách điên rồ. Điều đó sẽ rất tệ! Doug Crockford đã nói về điều này ở nhiều điểm khác nhau và tại sao những nỗ lực để thêm nó đã thất bại.


Đó là một điểm hay. Nhưng ActionScript vẫn quản lý nó, bằng cách đưa ra một phiên bản mới. Khi xác định thẻ tập lệnh của bạn, bạn luôn có thể chỉ định phiên bản JavaScript, do đó, việc "phá vỡ" các trang web hiện tại sẽ không thành vấn đề.
Tom Auger

1
Trong thực tế hầu hết các thẻ script trên mạng không có số phiên bản. Thành thật mà nói tôi không chắc chắn về tất cả các vấn đề về vấn đề này, nhưng tôi biết rằng những người nghĩ về công cụ này đã quyết định rằng điều đó là không thể.
Zachary K

1
@Tom: Adobe cũng có toàn quyền kiểm soát nền tảng Flash. Không một thực thể nào có toàn quyền kiểm soát tất cả các nền tảng JS ngoài kia. Ngoài ra, chỉ cần xử lý số phiên bản cho tập lệnh JS trong trình duyệt sẽ có nghĩa là bạn không hỗ trợ các trình duyệt cũ hơn hoặc phải viết hai tập lệnh. Vì vậy, nó một vấn đề.
Jeremy Heiler

2

Vâng, nó là một loại bùn.

Rất nhiều người đang nói rằng "nguyên mẫu không thua kém các lớp". Tôi không đồng ý, nhưng đó là vấn đề ưu tiên. Nhưng đó thậm chí không phải là vấn đề thực sự với JavaScript - vấn đề là ban đầu nó được thiết kế như một ngôn ngữ kịch bản nhanh và bẩn để tạo ra những thứ như các nút hoạt hình. Trở lại giữa những năm 90, không ai từng nghĩ rằng JavaScript sẽ được yêu cầu làm một số thứ điên rồ mà nó đang làm bây giờ.


6
Tôi không đồng ý, ngôn ngữ JavaScript thực sự tuyệt vời. Rằng nó được gộp chung với một DOM được chỉ định và không tương thích lẫn nhau là nơi tất cả các vấn đề bắt đầu.
Dean Harding

2
Điều này có liên quan gì đến nguyên mẫu?
Erik Reppen

2

Các hàm tự gọi ẩn danh gần giống với các mô-đun hơn là các lớp. Thật khó chịu khi mặc định cho javascript là chạy trong phạm vi toàn cầu. Ủy ban làm việc trên JS.next đang nghiêm túc xem xét việc thêm các mô-đun, để bạn không bỏ các biến cục bộ của mình vào phạm vi toàn cầu. May mắn thay, các chức năng của Javascript có ngữ nghĩa thuận tiện đến mức chúng ta có thể sử dụng một chức năng ẩn danh như một phạm vi riêng tư một cách dễ dàng.

Tôi không thấy cách các lớp thực sự tham gia vào cuộc thảo luận, ngoại trừ việc chúng là cấu trúc phạm vi cấp cao nhất trong nhiều ngôn ngữ. Một mô-đun / gói / xin vui lòng-cho-tôi-a-local-scope-so-i-đừng-rời-my-biến-trong-toàn cầu-môi trường toàn cầu sẽ rất tốt để có.


1

Bạn có thể muốn xem ExtJS 3 và 4 nơi họ đã quản lý để triển khai không gian tên khá tốt.

- được thêm sau -1

Quan điểm của tôi ở đây là, có thể ẩn tất cả các 'kết luận' này và vẫn có mã khá thân thiện như vậy:

Ext.ns('com.tomauger');
Ext.Loader.load('bar.js'); //unfortunately filname needs to be used
MyNameSpace.Foo = {
   //...
}
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.