1

I got this code in a function.

The first line works.

    this.learningPlan.learnerType = ['abc']; // this line works

but these lines below won't.

    properyName = 'learningPlan.learnerType';
    this[properyName] = ['abc'];

Is there a way to refer to the this so I can pass the properyName value to the function?

I need this functionality so I can keep the function generic and not mention the specific phrase 'learningPlan.learnerType'. Cause then I can do the following:

function blah(propertyName){
        this[properyName] = ['abc'];
}
Average Joe
  • 4,521
  • 9
  • 53
  • 81
  • 1
    Does `this['learningPlan']['learnerType'] = ['abc'];` work? If so, `blah()` could split the `propertyName` on `.` and then loop through the results. – Forty3 Dec 07 '17 at 01:54
  • 1
    Based on the perceived context, `this.learningPlan.learnerType = ['abc']; ` should not work. – Jay Harris Dec 07 '17 at 02:04
  • @Forty3 Does this['learningPlan']['learnerType'] = ['abc']; work? YES, IT DOES. I also checked your implementation but with the reduce built in, it's difficult to follow what's happening, what the logic is. I see that you split on the dot, and you get the prop & val, as p & s, but then I get lost afterwards.. Could you tell me what's happening in here: ` var o = ps.reduce(function(a,e){ a[e] = (a[e] || {}); return a[e]; }, this);` And could this be simplified? – Average Joe Dec 07 '17 at 06:29
  • I also observed that surprisingly, this does not work neither: `this[objectLeft][objectRight] = ['abc'];` despite the following totally works: `this['learningPlan']['learnerType'] = ['abc'];`. It's just unbelievable! Here, the objectLeft & objectRight are just passed in as simple strings as 'learningPlan' and 'learnerType' respectively. All I can sat that there is something definitely weird about the way 'THIS' works internally. – Average Joe Dec 07 '17 at 06:38
  • To my surprise, I also observed the following: `// works ->> this.learningPlan.learnerType = ['abc']; and // does not work ->> eval("this.learningPlan.learnerType = ['abc'];"); --- Even the eval is not a way out of this??? – Average Joe Dec 07 '17 at 12:31
  • In order for `this[objectLeft][objectRight] = ['abc']` to work, you have to ensure that `this[objectLeft]` exists as a property of `this` before you attempt to reference its `objectRight` property. – Forty3 Dec 07 '17 at 13:45
  • True, but since ` this.learningPlan.learnerType = ['abc'];` already works, we can safely say that both the object & the property exists.. I will check your code, THANK YOU so much for the explanations. I will get back to you on that later. But the lines marked by me as `// does not work` in my above comments still boggle my mind. Even the eval fails. – Average Joe Dec 07 '17 at 16:06
  • This may explain why the `eval(...)` fails [SO Answer](https://stackoverflow.com/a/25859853/3485669) insofar as it explains why the `eval` lacks the context. – Forty3 Dec 07 '17 at 18:04

1 Answers1

1

How does this look:

Edit: Added explanatory comments.

function T() {
    this.learningPlan = { learnerType : "aaa" };
    this.setVal = function(p, v) {
        // Split the property string into its "parts"
        // thus "learningPlan.learnerType" becomes ["learningPlan","learnerType"]
        var ps = p.split(".");

        // Remove and capture the "last" (right-most) property
        // From ["learningPlan","learnerType"] this would be "learnerType"
        // leaving the array with ["learningPlan"]
        var lastProp = ps.pop();

        // Work "down" the object finding each level object finally returning
        // the property object containing the property you wish to set
        var o = ps.reduce(function(a,e) { 
          // This checks that each object["property"] exists and if
          // it doesn't then it creates an empty object so that it can
          // continue traversing down the property hierarchy. 
          // Given the property string "learningPlan.learnerType" if the
          // property this.learningPlan didn't exist then attempting to 
          // reference this.learningPlan.learnerType would throw an error
          // since learnerType is not a property of undefined. This is, I
          // believe, the error you are experiencing. Using (a[e] || {}) 
          // ensures that a[e] references something so that traversal
          // can continue.
          a[e] = (a[e] || {}); 

          // This simply returns the property so that the reduce can keep 
          // moving through the array
          return a[e]; 
        }, this);

        // Finally, we set the value for the last property in our string.
        // The above reduce would walk down 'this' finding/setting each 
        // property until it reached the last string we left in our array
        // after the pop and thereby returning a reference to that property
        // into our variable "o". We then use the last property string as a
        // property of "o" to set our value. 
        o[lastProp] = v;
    };
}

It will allow you to do things like:

var t = new T();
t.setVal("learningPlan.learnerType", "def");
Forty3
  • 2,199
  • 1
  • 14
  • 19