2010-04-26 6 views
14

Sau khi thực hiện một số đọc về Mô hình Mô-đun, tôi đã thấy một vài cách để trả lại các thuộc tính mà bạn muốn công khai.Mô-đun JavaScript Mô-đun - Điều gì về việc sử dụng "trả lại" này?

Một trong những cách phổ biến nhất là khai báo các thuộc tính và phương thức công khai của bạn ngay bên trong câu lệnh "trả về", ngoài các thuộc tính và phương thức riêng của bạn. Một cách tương tự (mẫu "Tiết lộ") là cung cấp các tham chiếu đơn giản tới các thuộc tính và phương thức mà bạn muốn công khai. Cuối cùng, một kỹ thuật thứ ba tôi thấy là tạo một đối tượng mới bên trong hàm module của bạn, mà bạn gán các thuộc tính mới của mình trước khi trả về đối tượng đã nói. Đây là một ý tưởng thú vị, nhưng đòi hỏi phải tạo ra một vật thể mới.

Vì vậy, tôi đã suy nghĩ, tại sao không chỉ sử dụng this.propertyName để gán các thuộc tính và phương pháp công khai của bạn và cuối cùng sử dụng return this ở cuối? Cách này có vẻ đơn giản hơn nhiều đối với tôi, vì bạn có thể tạo các thuộc tính và phương thức riêng với cú pháp thông thường var hoặc function hoặc sử dụng cú pháp this.propertyName để khai báo phương pháp công khai của mình.

Dưới đây là phương pháp tôi đang đề xuất:

(function() { 

var privateMethod = function() { 
    alert('This is a private method.'); 
} 

this.publicMethod = function() { 
    alert('This is a public method.'); 
} 

return this; 

})(); 

Có bất kỳ ưu/khuyết điểm để sử dụng phương pháp trên? Còn những người khác?

+5

Bạn đã xem chính xác 'cái này' là gì? Nơi bạn đang thêm publicMethod của bạn? –

Trả lời

30

Chức năng của bạn không có ngữ cảnh đối tượng, do đó, this tham chiếu đến đối tượng window toàn cầu trong trường hợp này. Mỗi thuộc tính bạn gán cho this sẽ tự động gây ô nhiễm không gian tên chung.

(function() { 
    console.log(this == window); // true 

    this.publicMethod = function() { 
     alert('This is a public method.'); 
    } 

})(); 

console.log(publicMethod); // function() 

Bạn có thể chuyển đối tượng đó một cách rõ ràng để cho biết sử dụng ngữ cảnh nào.

var MYAPP = {}; 

(function() { 
    // 'this' will now refer to 'MYAPP' 
    this.publicMethod = function() { 
     alert('This is a public method.'); 
    } 
}).call(MYAPP); 

console.log(publicMethod); // undefined 
console.log(MYAPP.publichMethod); // function() 

nào bạn có thể viết theo phong cách hơi khác:

var MYAPP = (function(my) { 
    var my; 
    ⋮ 
    return my; 
})(MYAPP); 

Và chúng tôi đến để an already discussed pattern. Để biết thêm chi tiết, xem bài viết của Dustin trên Scoping anonymous functions.

+0

Cảm ơn rất nhiều. Tôi đã không nhận thức được hành vi của "này" trong các chức năng vô danh. –

+0

Không có gì liên quan đến chức năng ẩn danh. Nó liên quan đến cách hàm (bất kỳ hàm nào có thể được tạo bằng khai báo hàm hoặc biểu thức hàm) được gọi. Nếu bạn gọi một hàm được lưu trữ trong một biến 'f' (ví dụ, được xác định bởi khai báo hàm' function f() {} 'hoặc thông qua một biểu thức hàm được gán cho một biến:' var f = function() {}; ') bằng cách sử dụng biểu thức 'f()', 'this' sẽ luôn là đối tượng chung. –

+0

@Tim Down: cảm ơn nhận xét của bạn. Tôi đã sửa lại câu trả lời của mình. –

4

Tôi muốn giới thiệu phong cách nơi bạn thêm các thuộc tính và phương pháp công cộng của bạn đến một đối tượng ẩn danh mà bạn sau đó trở về:

var myModule = (function() { 
    function privateMethod() { ... } 
    function publicMethod() { ... } 

    return { publicMethod: publicMethod }; 
})(); 
+0

vâng, vâng, ngoại trừ bạn đang trả lại thứ gì đó ngay lập tức bị vứt bỏ. –

+0

Tôi rất tò mò về ý nghĩa của Jason. Những vấn đề phát sinh từ việc sử dụng đối tượng ẩn danh như một sự trở lại? Điều này có vẻ như là tốt nhất của các kỹ thuật tôi đi qua, khi sử dụng mô hình mô-đun. –

+0

Tôi nghĩ Jason đang đề cập đến mã bị bỏ qua hoặc suy ra, vì chúng tôi đang thảo luận về một mẫu Mô-đun. Tôi sẽ cập nhật ví dụ của mình. –

2

nếu bạn muốn xuất bản các phương pháp, sau đó làm một cái gì đó như:

var export = (function() { 

var privateMethod = function() { 
    alert('This is a private method.'); 
} 
var export = {}; 

export.publicMethod = function() { 
    alert('This is a public method.'); 
} 

return export; 

})(); 
2

Một tùy chọn khác là tránh hoàn toàn tham chiếu này. Xác định một hàm tạo và trả về một đối tượng ẩn danh để thay thế.

function makeThing(someAttribute) { 
    var privateVariable = 42; 

    function someMethod() { 
    return privateVariable; 
    } 

    return { 
    "publicMethodName": someMethod, 
    "getAttribute": function() { 
     return someAttribute; 
    } 
    }; 
} 

var thing = makeThing(99); 
thing.publicMethodName(); 
thing.getAttribute(); 
1

mẫu Mô-đun Tiết lộ:

var m1 = (function(){ return {method: mthod} })(); 
var m2 = new function Singleton(){ return {method: mthod} }; 
var m3 = ({}).prototype = {method: method}; 
var m4 = ({}).prototype = (function(){ ... })(); 
var m5 = (function(){}).prototype = {} || (function(){ ... })(); 

var m6 = (function(extendee){ 
    return extendee.prototype = {attr3: 'attr3'}; 
})({currentAttr1: 1, currentAttr2: 2}); 

Ngoài ra, nếu bạn cần phương pháp xâu chuỗi:

var m = (function(){}).prototype = (function(){ 
    var thus = m; // this 
    console.log('m this-------', thus); 

    function fn(){ 
     console.log('fn', thus); 
     return thus; 
    } 
    function f(){ 
     console.log('f', thus); 
     return 'poop'; 
    } 

    return {f: f, fn: fn}; 
})(); 

console.log('M:', m, 'm.fn', m.fn(), 'm.fn.f', m.fn().f()); 

Ngoài ra còn có rất nhiều nhiều cách, và bạn có thể protagonize module của bạn cũng .