2012-05-23 24 views
13

tôi có lớp học này:javascript công cộng biến

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     this.var1 = "huhu"; 
    } 
} 

và gọi nó là:

var myobj = new ctest(); 
    myobj.func1(); 

không được coi là cảnh báo thứ hai sẽ bật lên "huhu"? func2 là riêng tư, nó có thể không truy cập vào biến công cộng var1?

nếu chức năng riêng tư không thể truy cập vào biến công khai, tôi có thể làm như thế nào?

Cảm ơn trước!

+2

Ngoài ra, không có những thứ như 'riêng tư' ở đây. – Alexander

+0

Điều này 'obj.func1()' nên có lẽ là 'myobj.func1()' – forsvarir

+0

@forsvarir yeah nó nên - tôi cố định nó cho anh ta. – Alnitak

Trả lời

17

Bạn cần cung cấp một bối cảnh cho các cuộc gọi đến func2:

this.func1 = function() { 
    alert(this.var1); 
    func2.call(this); 
    alert(this.var1); 
} 

Nếu không có bối cảnh cuộc gọi sẽ sử dụng đối tượng toàn cầu (tức là window) - bạn sẽ thấy khi bạn chạy mã hiện tại của bạn mà window.var1 là được tạo ra giữa hai cảnh báo.

+0

nếu tôi làm những gì bạn đề nghị nó nói rằng func2() không phải là một chức năng – MIrrorMirror

+0

@MIrrorMirror ah, umm, vâng - giữ! – Alnitak

+0

@Alnitak Vui lòng đọc mã của anh ấy, func2 không phải là chức năng công khai. – xdazz

0
function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(this); 
     alert(this.var1); 
    } 
    var func2 = function(obj) { 
     obj.var1 = "huhu"; 
    } 
} 

Và có cách nào khác để giải quyết vấn đề này, đánh dấu vào câu trả lời khác :)

+0

Downvoter nên cho lý do của bạn. – xdazz

+0

@Alnitak Nhưng đó không phải là vấn đề, 'obj' là tham số. – xdazz

12

Chức năng không được gắn với trường hợp, do đó gọi lại func2 kết thúc lên như gọi mà không this trỏ đến các trường hợp dự kiến .

Bạn có thể sửa chữa các sự thỉnh nguyện bao gồm bối cảnh:

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2.call(this); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     this.var1 = "huhu"; 
    } 
} 

Hoặc bạn có thể giữ một biến với các tham chiếu đối tượng truy nã xung quanh:

function ctest() { 
    var that = this; 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     that.var1 = "huhu"; 
    } 
} 
+0

cảm ơn! điều này đã giúp tôi rất nhiều –

+0

bạn có thể cung cấp thêm đọc về chủ đề này, vì tôi muốn biết đó là phương pháp hay nhất và tại sao – InsOp

+1

@InsOp Tôi khuyên bạn nên đọc MDN trợ giúp về từ khóa "này": https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Tham chiếu/Toán tử/ – Lucero

2

Một lựa chọn khác là sử dụng Function.bind:

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     this.var1 = "huhu"; 
    }.bind(this); 
} 

Lưu ý rằng hỗ trợ trình duyệt cho điều này không hoàn hảo.

+0

Tại sao lại sử dụng 'đó' _and_' .bind() 'cùng một lúc? – Alnitak

+0

@Alnitak: Sao chép và dán kém – Eric

2

Không có điều gì là riêng tư trong JS, nhưng bạn có thể chơi với phạm vi bằng cách sử dụng closures.

Ví dụ: trong ví dụ của bạn, bạn không cần phải phơi bày var1 làm tài sản công cộng. Bạn có thể dễ dàng viết lại mã của bạn như sau:

function ctest() { 
    var var1 = "haha"; 

    this.func1 = function() { 
     alert(var1); 
     func2(); 
     alert(var1); 
    } 

    var func2 = function() { 
     var1 = "huhu"; 
    } 
} 

Bởi vì cả hai func1func2 cổ phiếu cùng một phạm vi - chúng được định nghĩa trong cùng chức năng, ctest - họ có thể truy cập vào các biến tương tự. Tất nhiên trong trường hợp đó, bạn không có var1 được hiển thị, vì vậy: myobj.var1 sẽ là undefined.

Nếu bạn muốn var1 được tiếp xúc như bất động sản, thì những gì bạn cần là bindfunc2 với trường hợp đối tượng mà bạn đã tạo trong constructor:

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     this.var1 = "huhu"; 
    }.bind(this); 
} 

Nếu không func2 sẽ có một đối tượng bối cảnh khác nhau (this). Nếu trình duyệt không hỗ trợ bind và bạn không muốn sử dụng một shim (như thể hiện trong các liên kết ở trên), bạn có thể tận dụng lợi thế của việc đóng cửa một lần nữa:

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var context = this; 
    var func2 = function() { 
     context.var1 = "huhu"; 
    } 
} 

IMVHO ít thanh lịch.