2

私は、javascript を使用して iframe 内のページを変更するウィザードに取り組んでいます。次および前のページへの参照を使用して、ウィザードの各ページのオブジェクトを作成したいと思います。

編集: 以下に投稿されたコードは機能しません。実行後、actionOne.nextAction は {} と等しくなります。

var actionOne = {};
var actionTwo = {};

actionOne = {
    url: 'actionOneUrl.htm',
    prevAction: null,
    nextAction: actionTwo,
    doDisplay: function(){
        $('.label').html('Action One');
    }
}

actionTwo = {
    url: 'actionTwoUrl.htm',
    prevAction: actionOne,
    nextAction: null,
    doDisplay: function(){
        $('.label').html('Action Two');
    }
}

問題は、次の参照と前の参照を適切に設定する方法がわからないことです。比較的単純な解決策がある可能性がありますが、何を検索すればよいかわかりません。すべてのページを作成した後で参照を設定できますが、それを行うのは非常に面倒です。オブジェクトの作成中にそれを行う方法はありますか?

4

7 に答える 7

2

あなたがやろうとしていることについては、JavaScript でオブジェクト指向のアプローチを使用する必要があります。これにより、オブジェクトの新しいインスタンスへの参照を割り当てることができます。たとえば、これは機能します:

http://jsfiddle.net/Gq7vQ/

function Action(url, name){
    this.url = url;
    this.prevAction = null;
    this.nextAction = null;
    this.name = name;
}

Action.prototype.doDisplay = function(){
    $(".label").html(this.name);
}

var actionOne = new Action('actionOneUrl.html', 'Action One');
var actionTwo = new Action('actionTwoUrl.html', 'Action Two');

actionOne.nextAction = actionTwo;
actionTwo.prevAction = actionOne;

console.log(actionOne.nextAction);

編集:OPは、新しく追加されたアクション間のこれらのリンクを自動的に設定する実装を求めました。したがって、ここに二重にリンクされたリストの実装があります:

http://jsfiddle.net/wXC9B/1/

function ActionList(){
    this.head = null;
    this.tail = null;
}

ActionList.prototype.doDisplay = function(index){
    var node = this.getNode(index);

    console.log(node.name);
}

ActionList.prototype.getNode = function(index){
    var current = this.head,
        c = 0;

    while(c < index && current !== null){
        current = current.nextAction;
        c++;
    }

    return current;
}

ActionList.prototype.add = function(url, name){
    var node = {
        url: url,
        name: name,
        nextAction: null,
        prevAction: null
    };

    if(this.head === null){
        this.head = node;
        this.tail = node;
    }
    else{
        this.tail.nextAction = node;
        node.prevAction = this.tail;

        //move tail to new node
        this.tail = node;
    }
}

var actionList = new ActionList();

//Each add automatically sets up links between the two
actionList.add('actionOneUrl.html', 'Action One');
actionList.add('actionTwoUrl.html', 'Action Two');

console.log(actionList.getNode(1));

actionList.doDisplay(1);
于 2013-02-07T19:12:22.730 に答える
1

これは非常に単純化された例ですが、次の構造のようなものを使用すると、次/前のアクションを手動で参照する必要がなくなります...アプリケーションロジックにユーザーの入力に基づいて何をすべきかを見つけさせます。

UnderscoreJSのwhere関数http://underscorejs.org/#whereはここで役立ちます

var dataFromServer = [
  {id:"1", name: "First Page", nextId:"2"},
  {id:"2", name: "Second Page", nextId:"3", prevId: "1"},
  .....];

var actions = [];

var Action = function(data) {
    this.doNextURL = function() {
        //find action with id= data.nextId;
        var actionToDo = _.where(actions, {id: data.nextId})[0];
        window.location.href = actionToDo.url; //or something... a callback parameter, or returning the action rather than doing the 'ui logic' here would be better real world
    }
}

for(var i = 0; i < dataFromServer.length; i+=1){
  actions.push(new Action(dataFromServer[i]));
}
于 2013-02-07T19:04:16.917 に答える
1

これを試してください:actionOne、actionTwoの新しいオブジェクトを作成せず、代わりにコードをそのままにします-ただし、既存のオブジェクト(最初の2行で作成)のオブジェクトプロパティに割り当てます。

var actionOne, actionTwo;

actionOne = {
    url: 'actionOneUrl.htm',
    doDisplay: function(){
        $('.label').html('Action One');
    }
};

actionTwo = {
    url: 'actionTwoUrl.htm',
    doDisplay: function(){
        $('.label').html('Action Two');
    }
};

actionOne.prevAction = null;  //could also be set above
actionOne.nextAction = actionTwo;

actionTwo.prevAction = actionOne;
actionTwo.nextAction = null;  //could also be set above

あなたの質問は非常に良いものでした-他の人に言わせないでください:)かなりのJSの背景があっても、オブジェクトのプロパティがその時点で変数が指していたオブジェクトを指していることは明らかではありません(リテラル)変数自体ではなく、オブジェクト作成ステートメントが実行されました(この場合、例は機能します)。

そして、たとえそれが賛成されたとしても、MVCパターンのことは無視してください。MVCには(時々)何も問題はありませんが、これははるかに基本的なJavascriptの質問であり、これらのパターンは、あなたの小さな興味深い問題とはまったく異なる(より高い)レベルで機能します。

いくつかの背景:オブジェクトを値として持つJavascript実行エンジン変数の内部の奥深くにはポインターがあります(JSエンジンが記述されているため、C / C ++の背景知識はJavascriptを理解するのに役立ちます)。したがって、そのような変数の値をオブジェクトプロパティに割り当てると、変数を指すのではなく、変数がその時点で値を持っているポインタを受け取ります。これは、変数がメモリ内の別の場所を指す新しいオブジェクトを割り当てられた場合、objectプロパティは古いオブジェクトを指し続けることを意味します。代わりに変数を指している場合は、新しいオブジェクトへのポインターが見つかります。ご覧のとおり、質問に答えることで、Javascriptエンジンが実際に非常に低いレベルでどのように機能するかを深く知ることができます:)

他のすべての答えも確かにあなたの当面の問題を解決しますが、私はこの少しの背景を知ることは最終的にはるかに肥沃であると信じています。うまくいく答えを出そうとする代わりに、実際に何が起こっているのかを調査する価値がある場合があります... :)

プリミティブ型は変数に直接格納され、オブジェクトの変数は実際にはポインターです。new String( "foo")はオブジェクト(String)であり、 "foo"はプリミティブ型(string)です。

Javascriptで関数を呼び出すときは、まったく同じ問題を覚えておくことが重要です。技術的には常に値によって呼び出されますが、変数がオブジェクトへのポインターである場合、値はポインターであり、変数に割り当てるときに関数がパラメーターとして取得することを考慮する必要があります。

于 2013-02-07T19:15:22.387 に答える
1

あなたがするとき

actionTwo = {
    // ...
}

に新しい値を割り当てていますactionTwo。で割り当てたオブジェクトをvar actionTwo = {};参照していないため、で使用したオブジェクトを参照していません

actionOne = {
    // ...
    nextAction: actionTwo,
    // ...
}

最も簡単な方法は、両方のオブジェクトを初期化してから、後で正しいプロパティに割り当てることです。

var actionOne = {
    url: 'actionOneUrl.htm',
    prevAction: null,
    nextAction: null,
    doDisplay: function(){
        $('.label').html('Action One');
    }
};

var actionTwo = {
    url: 'actionTwoUrl.htm',
    prevAction: null,
    nextAction: null,
    doDisplay: function(){
        $('.label').html('Action Two');
    }
};

actionOne.nextAction = actionTwo;
actionTwo.prevAction = actionOne;

複数のアクションに対してこれを行いたい場合は、コンストラクター関数の使用を検討する必要があります


オブジェクトの詳細については、MDN - Working with Objectsをご覧ください。

于 2013-02-07T19:14:29.087 に答える
1

オブジェクト リテラルを使用して{}オブジェクトを定義すると、Object コンストラクターで新しいオブジェクト インスタンスが作成されます。

以下は、Object コンストラクターから 2 つの新しいオブジェクト インスタンスを作成します。

var actionOne = {}; // object instance 1
var actionTwo = {}; // object instance 2

この次の部分では、Object コンストラクターから別の新しいオブジェクト インスタンス(3 番目のオブジェクト インスタンス) を作成し、いくつかのプロパティを追加します。(独自のプロパティを持たない)actionOne.nextActionのオブジェクト インスタンスを指します。actionTwo

actionOne = {
    url: 'actionOneUrl.htm',
    prevAction: null,
    nextAction: actionTwo,
    doDisplay: function(){
        $('.label').html('Action One');
   }
} // object instance 3

したがって、宣言するactionTwo = {....}と、一連の新しいプロパティを持つ4 番目のオブジェクト インスタンスが作成されます。actionOne.prevAction作成した 2 番目のオブジェクト インスタンスをまだ指しています (ただし、グローバル変数 actionTwo を参照していません)。

覚えておくべき重要な点は、オブジェクト リテラル{}は Object コンストラクターを使用して新しいオブジェクト インスタンスを作成し、作成したプロパティは宣言時にオブジェクト インスタンスを参照するということです。

于 2013-02-07T19:31:15.817 に答える
0

誰もがこれを非常に複雑にしているようです。

function Wizard(o) {
    return { url:o.url, doDisplay:function() { $('.label').html(o.html); } };
}
var wizards = [{url: 'actionOneUrl.html', html:'Action One'},
               {url: 'actionTwoUrl.html', html:'Action Two'}].map(Wizard);
    // wizards now contains an array of all your wizard objects
wizards.reduce(function(p,c) { c.prevAction = p; return p.nextAction = c;  });
    // prevAction and nextAction now point to the right places
于 2013-02-07T20:39:35.553 に答える
-1

いいえ、できませんが、空のオブジェクトを保持して、それらを埋めることはできます。

var actionOne = {};
var actionTwo = {};

actionOne.url = 'actionOneUrl.htm';
actionOne.prevAction = null;
actionOne.nextAction = actionTwo;
...

しかし、それはかなり醜いです。次のような関数を使用して、それらの間のリンクを入力することをお勧めします。

function chain() {
    var i, prev, curr;
    for(i = 0; i < arguments.length; i++) {
        curr = arguments[i];
        if(prev) {
            prev.nextAction = curr;
            curr.prevAction = prev;
        }
        else {
            curr.prevAction = null;
        }
        prev = curr;
   }
   if(curr) curr.nextAction = null;
}


var actionOne, actionTwo;

actionOne = {
    url: 'actionOneUrl.htm',
    doDisplay: function(){
        $('.label').html('Action One');
    }
}

actionTwo = {
    url: 'actionTwoUrl.htm',
    doDisplay: function(){
        $('.label').html('Action Two');
    }
}

chain(actionOne, actionTwo);
于 2013-02-07T19:15:32.133 に答える