簡體   English   中英

如何在JavaScript中創建統一的對象?

[英]How do I create an unitialized object in javascript?

我正在使用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');
    }
}

問題是我不知道如何正確設置下一個和上一個參考。 可能有一個相對簡單的解決方案,但我不確定要搜索什么。 創建所有頁面后,我可以設置引用,但是這樣做很麻煩。 創建對象時有沒有辦法做到這一點?

對於您想做的事情,您將需要在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);

這是一個非常簡化的示例,但是類似下面的結構將避免需要手動引用您的下一個/上一個操作...讓應用程序邏輯根據用戶的輸入來查找要做什么。

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]));
}

當你做

actionTwo = {
    // ...
}

您正在為actionTwo分配一個新值。 它不再引用您在var 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;

如果要對多個操作執行此操作,則應考慮使用構造函數,如joeltine在他的答案中所示


要了解有關對象的更多信息,請查看MDN-使用對象

嘗試以下操作:不要為actionOne,actionTwo創建NEW對象,而是將代碼保持原樣-而是為已存在的對象(由前兩行創建)分配給對象屬性。

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問題,這些模式問題在一個與您有趣的小問題完全不同(更高)的水平上發揮了作用。

一些背景:以對象為值的Java腳本執行引擎變量的內部深處是指針(C / C ++背景知識對於理解Java腳本非常有用,因為JS引擎是用Java編寫的)。 因此,當您將此類變量的值分配給對象屬性時,它不會指向該變量,而是將接收該變量當時具有值的指針。 這意味着,如果變量被分配了一個新對象,指向內存中的另一個位置,則object屬性將始終指向舊對象。 如果它指向變量,它將找到一個指向新對象的指針。 如您所見,回答您的問題使我們深入了解Javascript引擎實際上是如何在很低的水平上工作的:)

所有其他答案肯定也可以解決您的迫在眉睫的問題,但是我相信知道這一點背景最終會更加肥沃。 除了嘗試給出可行的答案外,有時還值得調查實際發生的事情... :)

基本類型直接存儲在變量中,對象的變量實際上是指針。 new String(“ foo”)是一個對象(字符串),“ foo”是一個原始類型(字符串)。

在Java語言中調用函數時,請牢記完全相同的問題! 從技術上講,它總是按值進行調用-但是,當變量是指向對象的指針時,值就是指針,將變量作為參數分配給變量時必須考慮該指針。

當使用{}對象常量來定義對象時,您將使用Object構造函數創建一個新的對象實例。

以下從Object構造函數創建兩個新的對象實例:

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

下一部分將通過Object構造函數創建另一個新的對象實例 (第三個對象實例),並添加幾個屬性。 actionOne.nextAction指向的對象實例actionTwo (其中沒有任何自己的屬性)。

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

因此,現在,當您聲明actionTwo = {....}會創建帶有多個新屬性的第四個對象實例 actionOne.prevAction仍指向您創建的第二個對象實例(但不再使用全局變量actionTwo進行引用)。

要記住的關鍵是對象文字{}使用Object構造函數創建新的對象實例,並且您創建的屬性在聲明它們時引用該對象實例。

每個人似乎真的使這個問題復雜化了。

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

不,您不能,但是您可以保留空對象並填充它們:

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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM