简体   繁体   中英

Javascript prototype - Need help adding a Helper prototype

OK, I doubt this is a unique situation, so either someone has done this, or someone has decided this isn't possible, at least in the way I am asking.

I have 2 prototyped variables (functions), one is the parent, the other is a helper. What I'd like to do is reference the parent from within the helper such that each instance of each parent can utilize the helper while allowing the helper to essentially extend the parent. I'm using jQuery and javascript.

Here's a simplified example:

var Parent = function(identity) {
    this.identity = identity;
    this.group = $(this.identity);
    this.helper = new Helper(this);
    return this;
};
Parent.prototype = {
    _setup : function(dolisten) {
        dolisten = dolisten || false;
        var that = this;
        that.group.each(function(i) {
            if ($(this).data('key') !== 'undefined') {
                that.elems[i] = new Object();
                that.elems[i].key = parseInt($(this).data('key'));
                // build out rest of elems object
            }
        });
        if (dolisten) {
            this._listen();
        }
    },
    _listen : function() {
        var that = this
        $('body').on('click tap', that.identity, function() {
            that.helper._showbusy(this, true);
            // do some other stuff
        }
    }
};
var Helper = function(reference) {
    this.reference = reference;
};
Helper.prototype = {
    _showbusy : function(elem, isbusy) {
        console.log(this.reference);
        // do some stuff to elem
    },
};

This works but creates an essentially infinite reference to Parent from within its own .helper node. So, without actually passing the parent every single time (hoping to create a single point of reference just once, the above seems to cause a reference "loop"?), can this be done elegantly?

In the end, what I would like is a simple:

var obj = new Parent('.myClass');
console.log(obj);
// result : Parent { identity:'.myClass', group: [Object object], helper: {reference : *Parent without helper key included, which is where the looping seems to occur}, etc...

EDIT: For the time being, I'm resorting to passing in the specific keys of the parent that are needed by the helper. This prevents the helper from infinitely cascading into copies of the parent and itself, but a more elegant solution, where helper has access to the entire parent instead of just the specific keys passed, without cascading helper's reference to parent to become parent -> helper -> parent -> helper -> parent -> etc...

What you are referring to is called a circular reference , which is defined as two data structures that both reference each other.

var a = {value: 'A'};
var b = {value: 'B'};
a.b = b;
b.a = a;

console.log(a.b.a.b.a.b.a.b.a.b.a.b.value); // 'B'

And in most cases, this is actually okay. Modern garbage collectors are smart enough to clean this up when the objects expire, so memory should be handled fine. Lots of JS code out there ceates objects with circular references.

The biggest problem you'll hit is if you want to encode the object to JSON, or do anything recursive with the object.

// continued code form above
JSON.stringify(a);
// TypeError: Converting circular structure to JSON

Because JSON generation is a recursive process, it's drilling into every property which would get locked in the circular reference and generate an infinite amount of JSON.

There are some ways handle that though

I made some adjustments to my code and after console.logging the results, it appears to be much cleaner. I'm posting this as a potential answer because, well, I could edit my question but I'd like to keep the feedback separate between question and answer, and see if anyone has any potential changes or alternatives, other than those already posted, that may provide a better solution.

For now, I'm going to go with this:

var Parent = function(identity) {
    if (identity) {
        this.identity = identity;
        this.group = $(this.identity);
        if (this.group.length > 0) {
            this.elems = new Array();
            this.helper = new Helper(this);
            this._setup(true);
        }
    }
    return this;
};

and

var Helper = function(reference) {
    for (var key in reference) {
        if (!this[key]) {
            this[key] = reference[key];
        }
    }
};

and extend accordingly from there.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM