1

I'm creating a quiz interaction, and after a few days of research I'm trying to determine the best way to declare my objects. There's a master anonymous function (which could be called Quiz, but there is no requirement for public methods) that contains a class definition for Scenarios that contain a class definition for Questions:

Quiz > Scenario > Questions > Answers (eventually)

I prefer the Immediately-Invoked ('iffy') model to enforce private/public, but I also require multiple instances, so I believe I should be using prototypes? I've placed the class definitions as private as they are only used by this interaction. Is this the best model?

JsFiddle: http://jsfiddle.net/QtCm8/

(function(quizData) {
    var scenarios = [];
    for(var s=0;s<quizData.scenarios.length;s++) scenarios.push(new Scenario(quizData.scenarios[s]));
    function Scenario(scenarioData) {
        console.log("New Scenario: " + scenarioData.title);
        var questions = [];
        for(var q=0;q<scenarioData.questions.length;q++) questions.push(new Question(scenarioData.questions[q]));
        function Question(questionData) {
            console.log("New Question: " + questionData.text);
            // Repeat pattern for future answers object
        }
    }
})({
    scenarios: [
        {
            title: 'Scenario1'
            ,questions: [
                {
                    text: 'What is 1+1?'
                }
                ,{
                    text: 'What is 2+2?'
                }
            ]
        }
    ]
});
4

3 に答える 3

0

個人的には、公開したいプロパティを返すクラス定義を使用するのが好きです。以下はあなたのケースの例です。構造をいじって、自分が一番好きなものを見つけることができますが、いくつかの例が示されているはずです。

// Namespace
var q = {};

q.Quiz = function Quiz (data) {

    // Private code & variables
    var scenarios = [];
    for (var i = 0; i < data.scenarios.length; i++) {
        scenarios.push(new q.Scenario(data.scenarios[i]));
    }

    // Return public methods & values
    return {
        scenarios: scenarios
    };
};

q.Scenario = function Scenario (sData) {

    // Private inner class
    var Question = function (qData) {
        console.log("New Question: " + qData.text);
        return {
            text: qData.text
        };
    };

    console.log("New Scenario: " + sData.title);
    var questions = [];
    for (var i = 0; i < sData.questions.length; i++) {
        questions.push(new Question(sData.questions[i]));       
    }

    return {
        questions: questions
    };
};

var data = {
    scenarios: [
        {
            title: 'Scenario1'
            ,questions: [
                {
                    text: 'What is 1+1?'
                }
                ,{
                    text: 'What is 2+2?'
                }
            ]
        }
    ]
};

console.log(new q.Quiz(data));

ここでの実例:http://jsfiddle.net/5M8bp/

または、returnステートメントを削除し、「this」キーワードを使用してパブリックプロパティとメソッドを定義します。例えば:

q.Quiz = function Quiz (data) {

    this.scenarios = [];

    for (var i = 0; i < data.scenarios.length; i++) {
        this.scenarios.push(new q.Scenario(data.scenarios[i]));
    }
};

q.Scenario = function Scenario (sData) {

    // Private inner class
    var Question = function (qData) {
        console.log("New Question: " + qData.text);
        this.text = qData.text;
    };

    console.log("New Scenario: " + sData.title);
    this.questions = [];
    for (var i = 0; i < sData.questions.length; i++) {
        this.questions.push(new Question(sData.questions[i]));       
    }
};
于 2013-02-18T22:59:57.547 に答える
0

クラスをオブジェクトにパックすることを検討してください。以下は私が思いついたデザインパターンです。相互に依存するクラスが非常に多いため、それらを 1 つのオブジェクトにまとめる方がよいと考えました。コードは次のとおりです。

var quiz = {};

quiz.init = (function(data) {
    this.scenarios = this.questions = this.answers = [];

    this.data = {
        Question: data.Question.bind(this),
        Answer: data.Answer.bind(this),
        Scenario: data.Scenario.bind(this)
    };

    this.set_data = function(qas) {
        // fill the arrays here
        // Question, Scenario and Answer are now this.data.Question/Answer...
        // you can use a variable to shorten the names here
    };
});

var Quiz = function(data) {
    return new quiz.init(data);
};

var data = { // classes are defined here
    Question: function() {},
    Answer: function() {},
    Scenario: function() {}
};

var q = Quiz( data );

q.data.set_data(/* Big object literal goes here */);
于 2013-02-18T22:38:48.777 に答える
0

まず、Javascript にはクラスはなく、オブジェクトだけです。これは(クラスベースではなく)プロトタイプベースの言語であり、その関数はファーストクラスのオブジェクトです。ところで、aprototypeはオブジェクトであり、作成するすべての関数はそれを新しい空のオブジェクトを指すように取得します。関数を使用してシミュレートされた「クラス」の概念があります。

あなたが言ったように、この即時パターン(別名匿名関数)は、よりクリーンな名前空間を提供するのに非常に役立ちます。また、初期化コードなど、一度だけ実行する必要がある作業がある場合にも役立ちます。そのため、再利用可能な名前付き関数を使用する理由はありません。

ただし、再利用可能なメンバー (メソッドなど) が必要な場合は、はい、prototype. 共通のプロパティとメソッドをプロトタイプ プロパティに追加すると、これらの共通部分を、同じコンストラクターを使用して作成されたすべてのインスタンス間で共有できます。

たぶん、次のようなパターンの組み合わせであるModule Patternを探しているかもしれません

  • 名前空間、
  • 即時関数、
  • プライベート会員など
于 2013-02-19T20:05:01.720 に答える