2009-12-31 76 views
6

只是爲了踢我試圖在javascript中創建一個簡單的數據對象。這是代碼。在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); 

我對這個創作有幾個問題。

  1. 我想創建一個對象的屬性/屬性是私人的,不可見的世界。我能成功嗎?我真的不能訪問對象屬性嗎?
  2. 有沒有更好的方法來創建這種類型的對象?
  3. 如果我想繼承這個對象,我應該做一個newObject.prototype = roverObject會工作嗎?最重要的是,這是有意義的。
  4. 最後我有一個奇怪的問題。注意objet「where」的最後一個方法,它返回一個串聯的字符串。在這裏,我嘗試了下面的代碼。

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

,然後做對我來說是以下的console.log

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

把它扔到了以下錯誤:

cannot access optimized closure 

它爲什麼會這麼說?我究竟做錯了什麼?

感謝您的幫助。任何評論意見,將不勝感激! 乾杯

+2

在'var newRover = {}'上忘記了分號和所有函數定義。 – philfreo 2009-12-31 04:43:19

+0

謝謝。會做出改變。 :) – Priyank 2009-12-31 04:50:46

+0

添加分號仍然不能解決問題,雖然 – Priyank 2009-12-31 05:04:36

回答

6

我是否成功地做到了這一點?我真的不能訪問對象屬性嗎?

確實。你沒有對象屬性,你在roverObject函數中有局部變量。局部變量不能從外部訪問,只能從roverObject函數內的函數關閉它們。

您調用roverObject作爲構造函數,與new roverObject不相關,因爲您從函數返回不同的對象。說var rover1= roverObject()沒有new會做同樣的事情。值得注意的是,[new] roverObject返回的對象是{}中創建的普通Object; rover1 instanceof roverObjectfalse

如果你想instanceof工作,你就必須用new打電話,並在構造函數中使用this代替newRover

如果我想繼承這個對象,我應該做一個newObject.prototype = roverObject會工作嗎?最重要的是,這是有意義的。

號您目前有沒有考慮原型。您正在爲每個roverObject實例使用每種方法的單獨副本。您可以通過這種方式確定對象,但這與原型設計不同。如果你想使類似的roverObject在你現在有配置的子類,你會這樣說:因爲在基類構造函數的「私人」局部變量

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

注意還真是私有的,甚至該子類無法獲取它們。沒有'保護'。

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

那是什麼想幹什麼?我無法得到你所犯的錯誤;以上所做的就是將該字符串的位置分配給where(在setter方法被調用之前,所以它沒有定義)。

是否有更好的方法來創建這種類型的對象?

也許吧。有關JavaScript中的類/實例策略的討論,請參閱this question

+0

優秀指針!它提供了大量的信息。謝謝 – Priyank 2009-12-31 06:04:51

1

關於4. - 你正在嘗試記錄函數,而不是調用該函數的結果。應該是console.log(rover1.where());我猜firebug(我認爲它是firebug的console.log)不喜歡記錄函數定義。

編輯哦,我明白了,當你分配rover.where時,你實際上正在執行哪個功能。你是否想要得到一個看起來像屬性的東西來實際上是一個功能?如果是這種情況,它將無法工作。如果您希望在被調用時對其進行評估,它必須是一個函數。

你會發生什麼情況where在構造函數中被執行。那時你仍然在創建閉包,因此訪問它的私有變量還爲時過早。

+0

,這是行不通的。我相信,如果認爲如果我的閉包函數返回函數的值,而不是函數本身,那麼哪裏成爲一個屬性的權利?不是一個功能。 – Priyank 2009-12-31 05:28:25

+0

正確 - 但是當你調用'console.log(rover1.where)',你試圖打印出我認爲Firebug不能的函數定義(在這種情況下) – 2009-12-31 05:34:33

+0

看到編輯,我沒有意識到新的'where'函數的語法:) – 2009-12-31 05:54:38

2

Q1:您可以創建在JavaScript「類」「私有」的成員。在JavaScript中,隱私不是由任何訪問說明符決定的。相反,訪問需要專門的儀器。示例:

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; 
    } 
} 

JavaScript中的對象範圍受稱爲閉包的奇怪概念支配。據我所知,沒有任何其他流行launguage像C沒有平行概念+/Java的等

雖然我理解閉包是什麼,我不能把它的話。也許一個演示將幫助您:

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

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

closureDemo(); 

現在,而setDone是從內部doLater調用,它仍可以訪問done在closureDemo,即使done範圍(在常規程序意義上的)

我想你會明白更多,當你閱讀this。Q2:我只能說我在做什麼;我只能說我在做什麼;我不知道這是否更好。如果我寫你的代碼,它應該是這樣的:

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(); 

注意要點:roverObject

  1. 資本「類名」的第一個字母
  2. 使用這種替代
  3. 這個函數是一個純粹的構造函數。它什麼都不返回。

Q3:如果你想要做的繼承,那麼我的方法(使用本)將行不通。相反,公共方法應該是RoverObjectprototype的一部分。閱讀this。優秀的材料。

希望有所幫助。


編輯:你的代碼的工作方式有問題。問題:

  1. 你的功能沒有按顧名思義去做。它的名字最好是createRoverObject,因爲這正是它所做的。它不像類構造函數那樣工作
  2. 你的類支持的方法是對象的一部分,但數據成員不是。雖然這可能起作用(事實並非如你的console.log()問題所示),但它不是一種在javascript中實現類的好方法。這裏的問題是關閉。再次,我無法明確具體是什麼問題,但我可以smell it
0

像這樣定義您的對象會爲您提供私人成員。

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();