2012-05-21 87 views
1

所以我有一個僞類,其中包含函數和變量。例如:訪問js函數內的變量

function MyClass() 
{ 
    this.a = 0; 
    this.b = function(c) 
    { 
     this.a += c; 
    } 
} 

然後,當我後來去使用它,我會做到這一點:

var myObject = new MyClass(); 
myObject.b(3); 
myObject.b(5); 

,但是當我這樣做:

console.log("A: " + myObject.a); 

我得到:

A: 0 

我在做什麼錯?

這是我的實際代碼。 a+=c

function SongDatabase() { 

    this.songs = new Array(); 

    this.loadSongs = function() { 

    }; 

    this.saveSongs = function() { 

    }; 

    var _Constructor_ = function() { 
      var mySong = new Song(); 
      this.songs = new Array(mySong); 
     }; 
    _Constructor_(); 
} 

function LyriX() { 
    var songDatabase = new SongDatabase(); 
    //var playlistDatabase = new PlaylistDatabase(); 
    songDatabase.loadSongs(); 
    var sourceList = new ScrollableList(); 
    sourceList.setElement($S.getElement("sourceList")); 
    var accessoryList = new ScrollableList(); 
    accessoryList.setElement($S.getElement("accessoryList")); 

    var sourceListClick = function (index) { 
      $S.log("source click: " + index); 
      if (index == 0) { 
       displaySongs(); 
      } 
     }; 
    sourceList.setClickListener(sourceListClick); 

    var displaySongs = function() { 
      $S.log("display songs"); 
      // STACK OVERFLOW LOOK HERE!!! thanks :) 
      // in debug in chrome songDatabase.songs is a zero length array 
      accessoryList.loadArray(songDatabase.songs); 
     }; 
} 

$S.addOnLoadListener(function() { 
    new LyriX(); 
}); 
+1

我拿到8,不爲0,http://jsfiddle.net/FRGEr/ –

+0

準確地說,應該是8 – vbman11

+0

那麼你的代碼是正確的。 :)也許你應該發佈實際的代碼給你帶來麻煩。 –

回答

1

我看到有人在服用的「Java」在JavaScript望文生義。 :)

有兩件事情你應該知道的JavaScript:

  1. 在JavaScript中,數組不一樣,他們在其他語言中做工作。 它們更像字典,然後你會在C或Java中調用一個數組; 他們沒有更高的內存效率或更快; 沒有預分配完成; 在低級別的實現中沒有任何不足之處。 JavaScript數組僅僅是一個方便(但有用)的結構 用於保存命令式命令數據。

  2. 陣列可以使用new Array(length)表達, 或簡單的文字表達,[]被創建。 一般來說,您需要使用數組字面值[]

  3. 使用new Array(length)並沒有真正做任何有用的事情; 它設置了數組的初始length屬性,但基本上就是這樣。 所有元素仍爲undefined。 沒有附加約束或邊界檢查。 你可以在var a = new Array(5) 創建的數組上做a[100] = 'whatever',解釋器不會眨眼睛。

  4. JavaScript使用原型繼承,與C++和Java等語言中使用的經典繼承模型明顯不同。

考慮到這些點,讓我們看下面的代碼塊:

function SongDatabase() { 
    this.songs = new Array(); 
    this.loadSongs = function() { 
     // etc. 
    }; 

    this.saveSongs = function() { 
     // etc. 
    }; 

    var _Constructor_ = function() { 
     var mySong = new Song(); 
     this.songs = new Array(mySong); 
    }; 
    _Constructor_(); 
} 

這個代碼塊很可能無法做你覺得它在做什麼。

  1. 通過初始化SongDatabase()功能 你爲songDatabase每個實例創建新方法函數內SongDatabase方法。 當您處理幾十個實例時,這可能不是什麼大問題,但如果您要處理的是數百個,則所需的額外內存可能會成爲問題。 你會想在這裏使用prototype模式,而不是(見下文)。
  2. 你的_Constructor_函數沒有做任何事情。 var mySong = new Song()創建一個新的mySong對象 本地的_Constructor_功能和無法訪問它之外。 當_Constructor_調用返回, 它是垃圾回收mySong變量(像任何其他局部變量會)。
  3. _Constructor_是一個私有函數和不是一個方法; 我不完全確定在這種情況下this將引用。 您可能會最終在全局對象 上創建一個歌曲屬性(但我想測試一下)。
  4. 正如我前面提到的那樣,當您使用new運算符 調用Array()時,它需要一個可選參數來設置數組的初始值length。 在這種情況下,解釋器會試圖將mySong強制轉換爲 (mySong而不是添加到數組!); 當它失敗時,它將簡單地返回一個帶有length = 0的新數組。

相反,你最好寫SongDatabase()像這樣:

function SongDatabase() { 
    this.songs = []; 
    // etc. 
} 

SongDatabase.prototype.loadSongs = function() { 
    // load songs into `this.songs` 
}; 

SongDatabase.prototype.saveSongs = function() { 
    // save songs loaded into `this.songs` 
}; 

的原型模式可能看起來很奇怪,但 它可能處理您的使用案例的最佳途徑。 你仍然必須再songs陣列(這可能會或可能並不重要), 並通過附加loadSongssaveSongs功能SongDatabase的原型 保證這些功能共享的直接訪問。

+0

請注意,給定'var a = new Array(length)',* a *沒有成員。 'a [0]'返回'undefined',因爲不存在'a [0]'或任何其他成員,無論長度值如何。也許值得注意的是,數組中的「order」只能通過順序訪問屬性來實現,for ... in迭代不會(並且不會在某些broswers中)必然以任何特定的順序返回成員,甚至一致的順序。 – RobG

1
function MyClass() 
{ 
    this.a = 0; 
    this.b = function(c) 
    { 
     this.a += c; 
    } 
} 

變化爲this.a+=c;

+0

對不起MIS型我的部分,即時通訊在我的代碼中使用「this」 – vbman11

+0

在我的帖子中修復了它 – vbman11

+0

現在它應該可以工作了。 – mpm

0

變量不綁定到「類」,在其他語言:它拆分成多發的文件,但我要是把那些相關的人。把它想象成一個具有屬性的對象。一個a只是引用一個變量「a」(在函數中沒有聲明爲var,所以在這裏甚至是全局的)。您要更新屬性對象this的「a」,請使用this.a代替(dot operator訪問該屬性)。您也可以閱讀Working with objects


你的編輯(你說你會一直使用this.a)後,它的工作對我來說:http://jsfiddle.net/WKuZe/


後您向我們提供您的真實代碼,我發現這個奇怪的結構:

function SongDatabase() { 
    this.songs = new Array(); 
    // some methods 
    var _Constructor_ = function() { 
     var mySong = new Song(); 
     this.songs = new Array(mySong); 
    }; 
    _Constructor_(); 
} 

SongDatabase構造函數是(與new關鍵字)調用新的實例爲this。正常函數通常不會被調用,即thisundefined或全局對象處於非嚴格模式。請參閱documentation for the this keyword on MDN

在這裏,您首先用空數組初始化songDatabases'songs屬性。然後,在_Constructor_函數中,您創建另一個包含一首歌曲的數組,但將其分配給window.songs,因爲songDatabase實例上的函數不是called。您的loadSongs()方法可能會出現相同的問題。除了通話和binding通常的方法提供一個「靜態」參考實例對象是範圍變量:

function SongDatabase() { 
    var that = this; // <== always points to the instance 
    // some methods 
    function _Constructor_() { 
     var mySong = new Song(); 
     that.songs = new Array(mySong); 
    // ^^^^ 
    }; 
    _Constructor_(); 
} 

如果您_Constructor_不是本地的功能,但也許一個接口添加全局函數,你可能會提供實例(this)作爲參數或使用_Constructor_.call(this),它允許使用this關鍵字,就好像_Constructor_是「類」一樣。

+0

對不起,我固定我的帖子這就是我如何使用它在我的實際代碼 – vbman11

+0

你的「實際」代碼中的問題的作品。 – Bergi

+0

只是添加了我的真實代碼:) – vbman11

2

一個問題:

> var _Constructor_ = function() { 
> var mySong = new Song(); 
> this.songs = new Array(mySong); 
> }; 
> _Constructor_(); 

在上面,當_Constructor_被稱爲一個功能,您沒有設置其this值,則默認爲全局對象(在非嚴格模式,或未定義在嚴格模式下)。因此songs成爲全局變量或在嚴格模式下引發錯誤。

這似乎是相當無用的功能反正考慮:

this.songs = [ new mySong() ];