javascript类中的神秘bug

时间:2012-04-28 11:32:58

标签: javascript jquery dom

这是我的一个javascript类的代码:

function Foo(text)
{
   var container = document.createElement('span');
   container.innerHTML = text;
   $("#fooContainer").append(container);

   this.select = function()
   {
       $(container).addClass('selected');
   }

   this.getContainer = function()
   {
       return container;
   }

   this.getText = function()
   {
      return text;
   }
}

在每次页面加载时,我会执行以下操作:

var fooList = {};

fooList['foo1'] = new Foo('Foo 1');
fooList['foo2'] = new Foo('Foo 2');
fooList['foo3'] = new Foo('Foo 3');

这会导致正确创建每个foo对象的跨度,从而在dom中生成:

<div id="fooContainer">
    <span>Foo 1</span>
    <span>Foo 2</span>
    <span>Foo 3</span>
</div>

但是,如果我这样做:

fooList['foo1'].select();

然后它导致:

<div id="fooContainer">
    <span>Foo 1</span>
    <span>Foo 2</span>
    <span class="selected">Foo 3</span>
</div>

而不是预期的,这是:

<div id="fooContainer">
    <span class="selected">Foo 1</span>
    <span>Foo 2</span>
    <span>Foo 3</span>
</div>

似乎所有container个对象的foo对象都指向最后一个foo的容器,在本例中是foo 3.为了进一步测试它,我做了这个:

    for (var key in fooList)
    {
        console.log(key);
        console.log( fooList[key].getText() );
        console.log(fooList[key].getContainer() );
    }

这导致这被记录在firebug控制台中(仅显示第一个foo):

foo1
Foo 1
<span>

当我点击span时,然后在firebug中,它指向跨度的第3个而不是预期的第一个或第二个。

任何想法我做错了什么?我是否需要为跨度设置ID?

4 个答案:

答案 0 :(得分:3)

您确定在代码中容器之前有var吗?

答案 1 :(得分:2)

你正在混合和匹配直接的javascript DOM操作和jQuery方法。不要那样做。

如果要使用jQuery将元素附加到另一个元素,请使用jQuery来执行这两个操作,或者两者都不使用。而不是

var container = document.createElement('span');

使用jQuery的版本:

var container = $("<span>");

当然使用JQuery的方式添加html:

container.html(text);

等等。

如果你真的冥想使用document.createElement(),我认为你可以逃脱:

$("#fooContainer").append($(container));

答案 2 :(得分:1)

尝试:

function Foo(text)
{
   var container = document.createElement('span');
   container.innerHTML = text;
   $("#fooContainer").append(container);

   this.container = container
   this.text = text

   this.select = function()
   {
       $(this.container).addClass('selected');
   }

   this.getContainer = function()
   {
       return this.container;
   }

   this.getText = function()
   {
      return this.text;
   }
}

答案 3 :(得分:1)

我认为您提出的解决方案恰到好处。 我通常不会在Jquery上编写,但是根据我的理解,$()方法用于通过id引用对象,或者按类引用对象数组。不知道通过传递DOM对象引用会发生什么,但在内部某些浏览器在将新DOM元素附加到子元素时重新引用子对象。试试这个:

var foo_count = -1;
function Foo(text)
{
   foo_count++;
   var id = foo_count;

   var container = document.createElement('span');
   container.setAttribute('id', "foo_" + id);
   container.innerHTML = text;
   $("#fooContainer").append(container);

   this.select = function()
   {
       $("#foo_" + id).addClass('selected');
   }

   this.getContainer = function()
   {
       return $('#foo_' + id);
   }

   this.getText = function()
   {
      return text;
   }
}