2015-09-08 13 views
15

Nhóm của tôi không có bất kỳ nhà phát triển JS có kinh nghiệm nào, nhưng chúng tôi đang viết thư viện ở Node và nhận được đề xuất từ ​​một nhà phát triển JS thực sự rằng "Chúng tôi sẽ làm cho mô đun trở nên phức tạp hơn - không gây ô nhiễm không gian tên toàn cầu và dễ đọc hơn để mới comers", và nói với chúng tôi phải làm như sau:Có lý do nào để xác định module.exports sử dụng IIFE không?

module.exports = (function(){ 
     return { 
     nameToExpose: functionToExpose 
     ... 
    }; 
})(); 

hơn

module.exports.nameToExpose = functionToExpose; 

điểm này là gì, nếu có? Sau này không thực hiện bất kỳ khai báo cục bộ nào có thể được phạm vi bởi IIFE, và thậm chí nếu nó đã làm, chúng sẽ là cục bộ cho tệp mô-đun và không phải là toàn cục cho toàn bộ chương trình mà require() của nó. Một số Googling và poking về trang web này không trả lời bất kỳ câu trả lời về câu hỏi cụ thể này, mặc dù có nhiều giải thích khác của IIFEs mà tôi đã đọc (và được tóm tắt trong các bình luận ở trên). Một số thử nghiệm chắc chắn cho thấy rằng sau này không không thực sự đặt functionToExpose trong không gian tên chung, mặc dù tên gốc của nó được ghi lại trong chính loại hàm.

+2

Anh ấy phải cung cấp cho bạn lời khuyên về mã javascript trong trình duyệt. Một IIFE trong trường hợp đó ngăn chặn sự ô nhiễm không gian tên toàn cầu. – MinusFour

+0

Đó là những gì đồng đội của tôi nghĩ, nhưng mã cụ thể trong câu hỏi là một phần của một ứng dụng đặc biệt có ý định chạy với Node. Không có giao diện người dùng trình duyệt. –

+4

Tìm một "nhà phát triển JS thực sự" khác thực sự hiểu nút và mô-đun là gì và không gian tên chung là gì. Nếu điều này dễ đọc hơn, tôi sẽ ăn mũ của mình. –

Trả lời

11

Khá nhiều sự khác biệt. Toàn bộ ý tưởng về Node.js, sử dụng require, có các mô-đun, v.v., là đặc biệt để phân tách mối quan tâm. Tôi muốn nói (thận trọng) rằng nếu bạn làm đúng, bạn không cần phải lo lắng về việc "gây ô nhiễm" bất kỳ phạm vi toàn cầu nào. Mọi thứ trong vòng module.exports đều tồn tại trong mô-đun đó.

Khi bạn đối phó với các công cụ giao diện, đó là khi phạm vi toàn cầu trở thành một vấn đề đáng lo ngại, bởi vì nếu một hàm hoặc bất kỳ điều gì không bị scoped (tức là, trong một khối IIFE hoặc khối chức năng khác) có quyền truy cập đối tượng window toàn cầu và mọi thứ khác đều có quyền truy cập vào chức năng đó.

một nhà phát triển JS thực

Gọi ai đó mà là một lá cờ đỏ.

không gây ô nhiễm không gian tên toàn cầu và để làm cho nó dễ đọc hơn để mới comers

Nếu bạn đang modularizing mã của bạn một cách chính xác, đó không phải là một mối quan tâm. Có một thời gian và một nơi dành cho IIFE, nhưng tôi không thấy lý do tại sao gói tất cả mọi thứ trong IIFE, là đã nằm trong mô-đun, bằng cách nào đó sẽ làm cho mã "mô-đun hơn" hoặc dễ đọc hơn đối với "người mới" hơn bằng cách đơn giản sử dụng Node.js như nó được thiết kế:

module.exports = function() { ... } // whatever 

và ngay cả khi nó đã làm, họ sẽ là địa phương để các tập tin mô-đun và không toàn cầu cho toàn bộ chương trình mà require() là nó.

Bạn là chính xác. Tôi sẽ lấy bất cứ điều gì anh ta nói với một hạt muối. Có lẽ anh ta biết về một số trường hợp sử dụng cụ thể mà cách tiếp cận của anh ta đã giúp ích cho anh ta trong quá khứ, vì vậy tôi sẽ hỏi anh ta cụ thể về điều đó để xem anh ta nói gì. Ngoài ra, tôi cảm thấy bạn đang đi đúng hướng.

6

Lý do để có thể đôi khi làm điều này là bởi vì nếu bạn không làm như vậy, thì bất kỳ biến nào bạn cần cho đối tượng module.exports phải được đưa vào toàn bộ tệp.

Cân nhắc hai cách này.

  1. Nếu không có IIFE.

    var foo = 'la' + 'la'; // some computed value 
    
    // 
    // ... lots of program code here ... 
    // 
    
    module.exports = { 
        foo : foo, 
    }; 
    
  2. Với IIFE.

    // 
    // ... lots of program code here ... 
    // 
    
    module.exports = (function() { 
        var foo = 'la' + 'la'; // some computed value 
        return { 
         foo : foo 
        } 
    }()); 
    

Trong ví dụ đầu tiên, hai vấn đề phát sinh.

  1. Biến của bạn (như foo) được tạo khá xa nơi chúng được sử dụng để xuất giá trị từ mô-đun. Điều này có thể làm giảm sự rõ ràng. Chắc chắn, bạn có thể khai báo một biến sau mã chương trình, nhưng nó vẫn có cùng phạm vi (và var s là hoisted). Thêm vào đó, thực hành chung tốt nhất là khai báo tất cả các biến của bạn lên phía trước, và không làm như vậy là một sự cân bằng để xem xét.
  2. Mã chương trình có thể gây rối với các biến của bạn, cố tình hoặc vô tình, làm phức tạp mọi thứ và không mong muốn trừ khi bạn cần điều đó (đôi khi bạn làm).

Ví dụ thứ hai loại bỏ những vấn đề này bằng cách có phạm vi riêng cho khu vực đó của tệp. Bạn vẫn có thể sử dụng các biến có phạm vi toàn bộ tệp, nhưng trong trường hợp bạn không cần, bạn có thể có các biến dễ đọc và dễ hiểu hơn.

Thông thường, chúng tôi lập trình cho con người chứ không phải máy móc. Đây là một ví dụ về tối ưu hóa cho cái cũ.

Cập nhật:

Trong các phiên bản hiện đại của JavaScript, constlet có lẽ giải pháp tốt hơn cho các vấn đề mô hình này nhằm mục đích để giải quyết. Với chúng, bạn có thể định nghĩa các biến theo cách sẽ ném lỗi nếu bạn mắc lỗi giống như lỗi mà IIFE đang cố gắng bảo vệ bạn.

// 
// ... lots of program code here ... 
// 

const foo = 'la' + 'la'; // some computed value 

module.exports = { 
    foo : foo, 
}; 

Trong ví dụ trên, nếu các mã chương trình sử dụng foo, nó sẽ sụp đổ với một ReferenceError, vì Temporal Dead Zone, như trái ngược với nhận undefined như sẽ là một var. Điều này là tuyệt vời bởi vì bây giờ bạn phải di chuyển một cách rõ ràng tuyên bố của foo đến một vị trí trước đó trong mã nếu việc sử dụng của nó là cố ý, hoặc sửa chữa mã khác.

+0

Câu trả lời hay! Điều đó nói rằng, nếu các tệp của bạn quá lớn đến nỗi bạn sẽ bị biến đổi gây ô nhiễm/biến của bạn đang bị bỏ lại ở đầu tệp, bạn có thể muốn suy nghĩ về tách thành một tệp riêng biệt –

+0

Với các mô-đun ES và các hằng số thích hợp bây giờ phổ biến trong mã JavaScript hiện đại, tôi muốn nói rằng mô hình IIFE đã bị cộng đồng phản đối một cách hiệu quả. Việc sử dụng nó có thể có ý nghĩa trong một số trường hợp cạnh, chẳng hạn như transpilers và một số hàm đệ quy, nhưng nói chung, không cần thiết cho những ngày này. –

Các vấn đề liên quan