Joined March 2014
·

Joseph Dalrymple

Lead Software Engineer at Yum! Brands
·
Dallas, TX
·
·

I totally forgot to get back on here after your reply!

But check out my implementation here.

Most specifically:

var my = { little: { object: "foobar" } };

function getObjectFromString(objRef) {
    myObj = window;

    var refParts = objRef.split('.');
    for (var c=0;c<refParts.length;c++) {
        var classVar = refParts[c];
        if (!classVar || !myObj[classVar]) {
            myObj = null;
            break;
        }

        myObj = myObj[classVar];
    }

    return myObj;
}

var result = getObjectFromString("my.little.object");

console.log(result); // "foobar"

It's not the best implementation in the world, but I wanted to avoid function recursion, so I decided to use a for loop instead that simply sets a variable over and over again. This changes the context and allows you to traverse the dimensions of the object based on the string provided.

The article goes into depth on this as well; See section about Property Declaration and the example in there:

In order to ensure uniqueness among instantiated prototype objects, it is advised to declare objects and arrays within the constructor or methods, rather than during declaration within the closure. Instead, these properties should be declared as "null" or "undefined", with a comment referencing the name of the method in which they are initially set.

Object declarations, however, are allowed when explicitly creating a "global" that all instantiated objects will share, like a defaultOptions object, which should be the same across all instantiated objects.

joe_44850,

Notice how, in my examples, my properties aren't defined until the constructor itself is called. There are many reasons for this, especially when dealing with objects. Property declarations can exist within the prototype object declaration, but in order to make sure things are maintainable and written with multiple instances in mind, a property's value assignment should happen within the Constructor or methods.

Thus, the example you gave should instead be:

var Config = (function () {
    var Constructor = function () {
            this.include = [
                this.dir+"/Common.js",
                this.enginedir+"/Class.js"
            ];
    };

    Constructor.prototype = {
        dir: "js",
        enginedir: "js/Engine",

        include: null
    };

    return Constructor;
})();

var MyConfig = new Config();

Like many other languages, the properties are not available until an instance of the object is created. So, until the constructor is executing, access to the properties is unavailable. This is by design.

Notice, however, in the refactored version above that the declaration and assignment of dir and enginedir is happening at the same time. There's a reason why this can be acceptable, versus the assignment of the include property.

Remember that all primitive values are immutable, and non-primitive values are Objects (inherently). When variables are assigned an object, the variable simply references the object created at assignment. Because of this, when the JavaScript engine parses the code to define Constructor.prototype, it is then that the object will be created and then stored into Constructor.prototype.include. Since Objects are references, modifying the property within one instance will also inadvertently change the property within another instance. This is because we're changing the Object itself, and every instance of Config.include will point to that object, rather than each instance having its own object to manipulate.

In the example I provided, you'll notice that only during instantiation of a new Config is the include property set, thus each instance will have its own include property.

This goes back to non-declarative statements within the main closure, although the dir and enginedir are breaking this rule. Mainly, the rule is in place for logic and non-primitive value assignments. Primitive value assignments are really the only available exception, and strictly within the prototype object declaration.

Because dir and enginedir are set to primitive values, you can technically get away with this exception.

I know of a couple different ways for this to be useful in some of my projects. Especially working with things like properties files that have a syntax similar to my.little.object=foobar per line. A couple of tweaks, and this could become very, very useful for that!

I wrote something similar to this for a project just recently. Except instead of creating an object, I'm searching for it within a context. In other words, "Ns.Utilities.MyUtility" would search for "Ns" inside "window" (unless another context was given), "Utilities" inside that result, and finally "MyUtility" inside that result. I have found it very, very useful. I'll see if I can carve out the time to throw it into a tip!

Also, for those wondering, you do not have to double click on the filename. If you double click on the highlighted area (the term you searched for) it will take you to that occurrence within the file. That way you don't have to jump around :)

I would very much like to know how to open all files, though.

essebé, I'm trying to do the exact same thing. It's quite a pain!

Achievements
56 Karma
25,688 Total ProTip Views