在其中一个属性中添加对Javascript对象的引用是不好的做法?

时间:2013-10-18 23:26:10

标签: javascript

假设我有这样的设置。

var Account = function(data) {
  this.data = data;
  this.domElement = (function(){ code that generates DOM element that will represent this account })();
  this.domElement.objectReference = this;
}

Account.prototype = {
  show: function() { this.domElement.classList.remove('hidden'); },
  hide: function() { this.domElement.classList.add('hidden') }
}

我的问题是关于最后一行:this.domElement.objectReference = this;

这将是一个有用的东西,因为我可以添加事件监听器到我的DOM元素,仍然可以访问对象本身。我可以添加会影响我的DOM元素的方法,例如hide()和show(),而不必直接使用CSS修改DOM元素的可见性。

我测试了这段代码并且它的工作方式与我想要的一样,但我很好奇这是否会导致内存泄漏或其他一些不愉快,或者这是否可以接受?

谢谢! 卢卡

3 个答案:

答案 0 :(得分:2)

我知道@PaulS已经回答了这个问题。已经,但我发现答案计数器直观(不希望从Account构造函数返回DOM元素)和DOM中心,但同时实现非常简单,所以我不知道该怎么想;)< / p>

无论如何,我只想展示一种不同的方式。您可以在地图中存储Account个实例,并为它们提供唯一的id(可能已经有一个),然后将id存储为DOM元素的数据属性。最后,您实现getById函数或类似的功能,以便从侦听器中通过id检索帐户实例。

这就是jQuery data的工作方式。

以下是您希望从评论中获得委托事件的示例。

<强> DEMO

var Account = (function (accounts, id) {

    function Account(data) {
        accounts[this._id = ++id] = this;

        this.el = createEl.call(this);
    }

    Account.prototype = {
        constructor: Account,
        show: function() { this.el.classList.remove('hidden'); },
        hide: function() { this.el.classList.add('hidden'); }
    };

    function createEl() {
        var el = this.el = document.createElement('div');
        el.className = 'account';
        el.innerHTML = el.dataset.accountId = this._id;

        return el;
    }

    Account.getById = function (id) {
        return accounts[id];
    };

    Account.init = function () {
        //add delegate listeners

        document.addEventListener('click', function (e) {
            var target = e.target,
                account = Account.getById(target.dataset.accountId);

            if (!account) return;

            account.hide();
        });
    };

    return Account;
})({}, 0);

//once DOM loaded
Account.init(); //start listening to events

var body = document.body;

body.appendChild(new Account().el);
body.appendChild(new Account().el);

答案 1 :(得分:1)

为什么不将domElement作为var iable,将return作为函数?要保留对构造的对象的引用(但仅限于this符合预期的位置),您可以执行if (this instanceof Account) domElement.objectReference = this;

您现在已经从循环引用中保存了自己,并且可以访问节点对象。如果您希望丢失对帐户实例的直接引用,那么这样做会更有帮助,但是在“查找”节点时需要它稍后会涉及到。

Code as requested

var Account = function (data) {
    var domElement; // var it
    this.data = data;
    domElement = (function(){/* ... */}()); // use var
    if (this instanceof Account)
        domElement.objectReference = this; // assign `this`
    return domElement;
};
// prototype as before

返回的元素现在是节点,而不是对象;所以你可以像这样访问帐户实例

var domElement = new Account();
domElement.objectReference.show(); // for example

答案 2 :(得分:0)

在我看来,引用对象本身内部的对象没有任何好处。造成这种情况的主要原因是复杂性和模糊性。

如果你想指出你在代码中稍后如何使用这个domElement.objectReference,我相信我或其他人能够在没有这个参考的情况下提供解决方案。