2

その場でアクションツリーを構築している場所で開発中のjavascriptアプリがあり、意図的に循環依存関係を導入したいという奇妙な状況に陥っています。最初の非常にハックな試みの後、JavaScript 変数スコープが実際にこれを解決するかなり合理的な方法を導入することを発見しました。私はまだ JavaScript の専門家ではないので、ベスト プラクティスについて意見を求めました。作業コードのスニペットを次に示します。

var Step = function(title, instructions, action) {
    this.title = ko.observable(title);
    this.instructions = instructions;
    this.action = action;
};

var Action = function(cancelText, cancelDescription, cancelStep, nextDescription, addText, addStep, continueText, continueStep) {
    this.cancelText = cancelText;
    this.cancelDescription = cancelDescription;
    this.cancelStep = cancelStep;
    this.nextDescription = nextDescription;
    this.addText = addText;
    this.addStep = addStep;
    this.continueText = continueText;
    this.continueStep = continueStep;
};

var PersonalStep = new Step(
    "Contact Information",
    "How can we contact you about your awesome assortment of vehicles? Fill out the form below",
    new Action(null, null, null, null, null, null, null, null)
);

var AddVehicleStep = new Step(
    "Additional Vehicle",
    "You have another car? Great, tell us about it too!",
    new Action("Cancel",
               "No, nevermind about this vehicle.",
               PersonalStep,
               "Add another vehicle?",
               "+ Add",
               AddVehicleStep, // This is the weird bit to me
               "No, continue on",
               PersonalStep)
    );

var VehicleStep = new Step(
    "Vehicle Details", 
    "Tell us about your primary vehicle by filling out the form below.",
    new Action(null, null, null,
               "Add another vehicle?",
               "+ Add",
               AddVehicleStep,
               "No, continue on",
               PersonalStep)
);

したがって、実際には、ユーザーがフォームで「追加」アクションを選択すると、AddVehicleStep は追加の車両を継続的に追加できます。ほとんどの言語 (私がよく知っている言語) では、AddVehicleStep 変数は独自のコンストラクター内からの解析に失敗します。これは私にとって非常に奇妙で、JS のこのイディオムについてもっと知りたいと思っています。このようなオブジェクト ツリーをオンザフライで実行するためのより良い方法はありますか?

また、解析可能になるように、ステップ変数を意図的に逆の順序で宣言していたのではないかと考えるようになりました。独自のコンストラクターで変数を参照することについての私の発見により、これは必要ではないと信じるようになりました。しかし、私はそれをテストしたところ、VehicleStep の後に AddVehicleStep var を移動すると、VehicleStep が取得nullされますaction.addStep。この制限を回避し、変数を任意の順序で宣言できるようにする方法はありますか? 空白の宣言を使用し、後でそれらを設定すると機能しますか? 例えば

var a;
var b;

var a = new Step(b);
var b = new Step(b);
// a should now have the full instantiated object of b within it, right?
// (provided the step constructor assigned it, of course)

これはおそらく他の場所で回答されていますが、それを表示するキーワードが見つかりませんでした...

また、基本的にダイアログ/フォーム ウィザードを実装する Knockout.js アプリの一部としてこれらの手順を使用しています。

更新 昨夜、JSフィドルでこれを機能させました。jsfiddleでの後続の実行間でjsメモリがどのように処理されるかについて何かがあることがわかりました。これにより、私が作業していた特定のウィンドウ(Chrome、最新バージョン)で動作しました。ただし、新しいウィンドウまたは新しいブラウザーで開くと、機能しなくなります。

本当に奇妙な部分は、どのブラウザーでも動作を再現できないことです。私の編集の 1 つは、別の方法で宣言されていて、何らかの方法でメモリに保持されていた可能性があります。私が狂っていないことを証明するために、それを複製できたらいいのにと思います...

助けてくれてありがとう!

4

2 に答える 2

2

ステップは同じステップを参照するアクションを持つことができるので、ステップが構築された後にアクションを追加する能力を自分自身に許可するのが最も簡単だと思います. だから、このようなもの。

var Step = function(title, instructions, action) {
    this.title = ko.observable(title);
    this.instructions = instructions;
    if (action === undefined) 
       this.action = null;  //action was not passed
    else
       this.action = action; 
};

//set the action after constructor invocation
Step.prototype.SetAction = function(action) {
    this.action = action;
};

var AddVehicleStep = new Step(
    "Additional Vehicle",
    "You have another car? Great, tell us about it too!"
    );
//AddVehicleStep is now instantiated with a new Step,
// so we can now set its action refering to that step 
AddVehicleStep.SetAction(new Action("Cancel",
               "No, nevermind about this vehicle.",
               PersonalStep,
               "Add another vehicle?",
               "+ Add",
               AddVehicleStep, // This is the weird bit to me
               "No, continue on",
               PersonalStep));

または地獄、メソッドを忘れて直接実行する

AddVehicleStep.action = new Action(...);

しかし、それをやり始めると、コードを書き直さずにアクションを設定したときに何が起こるかを常に判断する能力が失われます。

なぜこれを行うのですか?操作の順序と、それがここでどのように影響するかを理解する必要があります。

a = b(c(a))

操作の順序は

  1. c(a)->result1
  2. b(result1)-> 結果2
  3. aの値を取得しますresult2

a(ローカルスコープで) が以前に割り当てられていないと仮定c(a)すると、c(undefined)

于 2012-07-10T06:20:51.210 に答える
2

以下のコードを見てください。

function b(data, ref) {
    alert("instantiated B with : " + data + " and "  + ref);
}

function c(ref){
    alert("instantiated C with : " + ref + " ... this doesnt work");
}


var a = new b('blah', new c(a));

'b' は正しく初期化されています。ただし、「c」を初期化する際に表示される警告は次のとおりです。

「インスタンス化された C : undefined ... これは機能しません」

これは、'c' が開始されるまでに、'a' が開始されず、適切に参照されないためです。

jsfiddle を試してください:

http://jsfiddle.net/sNbm5/

于 2012-07-10T05:15:31.887 に答える