2012-04-18 37 views
8

Tôi có được các khái niệm cơ bản về Mô hình Mô-đun và việc sử dụng dấu đóng để cho phép thành viên riêng tư, NHƯNG tôi không thể nuốt được vì sao mã bên dưới làm như vậy:Mô hình Mô-đun Javascript và từ khoá mới

var Calculator = function() { 
    var priv = 0; 

    return { 
     changePriv: function() { priv++;}, 
     printPriv: function() { console.log(priv);} 
    } 
} 

var myCalc = Calculator(); 
myCalc.printPriv(); 
myCalc.changePriv(); 
myCalc.printPriv(); 

var myOtherCalc = Calculator(); 
myCalc.printPriv(); 

Giao diện điều khiển đầu ra là

0 
1 
1 

Vì vậy, cố tình bỏ qua new từ khóa ở đây, cuộc gọi đầu tiên đặt myCalc đến một đối tượng Calculator. Nó bắt đầu với một giá trị từ 0 priv, đã có tăng lên, và sau đó in ra giá trị mới priv của 1.

Nhưng a) Tại sao cuộc gọi tiếp theo để Calculator() kết thúc trở về một tham chiếu đến cùng một đối tượng (như được chứng minh bằng '1' thứ hai)? Tôi biết tôi có thể sử dụng new ở đây và tránh điều đó, nhưng không hiểu tại sao tôi phải làm vậy. Không phải chức năng này sử dụng cú pháp ngữ pháp đối tượng để tạo ra một đối tượng mới và sau đó trả về nó? b) Vì nó dường như đang sử dụng cùng một không gian ngăn xếp chức năng (là ngay cả cách đúng đắn để suy nghĩ về nó trong JS?), Tại sao nó không ra biến số priv trong quá trình trước khi trả về tham chiếu đến cùng một đối tượng?

CHỈNH SỬA: Sửa lỗi không chính xác/ngu ngốc (nhờ scessor), DOES bây giờ xuất ra đối tượng máy tính mới/khác biệt ngay cả khi không sử dụng từ khóa new. Vì vậy, xóa a) và b). Câu hỏi kết quả của tôi sẽ là "Liệu nó có quan trọng cho dù tôi sử dụng new hay không trong lời kêu gọi của một nhà xây dựng mô-đun mẫu. Câu trả lời là, tôi đoán nó không quan trọng (?). (Joseph: xem http://jsfiddle.net/MvMvy/5/ ... nhà điều hành instanceof chỉ đơn giản là không làm việc với kiểu mô-đun hoặc chiều)

+2

Theo quy ước, các hàm bắt đầu bằng một chữ hoa được dành riêng cho các hàm tạo (tức là các hàm được cho là được gọi với 'mới'). Hàm 'Calculator' trả về một đối tượng một cách rõ ràng để gọi nó bằng' new' không tạo ra bất kỳ sự khác biệt nào với nó trả về. – RobG

+0

Cảm ơn RobG. Đó là chính xác những gì tôi đã hy vọng để có được xác nhận trên. – jeffersii

Trả lời

8

bạn không xuất máy tính khác myOtherCalc:. nếu bạn muốn so sánh chúng, thay thế thứ ba myCalc.printPriv(); với:

myOtherCalc.printPriv(); 

Sau đó, đầu ra là:

0 
1 
0 
3

You don't need to use new trong trường hợp của bạn.

Thông thường, nếu bạn sử dụng new, bạn mong đợi rằng những gì bạn nhận được là một phiên bản của hàm tạo mà bạn đã gọi. Trong trường hợp của bạn, nó sẽ không phải vì bạn trả lại một đối tượng theo cách thủ công. Nó sẽ không có ý nghĩa và sẽ gây ra vấn đề sau này của bạn nhầm lẫn việc sử dụng. Chẳng mấy chốc bạn có thể là "thử nghiệm cá thể" đối tượng của bạn và sẽ chạy vào "sự không phù hợp" này.

và bạn nhận được một lỗi đánh máy trong mã của bạn:

var myCalc = Calculator();  //create calculator 
myCalc.printPriv();    //"myCalc" private is 0 
myCalc.changePriv();    //increment 
myCalc.printPriv();    //"myCalc" private is 1 

var myOtherCalc = Calculator(); //another calculator 
myCalc.printPriv();    ///but you printed "myCalc" again 
+0

"không được" và "không nên" là các câu lệnh khác nhau. Tôi sẽ nói trong ví dụ cụ thể của ông, ông không nên, tuy nhiên ... Có những phiên bản của mô hình mô-đun mà chơi tốt với "mới" và không gặp phải vấn đề instanceof bạn mô tả. Xem: http://carldanley.com/js-module-pattern/ – Frug

0

Không có gì để làm với các điều hành "mới" là ... Ở đây bạn sẽ có được một cái giếng giải thích chủ đề về proto/constructor: http://en.wikibooks.org/wiki/JavaScript/Access_Control

Tuy nhiên nó là một ví dụ vô nghĩa, bạn có thể làm điều này, vì vậy bạn có thể truy cập priv qua getter và setter chỉ phương pháp:

function Calculator2() { 
var priv = 0; 
this.public = 0; 
this.getPriv = function(){ 
    return priv; 
} 
this.setPriv = function(val){ 
    priv = val; 
} 
} 
Calculator2.prototype.changePriv = function(){ 
this.setPriv(this.getPriv()+1); 
} 
Calculator2.prototype.printPriv = function(){ 
    console.log("priv = " + this.getPriv()); 
} 
Calculator2.prototype.changePublic = function(){ 
    this.public++; 
} 
Calculator2.prototype.printPublic = function(){ 
    console.log(this.public); 
} 

Trong trường hợp var này priv phải lúc nào cũng truy cập thông qua một phương thức getter và setter một phương pháp,

Trong ví dụ sau khi bạn có một private var className và khác var __className công cộng:

<div id = "outputDiv" style="width:600px;height:400px;border:solid 1px #000"></div> 
<script type="text/javascript"> 
    //<![CDATA[ 

// kịch bản: var SomeClass = function (className) {

var __className__ = className; 
    this.__className__ = "\"public default className\""; 
    var someString = new String(""); 

    this.setScopeText = function() { // void 
     someString = "A new instance of \"private [__classname__] : " + 
     __className__ + "\"" + 
     " has been created. Refering to [__className__]<br />" + 
     "A new instance of " + 
     this.__className__ + 
     " has been created. Refering to [this.__className__]"; 
     return someString; 
    }; 

    this.getScopeText= function(){ 
     return someString; 
    } 

    this.setOutput = function(elementId, someString){ 
     var outputPane = this.getSomePane(elementId); 
     outputPane.innerHTML += "<p>" + someString + "</p>"; 
    } 

    this.getSomePane = function(elementId){ 
     var outputP = document.getElementById(elementId); 
     return outputP; 
    } 

} 

SomeClass.prototype.changeClassNameVariable = function(str){ 
    this.__className__ = str; 
} 

// khai kết thúc.

// kiểm tra:

var sc = new SomeClass("foo"); 

sc.setOutput("outputDiv",sc.__className__); 
sc.setOutput("outputDiv",sc.setScopeText()); 
sc.setOutput("outputDiv",sc.getSomePane("outputDiv")); 

sc.__className__ = "\"Some name\""; 
sc.setOutput("outputDiv",sc.__className__); 
sc.setOutput("outputDiv",sc.setScopeText()); 

sc.changeClassNameVariable("bar"); 
sc.setOutput("outputDiv",sc.__className__); 
sc.setOutput("outputDiv",sc.setScopeText()); 

// kết thúc javascript và phần CDATA

//]]> 
</script> 

Output trong "div: outputDiv":

"mặc định nào className"

Một phiên bản mới của "riêng [tên lớp]: foo "đã được tạo. Tham khảo [className] Một phiên bản mới của "className mặc định công khai" đã được tạo. Tham khảo [this. className]

[đối tượng HTMLDivElement]

"Một số tên"

Một ví dụ mới của "private [classname]: foo" đã được tạo. Tham khảo [className] Một phiên bản mới của "Một số tên" đã được tạo. Tham khảo [this. className]

thanh

Một ví dụ mới của "private [classname]: foo" đã được tạo. Tham khảo [className] Một thể hiện mới của thanh đã được tạo. Tham khảo [this. className]

->className được khai báo trong hàm tạo không bao giờ thay đổi! -> này. className hoặc SomeClass.prototype. className là công khai và có thể thay đổi.

Tôi hy vọng điều này có thể giúp hiểu chuỗi và nhận xét của tôi rõ ràng hơn ...

+0

Ví dụ của bạn không cho phép các phương thức riêng tư, là điểm của mẫu mô-đun. (getPriv có thể truy cập ở mọi nơi - xem http://jsfiddle.net/VjnGq/1/) – jeffersii

+0

Đây là lý do tại sao tôi nói "đây là một ví dụ vô nghĩa" Nó chỉ cho thấy nó hoạt động như thế nào ... getPriv có thể truy cập được không phải là nếu không gọi phương thức getPriv() ... – tatactic

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