2

I was studying the behavior of this inside object methods and I have got stuck at one output.

Here is the code.

'use strict';

let obj, method;

obj = {
  go() { alert(this); }
};

obj.go();               // (1) [object Object]

(obj.go)();             // (2) [object Object]     QUESTION 2

(method = obj.go)();    // (3) undefined

(obj.go || obj.stop)(); // (4) undefined     ------> Doubt  <-------------------

So if the fourth one is logically equivalent to the second one, why does the logical OR cause the context to be lost?

Part-2

Please correct me if I am wrong.

  1. The evaluation of this ocurrs the way it is called/invoked with function declaration/expression.

  2. Inside arrow function, this always refers to its enclosing parent . [lexical scope]

0

3 Answers 3

1

In case 2, the parentheses do not change the fact that the function reference value on the left side of () came from an object property reference. Thus the function invocation happens in exactly the same way as in case 1, with the object reference bound to this.

In case 4, however, the || evaluation inside those parentheses cause that relationship to be lost; all that's left is the function reference without any related object. That's because the logic of || doesn't care about the fact that the function reference came from an object property lookup, so it's result value is just the function reference "naked".

As to your follow-on questions, neither assertions are worded correctly. The value of this does depend on how a function is invoked, but that has nothing to do with where the function came from or how it was declared. Inside arrow functions, the value of this is not a reference to its lexical parent, it's the same as the value of this in the lexical parent.

Sign up to request clarification or add additional context in comments.

5 Comments

I will say that this behavior is somewhat surprising, though I think if it worked differently that would introduce a tremendous amount of complexity in the runtime.
(obj.go || obj.stop)(); -> how the evaluation happens?...first dot operator, then or operator, obj.go is true..thus it reduces to obj.go()...i know somewhere my assertion is wrong..Please elaborate the evaluation process
The obj.go expression is evaluated, and its value is checked to see if it's "truthy". It is, so the evaluation of the || expression stops and the overall value is the function reference. If you read the spec (which is tedious and difficult, unfortunately) the key difference is the difference between getting a reference to a value and the actual value itself. It's fairly arcane; it's more practical to simply accept that the relationship between a function-valued object property and the object is lost in any expression evaluation.
so in any expression evaluation, the reference values gets lost..right?
@tedd the object - function relationship gets lost, yes, unless the expression is only object.propertyName
1

@Pointy already answered your question. Just for fun: knowing what you know now, you can get your obj.go method to run in its own scope, wrapping in an arrow function expression:

let obj, method, otherMethod, m2;

obj = {
  foo: `obj.foo here, saying: done`,
  go(txt = ``) { console.log(`obj.go here, called as: ${txt} => ${this.foo}`); }
};
(txt => obj.go(txt))(`(txt => obj.go(txt))([...])`);
(method = txt => obj.go(txt))(`(method = txt => obj.go(txt))([...])`);
(obj.go && 
  (txt => obj.go(txt)) || 
  obj.stop)(`(obj.go && txt => obj.go(txt) || obj.stop)([...])`);

// or use a wrapper (factory function)
const wrap = (...[obj, method, txtArg]) => () => obj[method](txtArg);
(otherMethod = wrap(obj, `go`, `(otherMethod = wrap(obj, \`go\`, \`[...]\`))()`))();

// or make `go` a getter and that getter a factory function
let otherObj = {
  foo: `and hithere, here's otherObj.foo`,
  get go() { return txt => 
    console.log( `otherObj.go here, called as: ${txt} => ${this.foo}` ); }
};

(m2 = otherObj.go)(`(m2 = otherObj.go)([...])`);
.as-console-wrapper { top: 0; max-height: 100% !important; }

Comments

0

Actually, #'s 3 and 4 return [object Window]

See comments:

let obj, method;

obj = {
  go() { alert(this); }
};

obj.go();               // [object Object] represents obj

(obj.go)();             // [object Object] represents obj

(method = obj.go)();    // [object Window] because the go method is not running in the context of obj

(obj.go || obj.stop)(); //  Same as above

1 Comment

i have used the 'use strict ', i have added that to the code now

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.