【问题标题】:Multiple instances of constructor not working构造函数的多个实例不起作用
【发布时间】:2015-12-11 22:48:10
【问题描述】:

当我只用一个 Cat (var cat1) 实例运行这个程序时,它运行良好。 当我运行第二个实例时 (var cat2),事情停止工作。

function main() {
    var catPic = document.getElementById('catPic');
    var numClicks = 0;
    var numCats = -1;
    var scope;

    var Cat = function Cat(name, url) {
        numCats++;
        scope = this;
        this.name = name;
        this.url = url;
        this.numClicks = 0;
        this.clickId = 'clicks' + numCats;

        window.onload = function() {

            //Puts a new Cat on the screen. The name, image, and # of clicks will be shown.
            appendCat(scope.name, scope.url, scope.clickId, scope.numClicks, numCats);

        }
    };

    var cat1 = new Cat('Bob', 'https://lh3.ggpht.com/nlI91wYNCrjjNy5f-S3CmVehIBM4cprx-JFWOztLk7vFlhYuFR6YnxcT446AvxYg4Ab7M1Fy0twaOCWYcUk=s0#w=640&h=426');
    var cat2 = new Cat('Samantha', 'https://lh3.ggpht.com/nlI91wYNCrjjNy5f-S3CmVehIBM4cprx-JFWOztLk7vFlhYuFR6YnxcT446AvxYg4Ab7M1Fy0twaOCWYcUk=s0#w=640&h=426');
}

main();

问题与 appendCat();功能。

    //Puts a new Cat on the screen. The name, image, and # of clicks will be shown.
    function appendCat(name, url, clickId, numClicks, numCats) {
        document.body.appendChild(document.createElement('div'));
        document.getElementsByTagName('div')[numCats].setAttribute('id', 'cat' + numCats);

        document.body.getElementById().appendChild(document.createElement('h2'));
        document.getElementsByTagName('h2')[numCats].textContent = name;

        document.body.appendChild(document.createElement('img'));
        document.getElementsByTagName('img')[numCats].setAttribute('id', name);
        document.getElementsByTagName('img')[numCats].setAttribute('src', url);

        document.body.appendChild(document.createElement('p'));
        document.getElementsByTagName('p')[numCats].setAttribute('id', clickId);
        document.getElementsByTagName('p')[numCats].textContent = numClicks;

        document.body.appendChild(document.createElement('br'));
        document.body.appendChild(document.createElement('br'));
    }

当运行此函数的前两行时,document.getElementsByTagName('div')[numCats] 的计算结果为未定义。我不确定为什么会这样。 Console.log() 对我也没有多大帮助。谢谢!

【问题讨论】:

  • 这是实际代码吗?不确定document.body.getElementById() 将如何运行而不会出现错误。另外,您将var scope 放入main() 而不是function Cat() 有点奇怪。事实上,每个新的Cat 都会将其this 设置为所有 Cat 对象的scope
  • 它不是 C++。为什么在构造函数中使用window.onloadappendCat?而您的scope.numClicks 始终为 0。
  • 谢谢!我已经完全删除了范围变量。我还将所有不应该在构造函数中的东西移到了别处。感谢你们两个(当然还有@Ethan Lynn),我绝对不会再犯我在这段代码中犯的错误了。
  • 什么是 document.body.getElementById() ?不知道它怎么能运行一次?

标签: javascript debugging undefined


【解决方案1】:

首先您的scope 变量需要在构造函数中声明,以便window.onload 引用正确的实例。否则,两个window.onload 处理程序都将引用在window.onload 触发时设置的范围值——这将始终是第二个实例。其次,您需要使用window.addEventListener("load", function () { ... }"),而不是设置window.onload,以便每个实例都有自己的侦听器。 window 对象只有一个 onload 属性,因此多次设置它不会创建多个侦听器,它只会覆盖以前的侦听器。

作为补充说明,我建议从构造函数中删除事件处理并将其放置在如下内容之外:

var cats = [
    new Cat(...),
    new Cat(...)
];
window.addEventListener('load', function () {
    cats.forEach(function (cat) {
        appendCat(cat.name, cat.url, cat.clickId, cat.numClicks, cats.length);
    });
});

这将删除scopenumCats 变量并将所有window.onload 功能移动到一个处理程序,而不是每个实例都有一个处理程序。

【讨论】:

  • 谢谢!阅读您的回复后,发生了很多捂脸。此外,我最终使用了 for() 循环而不是 forEach(更好的性能)。
  • 你运行他的代码了吗?事实上,我看到了很多其他问题!
猜你喜欢
  • 1970-01-01
  • 2018-07-27
  • 2013-08-28
  • 2020-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多