繁体   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