Mẫu mô-đun JavaScript với ví dụ [đã đóng]


136

Tôi không thể tìm thấy bất kỳ ví dụ có thể truy cập nào cho thấy cách hai (hoặc nhiều) mô-đun khác nhau được kết nối để làm việc cùng nhau.

Vì vậy, tôi muốn hỏi liệu có ai có thời gian để viết một ví dụ giải thích cách các mô-đun làm việc cùng nhau không.


Điều này đã thay đổi tất cả trong bốn năm qua, nhưng nhờ sự tiết chế quá mức, thông tin lỗi thời này sẽ tồn tại mãi mãi . Đây là trang MDN trên các mô-đun ES6.
bbsimonbb

Câu trả lời:


256

Để tiếp cận với mẫu thiết kế Modular, trước tiên bạn cần hiểu các khái niệm này:

Biểu hiện chức năng được gọi ngay lập tức (IIFE):

(function() {
      // Your code goes here 
}());

Có hai cách bạn có thể sử dụng các chức năng. 1. Khai báo hàm 2. Biểu thức hàm.

Dưới đây là sử dụng biểu thức chức năng.

Không gian tên là gì? Bây giờ nếu chúng ta thêm không gian tên vào đoạn mã trên thì

var anoyn = (function() {
}());

Đóng cửa trong JS là gì?

Điều đó có nghĩa là nếu chúng ta khai báo bất kỳ hàm nào với bất kỳ phạm vi biến / bên trong hàm khác (trong JS chúng ta có thể khai báo một hàm bên trong hàm khác!) Thì nó sẽ luôn tính phạm vi hàm đó. Điều này có nghĩa là bất kỳ biến nào trong chức năng bên ngoài sẽ luôn được đọc. Nó sẽ không đọc biến toàn cục (nếu có) có cùng tên. Đây cũng là một trong những mục tiêu của việc sử dụng mô hình thiết kế mô-đun để tránh xung đột đặt tên.

var scope = "I am global";
function whatismyscope() {
    var scope = "I am just a local";
    function func() {return scope;}
    return func;
}
whatismyscope()()

Bây giờ chúng tôi sẽ áp dụng ba khái niệm tôi đã đề cập ở trên để xác định mẫu thiết kế mô-đun đầu tiên của chúng tôi:

var modularpattern = (function() {
    // your module code goes here
    var sum = 0 ;

    return {
        add:function() {
            sum = sum + 1;
            return sum;
        },
        reset:function() {
            return sum = 0;    
        }  
    }   
}());
alert(modularpattern.add());    // alerts: 1
alert(modularpattern.add());    // alerts: 2
alert(modularpattern.reset());  // alerts: 0

jsfiddle cho mã ở trên.

Mục tiêu là để che giấu khả năng tiếp cận biến đổi từ thế giới bên ngoài.

Hi vọng điêu nay co ich. Chúc may mắn.


đặt tên cho iife sẽ tốt hơn? cho mục đích ngữ nghĩa và theo dõi ngăn xếp tốt hơn? nó sẽ thay đổi bất cứ điều gì trong mã?
Jeroen

2
Ví dụ đầu tiên của bạn (function() { /* Your code goes here */}());thực sự là IIFE (Gọi ngay biểu thức hàm), ok nó là ẩn danh vì nó không có tên nên bạn thậm chí có thể muốn gọi nó là IIAFE (Gọi ngay biểu thức hàm ẩn danh) xem thêm về IIFE trên stackoverflow.com/questions/ 2421911 / Lọ
Adrien Be

Tại sao tuyên bố trả lại đã được sử dụng? nếu chúng ta bỏ qua return {} thì chức năng thêm và đặt lại sẽ được công khai và tôi đoán họ có thể truy cập tổng biến cục bộ? tôi có đúng không
Mou

ví dụ thứ hai của bạn trông giống như một đối tượng hoặc tôi không đúng?
Lý do

4
Điều này không giải quyết câu hỏi của OP. Đây là một mô tả về mẫu mô-đun không phải là một ví dụ về cách nhiều mô-đun có thể làm việc cùng nhau như OP muốn.
Erik Trautman

39

Tôi thực sự muốn giới thiệu bất cứ ai tham gia chủ đề này để đọc cuốn sách miễn phí của Addy Osmani:

"Học các mẫu thiết kế JavaScript".

http://addyosmani.com/resource/essentialjsdesignpotypes/book/

Cuốn sách này đã giúp tôi rất nhiều khi tôi bắt đầu viết JavaScript dễ bảo trì hơn và tôi vẫn sử dụng nó làm tài liệu tham khảo. Hãy nhìn vào các triển khai mô hình mô-đun khác nhau của anh ấy, anh ấy giải thích chúng thực sự tốt.


Tôi cũng khuyên bạn nên đọc bài viết của mình về "Mô hình mô đun dứt khoát" không có trong cuốn sách của Addy Osmani: github.com/tfmontague/definitive-module-potype
tfmontague 7/07/14

1
Làm thế nào điều này so sánh với "Các mẫu JavaScript" của Stoyan Stefanov
JohnMerlino

4
Cuốn sách của Stoyan toàn diện hơn nhiều. Nó không chỉ bao gồm các mẫu mức cao mà còn nói sâu hơn về các thực tiễn tốt nhất khác của JS.
Mã Novitiate

1
đánh giá về "Học các mẫu thiết kế JavaScript" amazon.com/product-reviews/1449331815
Adrien Be

3
đánh giá về "Các mẫu JavaScript" của Stoyan Stefanov amazon.com/product-reviews/0596806752 . Lưu ý: có vẻ tốt hơn nhiều so với từ "Học các mẫu thiết kế JavaScript"
Adrien Be

19

Tôi nghĩ rằng tôi sẽ mở rộng câu trả lời ở trên bằng cách nói về cách bạn kết hợp các mô-đun với nhau vào một ứng dụng. Tôi đã đọc về điều này trong cuốn sách crockford doug nhưng chưa quen với javascript, tất cả vẫn còn một chút bí ẩn.

Tôi đến từ nền tảng ac # vì vậy đã thêm một số thuật ngữ tôi thấy hữu ích từ đó.

Html

Bạn sẽ có một số tệp html cấp cao nhất. Nó giúp nghĩ về điều này như tập tin dự án của bạn. Mọi tệp javascript bạn thêm vào dự án đều muốn đi vào điều này, thật không may là bạn không nhận được hỗ trợ công cụ cho việc này (Tôi đang sử dụng IDEA).

Bạn cần thêm tệp vào dự án với các thẻ script như thế này:

        <script type="text/javascript" src="app/native/MasterFile.js" /></script>
        <script type="text/javascript" src="app/native/SomeComponent.js" /></script>

Nó xuất hiện làm sập các thẻ khiến mọi thứ thất bại - trong khi có vẻ như xml thực sự là một thứ gì đó với các quy tắc điên rồ hơn!

Không gian tên tập tin

MasterFile.js

myAppNamespace = {};

đó là nó. Đây chỉ là để thêm một biến toàn cục duy nhất cho phần còn lại của mã của chúng tôi. Bạn cũng có thể khai báo các không gian tên lồng nhau ở đây (hoặc trong các tệp của riêng họ).

Mô-đun

Một sốComponent.js

myAppNamespace.messageCounter= (function(){

    var privateState = 0;

    var incrementCount = function () {
        privateState += 1;
    };

    return function (message) {
        incrementCount();
        //TODO something with the message! 
    }
})();

Những gì chúng ta đang làm ở đây là gán một hàm đếm tin nhắn cho một biến trong ứng dụng của chúng ta. Đây là một hàm trả về một hàm mà chúng ta thực thi ngay lập tức .

Các khái niệm

Tôi nghĩ rằng nó giúp nghĩ về dòng trên cùng trong Một số thành phần là không gian tên nơi bạn đang khai báo một cái gì đó. Nhắc nhở duy nhất cho điều này là tất cả các không gian tên của bạn cần xuất hiện trong một số tệp khác trước - chúng chỉ là các đối tượng được bắt nguồn từ biến ứng dụng của chúng tôi.

Hiện tại tôi chỉ thực hiện các bước nhỏ với điều này (tôi đang cấu trúc lại một số javascript bình thường từ một ứng dụng extjs để tôi có thể kiểm tra nó) nhưng có vẻ khá hay vì bạn có thể xác định các đơn vị chức năng nhỏ trong khi tránh được vũng lầy của 'điều này ' .

Bạn cũng có thể sử dụng kiểu này để xác định các hàm tạo bằng cách trả về một hàm trả về một đối tượng có một tập hợp các hàm và không gọi nó ngay lập tức.


6

Tại đây https://toddmotto.com/mastering-the-module-potype bạn có thể tìm thấy mô hình được giải thích kỹ lưỡng. Tôi sẽ nói thêm rằng điều thứ hai về JavaScript mô-đun là cách cấu trúc mã của bạn trong nhiều tệp. Nhiều người có thể khuyên bạn nên đi với AMD, nhưng tôi có thể nói từ kinh nghiệm rằng bạn sẽ kết thúc ở một số điểm với phản hồi trang chậm vì nhiều yêu cầu HTTP. Cách thoát là biên dịch trước các mô-đun JavaScript của bạn (một cho mỗi tệp) thành một tệp theo tiêu chuẩn CommonJS. Hãy xem các mẫu tại đây http://dsheiko.github.io/cjsc/


Tất cả các triển khai AMD cũng cung cấp tiền biên dịch thành một tệp duy nhất.
I-Lin Kuo

1
Điều đó là chính xác, nhưng tệp được tối ưu hóa kết quả yêu cầu thư viện trình tải (chỉ cần kiểm tra lại nó với r.js v2.1.14), thường khá nặng. Ngay sau khi chúng tôi biên dịch mã, chúng tôi không cần giải quyết các phụ thuộc được tải không đồng bộ, chúng tôi không cần thư viện này. Chỉ cần xem xét: chúng tôi bọc các mô-đun vào AMD, có nghĩa là không đồng bộ. tải, sau đó biên dịch chúng thành một tệp duy nhất (không tải riêng nữa), nhưng tải toàn bộ thư viện để giải quyết chúng (hiện đang dư thừa). Nó không phải là một cách tối ưu với tôi. Tại sao AMD hoàn toàn không tải được đồng bộ?
Dmitry Sheiko

almond.js cung cấp trình tải trọng lượng nhỏ hơn cho mã sản xuất đã hoàn thành so với RequireJS, nhưng nói một cách tương đối, lợi ích về hiệu suất của việc không tạo ra một yêu cầu http duy nhất vượt xa chi phí thêm mã trình nạp vào mô-đun, do đó, nó ít tối ưu hơn, ở quy mô nhỏ hơn nhiều. Câu hỏi, theo tôi, nên được quay lại - tại sao lại giả sử tính đồng bộ khi trình duyệt không? Tôi thực sự có quan điểm rằng cả RequireJS và CommonJS nên có một triển khai lời hứa được xây dựng.
I-Lin Kuo

Cả hai định dạng đều là đường dẫn hợp lệ tới CommonJS Modules / 2.0 và cung cấp khả năng mở rộng giống nhau. Đối với tôi - đối phó với các Mô-đun CJS / 1.1 (đó là ý nghĩa của CommonJS) thì dễ dàng hơn nhiều, mã có vẻ sạch hơn.
Dmitry Sheiko

Tôi đã đáp ứng những lợi ích như vậy của AMD như: * có thể tải nhiều hơn chỉ các tệp JavaScript; * bí danh đường dẫn; Chà, Trình biên dịch CommonJS giải quyết những điều này - nó tải các phụ thuộc không phải JavaScipt / JSON dưới dạng dữ liệu và có thể được cung cấp với cấu hình xây dựng (bao gồm cả bí danh). Bất lợi duy nhất mà nó đòi hỏi phải xây dựng. Nhưng ngày nay mọi người dù sao cũng xây dựng dự án cho bộ xử lý trước CSS. Vì vậy, đó chỉ là về việc thêm một nhiệm vụ bổ sung cho Grunt / Gulp ...
Dmitry Sheiko

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.