1

I encounter a very tricky case:

class C {
  // class method are implicit in strict mode by default
  static method() { return this === undefined; }  
}

C.method(); // => false
(0,C.method)(); // => true

Why (0, C.method) changes the binding of this in the above case?

3
  • The context changes from the class to global so this is undefined. Commented Jan 8, 2017 at 5:36
  • You may want to read the MDN description of how this works with object methods. Commented Jan 8, 2017 at 5:40
  • @4castle If a memory is declared and initialized through var, it makes sense; but how does the expression (0, C.method) allocates new memory slot? Commented Jan 8, 2017 at 5:40

2 Answers 2

4

That's because C.method returns a reference like

{ base: C, referencedName: "method", strict: strictFlag }

When you call it, JS obtains the function using GetValue with that reference, and provides the base of the reference (C) as the this value.

CallExpression : MemberExpression Arguments

 1. Let ref be the result of evaluating MemberExpression. // <-- The reference
 2. Let func be ? GetValue(ref).                          // <-- The function
 4. If Type(ref) is Reference, then
    a. If IsPropertyReference(ref) is true, then
       i. Let thisValue be GetThisValue(ref).             // <-- C

However, when you use the comma operator, you directly get the function, not the reference.

Expression : Expression , AssignmentExpression

 1. Let lref be the result of evaluating Expression.
 2. Perform ? GetValue(lref).                             // <-- 0
 3. Let rref be the result of evaluating AssignmentExpression.
 4. Return ? GetValue(rref).                              // <-- The function

Since there is no reference, JS can't know the base object, so when you call it provides undefined as the this value.

CallExpression : MemberExpression Arguments

 1. Let ref be the result of evaluating MemberExpression. // <-- The function
 2. Let func be ? GetValue(ref).                          // <-- The function
 5. Else Type(ref) is not Reference,
    1. Let thisValue be undefined.                        // <-- undefined
Sign up to request clarification or add additional context in comments.

Comments

3

When you use the comma operator in JavaScript, both operands are evaluated, and then the right-most value is returned. The evaluated function value that comes out of the parentheses has no context of where it came from. This can be likened to assigning a value to a variable, where the right-hand side of the assignment operator = is evaluated before the value is assigned:

(0, C.method)();
//  ^^^^^^^^ evaluates here

var func = C.method;
//         ^^^^^^^^ evaluates here
func();

Once a function is put into a variable, it loses all context of what object it came from (unless bind is used). This context is important to determining the value of this. When a function is called without being the member of an object, it defaults to the global object, or undefined if the function is in strict mode. (MDN)

Comments

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.