2010-08-24 32 views
16

Tôi có một "lớp" Javascript được xác định như sau:Tôi có thể "mở rộng" một "lớp học" được đóng theo định nghĩa trong Javascript không?

var Welcomer = function(name) { 
    var pName = name; 
    var pMessage = function() { 
    return "Hi, " + pName + "!"; 
    }; 

    return { 
    sayHi: function() { 
     alert(pMessage()); 
    } 
    }; 
}; 

new Welcomer('Sue').sayHi(); 

Có cách nào để "phân lớp" Welcomer theo cách như vậy mà tôi có thể xác định lại phương pháp công cộng và được tiếp cận với những phương pháp riêng và các biến? Sau đây sẽ cho tôi tiếp cận với các phương pháp công cộng, nhưng không đến tư thục:

var UnhappyWelcomer = function(name) { 
    var pSadMessage = function() { 
    // won't work, b/c I don't have access to pMessage 
    return pMessage() + " Miserable day, innit?"; 
    }; 

    return { 
    sayHi: function() { 
     alert(pSadMessage()); 
    } 
    }; 
}; 
UnhappyWelcomer.prototype = Welcomer(); // failed attempt at inheritance 

new UnhappyWelcomer().sayHi(); 
+1

Bạn có thể muốn đọc qua [bài viết này] (http://mckoss.com/jscript/object.htm). –

+0

Đánh dấu bài viết đó. Thx –

Trả lời

10

Câu trả lời đơn giản cho câu hỏi của bạn là Không.

Bạn không thể làm bất cứ điều gì để truy cập vào những điều đó, trừ khi chức năng của bạn nằm trong cùng phạm vi, hoặc bằng cách nào đó 'công khai' thông tin (bằng cách trả lại hoặc đặt số this).

Nếu bạn có quyền chỉnh sửa chức năng gốc, bạn có thể viết lại mọi thứ theo cách mà các chức năng đó có thể được "chuyển" thành một hàm mở rộng, có thể thay đổi phạm vi "được bảo vệ" của đối tượng. Các mã sau đây nên cung cấp cho một ý tưởng tốt về những gì tôi đang đề xuất.

var Welcomer = function(name) { 
    var _protected = { 
    name: name, 
    message: function() { 
     return "Hi, " + _protected.name + "!"; 
    } 
    }; 

    return { 
    extendWith: function(extender) { 
     extender.call(this, _protected); 
     return this; 
    }, 
    sayHi: function() { 
     alert(_protected.message()); 
    } 
    }; 
}; 

var UnhappyWelcomer = function(name) { 
    var self = Welcomer(name).extendWith(function(_protected) { 
    _protected.sadMessage = function() { 
     return _protected.message() + " Miserable day, innit?"; 
    }; 
    // extending the public while still having scope to _protected... 
    this.sayHi = function() { 
     alert(_protected.sadMessage()); 
    }; 
    }); 
    return self; 
}; 

UnhappyWelcomer('bob').sayHi(); 
+0

. * có quyền truy cập vào chức năng ban đầu, vì vậy tôi muốn viết nó theo cách như vậy để làm cho mọi thứ "được bảo vệ" thay vì "riêng tư". bạn có thể cung cấp một ví dụ? –

+0

Tôi muốn thêm rằng đây là HUGELY lãng phí không gian "phạm vi" ... – gnarf

1

Nếu bạn thực sự cần kế thừa, có một số thư viện ra khỏi đó sẽ giúp vô cùng. Một tùy chọn là trait.js, có thể thực sự trở thành một phần tiêu chuẩn của javascript tại một số điểm. Nếu điều đó không trôi nổi thuyền của bạn, các thư viện như jQuery và nguyên mẫu có người giúp đỡ cho thừa kế.

Nếu bạn muốn sử dụng phương pháp tối thiểu/từ đầu, tôi khuyên bạn nên sử dụng mô hình nguyên mẫu cho mọi thứ. Bạn sẽ thấy sự gia tăng hiệu suất lớn so với mẫu bạn có trong ví dụ của mình.

Để trực tiếp giải quyết câu hỏi của bạn, không. Bạn sẽ có một thời gian dễ dàng hơn nếu bạn thiết kế 'các lớp' của bạn để các chức năng riêng tư không được dựa vào.

+0

Tôi đã thử 'return jQuery.extend ({}, Welcomer(), {sayHi: function() {alert (pSadMessage());});', nhưng 'extend' dường như chỉ sao chép các phần tử được định nghĩa trong đối tượng theo nghĩa đen (các phương pháp công khai), không phải phạm vi đóng cửa. –

+0

Yea, cách bạn đã thiết kế "class" của bạn với var/function riêng được định nghĩa trong constructor, chúng sẽ không hiển thị, đó là lý do tại sao tôi chắc chắn sẽ chuyển sang cấu trúc dựa trên nguyên mẫu chuẩn hơn – jdc0589

9

Mẫu "lớp" đó không phải là mẫu "lớp", được gọi là Module Pattern. Nó trả về một đối tượng không có quan hệ với hàm đã tạo ra nó, sau đó có sẵn các biến riêng tư của nó. Đối tượng trả về KHÔNG phải là một thể hiện của hàm đã tạo ra nó.

Khi bạn gọi 'Lớp mới()', nó tạo ra một thể hiện của hàm đó, nhưng nó cũng trả về một đối tượng khác. Bất kỳ hoạt động nào khác thực sự là trên đối tượng trả về và không phải là cá thể.

Để sử dụng thừa kế, bạn thực sự cần phải sử dụng thừa kế nguyên mẫu đúng, tôi đề nghị bạn đọc:

Đọc thêm:

Xin lỗi vì đã để lại cho bạn với chất liệu đọc, nhưng có vẻ như với tôi bạn đang khám phá khả năng. Những bài viết này sẽ cung cấp một cái nhìn sâu sắc hơn về vấn đề này.

Khi bạn biết nhiều hơn về vấn đề này, rất có thể bạn sẽ bỏ qua các thành viên riêng và sử dụng tiền tố _ và chỉ làm cho nó trở thành thành viên công khai như mọi người;)

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