2009-12-31 47 views
6

Chỉ dành cho các cú đá tôi đang cố gắng tạo một đối tượng dữ liệu đơn giản trong javascript. Đây là mã.Tạo đối tượng trong javascript

var roverObject = function(){ 

     var newRover = {}; 
     var name; 
     var xCord; 
     var ycord; 
     var direction; 

     newRover.setName = function(newName) { 
      name = newName; 
     }; 

     newRover.getName = function() { 
      return name; 
     }; 

     newRover.setDirection = function(newDirection) { 
      direction = newDirection; 
     }; 

     newRover.getDirection = function() { 
      return direction; 
     }; 

     newRover.setXCord = function(newXCord) { 
      xCord = newXCord; 
     }; 

     newRover.getXCord = function() { 
      return xCord; 
     }; 

     newRover.setYCord = function(newYCord) { 
      yCord = newYCord; 
     }; 

     newRover.getYCord = function() { 
      return yCord; 
     }; 

     newRover.where = function(){ 
      return "Rover :: "+ name +" is at Location("+xCord+","+yCord+") pointing to "+direction; 
     }; 

     return newRover; 
    }; 


    rover1 = new roverObject(); 
    rover2 = new roverObject();  

    rover1.setName("Mars Rover"); 
    rover1.setDirection("NORTH"); 
    rover1.setXCord(2); 
    rover1.setYCord(2); 
    console.log(rover1.where()); 
    console.log(rover1); 

    rover2.setName("Moon Rover"); 
    rover2.setDirection("SOUTH");  
    rover2.setXCord(1); 
    rover2.setYCord(1);  
    console.log(rover2.where());   
    console.log(rover2); 

Có một vài câu hỏi mà tôi có xung quanh sự sáng tạo này.

  1. Tôi muốn tạo đối tượng nơi thuộc tính/thuộc tính của đối tượng là riêng tư và không hiển thị với mọi người. Tôi có thành công trong việc đó không? Tôi có thể thực sự không truy cập vào các thuộc tính đối tượng không?
  2. Có cách nào tốt hơn để tạo loại đối tượng này không?
  3. Nếu tôi muốn kế thừa đối tượng này, tôi nên làm một newObject.prototype = roverObject sẽ hoạt động? Và điều đó có ý nghĩa nhất của tất cả.
  4. Cuối cùng tôi gặp vấn đề khó xử. Chú ý phương pháp cuối cùng của objet "ở đâu" trả về một chuỗi được ghép nối. Ở đây tôi đã thử mã sau để thay thế.

     newRover.where = function(){ 
         return "Rover :: "+ name +" is at Location("+xCord+","+yCord+") pointing to "+direction; 
        }(); 
    

và sau đó đã làm một lỗi

console.log(rover1.where); 
console.log(rover2.where); 

Nó ném sau console.log sau cho tôi:

cannot access optimized closure 

Tại sao nó sẽ lại nói thế? Tôi đang làm gì sai?

Cảm ơn tất cả sự trợ giúp. Bất kỳ nhận xét đánh giá nào cũng sẽ được đánh giá cao! Chúc mừng

+2

quên dấu chấm phẩy trên 'var newRover = {}' và trên tất cả các định nghĩa chức năng của bạn. – philfreo

+0

cảm ơn. Sẽ thực hiện thay đổi đó. :) – Priyank

+0

việc thêm dấu chấm phẩy sẽ không giải quyết được vấn đề mặc dù – Priyank

Trả lời

6

Tôi có thành công trong việc đó không? Tôi có thể thực sự không truy cập vào các thuộc tính đối tượng không?

Thật vậy. Bạn không có thuộc tính đối tượng, bạn có các biến cục bộ trong hàm roverObject. Không thể truy cập các biến cục bộ từ bên ngoài, chỉ từ các hàm bên trong hàm roverObject có đóng cửa trên chúng.

Bạn đang gọi roverObject làm hàm tạo, với new roverObject, không liên quan, vì bạn đang trả về một đối tượng khác từ hàm. Nói var rover1= roverObject() mà không có new sẽ làm chính xác điều tương tự.Đáng chú ý là đối tượng được trả về bởi [new] roverObject là một đồng bằng Object khi bạn tạo nó từ {}; rover1 instanceof roverObjectfalse.

Nếu bạn muốn instanceof hoạt động, bạn sẽ phải gọi với new và sử dụng this thay vì newRover trong hàm hàm tạo.

Nếu tôi muốn kế thừa đối tượng này, tôi nên làm một newObject.prototype = roverObject sẽ hoạt động? Và điều đó có ý nghĩa nhất của tất cả.

No. Bạn hiện không có phụ cấp để tạo mẫu. Bạn đang sử dụng một bản sao riêng biệt của từng phương pháp cho từng trường hợp của roverObject. Bạn có thể làm chắc chắn các đối tượng theo cách này nhưng đó là một cách tiếp cận khác với prototyping. Nếu bạn muốn làm một cái gì đó giống như một lớp con của roverObject trong sự sắp xếp bạn có bây giờ, bạn muốn nói cái gì đó như:

function AdvancedRover() { 
    var rover= new roverObject(); 
    rover.doResearch= function() { 
     return rover.where()+' and is doing advanced research'; 
    }; 
    return rover; 
} 

Lưu ý kể từ khi các biến địa phương 'tư nhân' trong constructor lớp cơ sở thực sự là tư nhân, thậm chí lớp con không thể nhận được chúng. Không có 'bảo vệ'.

newRover.where = function() {...}();

Điều gì đang cố gắng thực hiện? Tôi không thể nhận được lỗi bạn làm; tất cả những điều trên không được gán cho chuỗi có vị trí là where (trước khi các phương thức setter được gọi, vì vậy nó đầy đủ các undefined).

Có cách nào tốt hơn để tạo loại đối tượng này không?

Có thể. xem this question để thảo luận về các chiến lược lớp/thể hiện trong JavaScript.

+0

con trỏ tuyệt vời! Nó cung cấp tấn thông tin. cảm ơn – Priyank

1

Liên quan đến 4. - bạn đang cố đăng nhập chức năng, không phải là kết quả của việc gọi hàm. Nên là console.log(rover1.where()); Firebug phỏng đoán của tôi (tôi cho rằng đó là console.log của firebug) không thích ghi lại các định nghĩa hàm.

EDIT Ồ tôi hiểu rồi, bạn đang thực sự thực thi vị trí khi bạn gán rover.where. Bạn đang cố gắng để có được những gì trông giống như một tài sản thực sự là một chức năng? Nếu đó là trường hợp nó sẽ không hoạt động. Nó sẽ phải là một hàm nếu bạn muốn nó được đánh giá khi nó được gọi.

Điều gì xảy ra trong trường hợp của bạn where được thực thi trong hàm hàm tạo. Tại thời điểm đó bạn vẫn đang tạo ra việc đóng cửa roverObject và do đó còn quá sớm để truy cập vào các biến riêng tư của nó.

+0

không hoạt động. Tôi chắc chắn, nếu nghĩ rằng nếu hàm đóng của tôi trả về giá trị của hàm ở đâu, thay vì hàm của chính nó thì ở đâu sẽ trở thành thuộc tính đúng? Không phải là một hàm. – Priyank

+0

Đúng - nhưng khi bạn gọi 'console.log (rover1.where)', bạn đang cố gắng in ra định nghĩa hàm, mà tôi cho rằng Firebug không thể (trong trường hợp này) –

+0

Xem chỉnh sửa, tôi đã không nhận ra cú pháp cho hàm 'where' :) –

0

Đây chỉ là địa chỉ điểm 1 trong bài đăng của bạn.

Dưới đây là một bài viết tốt về javascript viên tin và nhiều hơn nữa:
Private Members in JavaScript

2

Q1: bạn có thể tạo các thành viên 'tư nhân' trong 'lớp' javascript. Trong javascript, quyền riêng tư không được xác định bởi bất kỳ trình xác định truy cập nào. Thay vào đó, quyền truy cập cần được cụ thể hóa. Ví dụ:

function MyClass() { 
    this.val = 100; // public; 
    var privateVal = 200; 

    function getVal() { return this.val; } // private method; 
    this.getPrivateVal = function() { // public method, accessor to private variable 
     return privateVal; 
    } 
} 

Phạm vi đối tượng trong javascript bị chi phối bởi một khái niệm được gọi là đóng cửa. AFAIK, không có khái niệm song song trong bất kỳ launguage phổ biến nào khác như C +/Java, v.v.

Trong khi tôi hiểu những gì đóng cửa, tôi không thể diễn đạt bằng lời. Có lẽ một cuộc biểu tình sẽ giúp bạn:

function closureDemo() { 
    var done=false; 
    function setDone() { done=true; } 
    doLater(setDone); 
} 

function doLater(func) { setTimeout(func,1000); } 

closureDemo(); 

bây giờ, trong khi setDone được gọi từ bên trong doLater, nó vẫn có thể truy cập vào done trong closureDemo, mặc dù done không là trong phạm vi (theo nghĩa thủ tục thông thường).

Tôi nghĩ bạn sẽ hiểu thêm khi đọc this.


Q2: Tôi chỉ có thể nói những gì tôi làm; Tôi không biết có tốt hơn hay không. Nếu tôi đã viết mã của bạn, nó sẽ trông như thế này:

function RoverObject() { 

    var newRover = {}; // privates 
    var name; 
    var xCord; 
    var ycord; 
    var direction; 

    this.setName = function(newName) { 
     name = newName; 
    }; 

    this.getName = function() { 
     return name; 
    }; 

    this.setDirection = function(newDirection) { 
     direction = newDirection; 
    }; 

    // and so on... 

    this.where = function(){ 
     return "Rover :: "+ name +" is at Location("+xCord+","+yCord+") pointing to "+direction; 
    }; 
} 
var rover1 = new RoverObject(); 

điểm cần lưu ý:

  1. vốn hóa của "tên lớp" của chữ cái đầu tiên
  2. sử dụng này thay vì roverObject
  3. chức năng này là một hàm tạo tinh khiết. nó không trả lại gì cả.

Q3: nếu bạn muốn làm thừa kế, sau đó phương pháp của tôi (sử dụng này) sẽ không hoạt động. Thay vào đó, các phương pháp công khai phải là một phần của prototype của RoverObject. Đọc this. Vật liệu tuyệt vời.

Hy vọng điều đó sẽ hữu ích.


EDIT: Có vấn đề với cách mã của bạn hoạt động. Sự cố:

  1. chức năng của bạn không làm theo tên của nó. Tên của nó tốt hơn là createRoverObject, bởi vì đó là chính xác những gì nó đang làm. Nó không hoạt động như một hàm tạo lớp học
  2. các phương thức được lớp của bạn hỗ trợ là một phần của đối tượng, nhưng các thành viên dữ liệu thì không. Trong khi điều này có thể làm việc (và nó không phải là, như vấn đề console.log() của bạn gợi ý), nó không phải là một cách tốt để thực hiện một lớp trong javascript. Vấn đề ở đây là đóng cửa. Một lần nữa, tôi không thể nói rõ vấn đề cụ thể là gì, nhưng tôi có thể smell it.
0

Xác định đối tượng của bạn như thế này sẽ cung cấp cho bạn các thành viên riêng tư.

function RolloverObject() { 
    var name; 
    var xCord; 
    var ycord; 
    var direction; 

    this.setName = function(newName) { name = newName; }; 
    this.getName = function() { return name; }; 

    this.setDirection = function(newDirection) { direction = newDirection; }; 
    this.getDirection = function() { return direction; }; 

    this.setXCord = function(newXCord) { xCord = newXCord; }; 
    this.getXCord = function() { return xCord; }; 

    this.setYCord = function(newYCord) { yCord = newYCord; }; 
    this.getYCord = function() { return yCord; }; 

    this.where = function() { 
     return "Rover :: " + name + " is at Location(" + xCord + "," + yCord + ") pointing to " + direction; 
    }; 
} 

var rolloverObject = new RolloverObject(); 
Các vấn đề liên quan