2012-09-28 19 views
11

Xét đối tượng mô hình sáng tạo với những đặc tính riêng, một cách để làm là:làm cách nào để tạo mẫu đối tượng Javascript bằng các phương thức và đặc tính riêng tư có thể sử dụng lại?

function MyStack(){ 
    var list = [], 
     index = 0; 

    this.push = function(val){ 
     return list[index++] = val; 
    }; 
    this.pop = function(){// ...} 
} 

var stack1 = new MyStack();  stack1.push(5); 
var stack2 = new MyStack();  stack2.push(11); 

Vấn đề với điều này: Mỗi thể hiện của ngăn xếp có nó bản sao riêng của phương pháp 'đẩy' và 'pop'.

Một cách khác để thực hiện các phương pháp xây dựng là:

function MyStack(){ 
    this.list = []; 
    this.index = 0; 
} 
MyStack.prototype = { 
    insert: function(val){ 
      return this.list[this.index++] = val; 
     }, 
    pop:function(){//...} 
} 

Vấn đề ở đây: Chúng tôi mất sự riêng tư của danh sách và chỉ mục.

Có cách nào, sao cho chúng tôi có thể có cả hai phương pháp sử dụng lại giữa các trường hợp và quyền riêng tư của các thuộc tính?

Tôi hiểu rằng chúng tôi có thể có điều này cho các phương pháp không hoạt động trên bất kỳ trạng thái nào của đối tượng, nhưng tôi đang nói nhiều hơn về những phương thức hoạt động trên trạng thái đó.

+0

Bạn có thể cung cấp cho mỗi cá thể một ID ngẫu nhiên và lưu trữ các thuộc tính riêng của nó trong một số loại cấu trúc dữ liệu. Nhưng tôi sẽ đề nghị chỉ cần quên đi các thuộc tính privat nếu bạn sử dụng các hàm xây dựng. JavaScript không được xây dựng cho điều đó và mọi cách giải quyết đều có một số bất lợi. –

+0

@FelixKling để cho phép nói rằng chúng tôi có một DS phụ trợ, Giống như {id1: {list: [3,4], currentIndex: 2}, id2: {list: [2,1,4], currentIndex: 3}} .. ngay cả trong MyStack.prototype.insert = function (val) {currState = this.auxiliaryDS [this.id]; this.currState.list.push (val) .. Một lần nữa, nó không thực sự riêng tư. – sbr

+1

Bạn có thể xác định lưu trữ dữ liệu và hàm dựng bên trong một hàm và chỉ hiển thị hàm khởi tạo.Kho dữ liệu sau đó sẽ là riêng tư và không thể truy cập từ bên ngoài. Có, ID sẽ có thể truy cập được, nhưng bạn thậm chí có thể tạo một tên thuộc tính ngẫu nhiên cho điều này nếu bạn muốn làm xáo trộn nó. Như tôi đã nói, JS không được xây dựng cho điều này và bất cứ điều gì bạn làm sẽ là hacky và/hoặc phức tạp. Tài liệu phù hợp là IMO có giá trị hơn. Bạn có thể tìm thấy một vài câu hỏi liên quan tại đây: http://stackoverflow.com/search?q=javascript+private+instance+variables+and+prototype+methods –

Trả lời

1

Có. Tôi đã chỉnh sửa mã này vì vậy nó thực sự đầy đủ chức năng như bạn đã dự định nó hoạt động. Nó có vẻ hơi dư thừa với tôi, nhưng nó cung cấp cho bạn khả năng cung cấp một giao diện công cộng, nhưng để giữ cho các biến của bạn riêng tư và kiểm soát cách người dùng tương tác với chúng.

function MyStack(){ 
    var list = []; 
    var index = 0; 

    this.getIndex = function(){ 
     return index; 
    } 
    this.setIndex = function(val){ 
     index = val; 
    } 
    this.list = function(val){ 
     if(val){ 
      // setter if a value was provided. Illustrating how you can control 
      // index, which I assume is the point of having these things private 
      // to begin with 
      return list[this.setIndex(this.getIndex() + 1)] = val; 
     } 

     // always return list - acts like a getter 
     return list; 
    } 
} 
MyStack.prototype = { 
    insert: function(val){ 
      return this.list(val); 
     }, 
    pop:function(){} 
} 

var stack1 = new MyStack();  
stack1.insert(5); 
var stack2 = new MyStack();  
stack2.insert(11); 
0

Tôi nghĩ rằng trong cả hai cách tiếp cận bạn đã đề cập, Khi đối tượng bao giờ được tạo bằng cách sử dụng mẫu xây dựng, các thuộc tính sẽ được sao chép vào các đối tượng của nó. Điều này bạn đã đề cập cho các phương pháp tiếp cận đầu tiên là mối quan tâm. Tôi cảm thấy như vậy sẽ được áp dụng cho phương pháp thứ hai cũng cùng với mối quan tâm của bạn trong cách tiếp cận này.

Chúng tôi thường đi đến phương pháp tiếp cận thứ hai mà bạn đã đề cập khi nào chúng tôi muốn mở rộng các thuộc tính của "MyStack" sang một số lớp khác.

phép nói rằng tôi muốn mở rộng MyStack lớp học của bạn để MyTest như dưới đây

var dummy = function(); 
dummy.prototype = MyStack.prototype; 
var MyTest = function(){ 
}; 
MyTest.prototype = new dummy(); // Assigning MyStack properties to MyTest 
var obj = new MyTest(); 
1

Bạn nên kiểm tra John Resig của Simple Javascript Inheritance. Đó là một bài đọc tuyệt vời và nó đã được mở rộng để cung cấp hỗ trợ cho các cá nhân, được gọi là Privates.js;

+0

Không biết về Privates.js. – sbr

1

Chức năng hàm tạo có thể trả về bất kỳ đối tượng nào (không cần thiết số) này. Người ta có thể tạo ra một hàm dựng, trả về một đối tượng proxy, có chứa các phương thức proxy cho các phương thức "thực" của đối tượng thể hiện "thực". Điều này nghe có vẻ phức tạp, nhưng nó không phải là; đây là đoạn mã:

var MyClass = function() { 
    var instanceObj = this; 
    var proxyObj = { 
     myPublicMethod: function() { 
      return instanceObj.myPublicMethod.apply(instanceObj, arguments); 
     } 
    } 
    return proxyObj; 
}; 
MyClass.prototype = { 
    _myPrivateMethod: function() { 
     ... 
    }, 
    myPublicMethod: function() { 
     ... 
    } 
}; 

Điều tuyệt vời là việc tạo proxy có thể được tự động, nếu chúng tôi xác định quy ước đặt tên các phương pháp được bảo vệ. Tôi đã tạo một thư viện nhỏ thực hiện chính xác điều này: http://idya.github.com/oolib/

+0

Điều này có vẻ kỳ lạ với tôi - bạn có thể giải thích thêm một chút không? Tôi đọc thông qua tài liệu lib của bạn cũng như cố gắng để grok nó, nhưng tôi không nhìn thấy chính xác những gì các đối tượng proxyObj đang làm – netpoetica

+0

Bạn có thể nhanh chóng MyClass với 'myObj = new MyClass();'. myObj sẽ là proxyObj: nó sẽ chỉ có 1 thành viên, được gọi là myPublicMethod. Điều này có dễ hiểu không, hoặc bạn có thêm câu hỏi? Tôi sẵn sàng giúp đỡ. – slobo

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