1

そのため、内部に関数と変数を含む疑似クラスがあります。例えば:

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

私は何を間違っていますか?

これが私の実際のコードです。複数のファイルに分割されていますが、関連するものを掲載します。

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

4 に答える 4

2

1 つの問題:

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

上記で_Constructor_は、 が関数として呼び出された場合、そのthis値を設定しないため、デフォルトでグローバル オブジェクトになります (非厳密モードでは、または厳密モードでは未定義)。グローバルsongs変数になるか、厳密モードでエラーをスローします。

とにかく、かなり役に立たない機能のように思えます。

this.songs = [ new mySong() ];
于 2012-05-21T01:28:59.853 に答える
1

JavaScript の「Java」を文字通りに解釈しすぎている人がいます。:)

JavaScript について知っておくべきことがいくつかあります。

  1. JavaScript では、配列は他の言語のようには機能しません。それらは、C や Java で配列と呼ばれるものよりも辞書に似ています。メモリ効率が大幅に向上したり、高速になったりするわけではありません。事前割り当ては行われません。低レベルの実装にはオフセットなどはありません。JavaScript 配列は、順序が必須のデータを保持するための便利な (しかし便利な!) 構造にすぎません。

  2. new Array(length)配列は、式または単純なリテラル式を使用して作成できます[]。通常、配列リテラルを使用する必要があります[]

  3. を使用new Array(length)しても、実際には何も役に立ちません。length配列の初期プロパティを設定しますが、基本的にはそれだけです。すべての要素が残りundefinedます。追加の制約や境界チェックはありません。a[100] = 'whatever'呼び出しによって作成された配列に対して行うことができvar a = new Array(5) 、インタープリターは目をつぶることはありません。

  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. 前述したようにArray()、演算子で呼び出すと、配列newの初期値を設定するオプションの引数を取ります。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`
};

プロトタイプのパターンは奇妙に見えるかもしれませんが、ユース ケースを処理するにはおそらくこれが最良の方法です。songsthen配列 (重要かどうかは別として) に直接アクセスでき、loadSongssaveSongs関数をSongDatabaseのプロトタイプにアタッチすることで、それらの関数が確実に共有されるようにします。

于 2012-05-21T03:25:38.697 に答える
1
function MyClass()
{
    this.a = 0;
    this.b = function(c)
    {
        this.a += c;
    }
}

a+=cに変わるthis.a+=c;

于 2012-05-21T00:45:14.210 に答える
0

他の言語のように、変数は「クラス」にバインドされていません。プロパティを持つオブジェクトと考えてください。シングルaは変数「a」を参照するだけです(var関数で宣言されていないため、ここではグローバルでもあります)。オブジェクトのプロパティ"a"を更新する場合は、代わりに (プロパティにアクセスするためのドット演算子) を使用します。オブジェクトの操作も読みたいと思うかもしれません。thisthis.a


編集後 (使用していたと言います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は、新しいインスタンス as で (newキーワードを使用して) 呼び出されますthis。通常の関数は通常、何も呼び出されません。つまり、thisisundefinedまたは非厳密モードのグローバル オブジェクトです。MDNのキーワードのドキュメントをthis参照してください。

ここでは、最初に songDatabases のsongsプロパティを空の配列で初期化します。次に、_Constructor_関数内で 1 つの曲を含む別の配列を作成しますが、それを に割り当てます。window.songsこれは、関数がsongDatabase インスタンスで呼び出されないためです。メソッドでも同じ問題が発生する可能性がありますloadSongs()。インスタンスオブジェクトへの「静的」参照を提供する通常のメソッドの呼び出しとバインドとは別に、スコープ変数があります。

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

your_Constructor_がローカル関数ではなく、インターフェイスを追加するグローバル関数である可能性がある場合は、インスタンス ( this) を引数として指定するか、キーワードを「クラス」であるか_Constructor_.call(this)のように使用できるようにする を使用できます。this_Constructor_

于 2012-05-21T00:48:10.403 に答える