JavaScript: Are (0, x.f) and (x.f) really different

81 Views Asked by At
x={f(){return this}}
x.f()  //x
(x.f)()  //x
(0,x.f)() //window

I've learned that parenthesis (grouping operator) does not apply GetValue to the expression inside it, while other operators such as , and || do. Does it mean (x.f) and (0,x.f) are actually two different object in the memory, so their this are also bounded to different objects. However, I tried the following ways to compare two functions themselves (not the value they return), they both shown the same. These methods cannot really compare their memory address so I have no idea if they are the same object.

(x.f)==(0,x.f) //true
(x.f)===(0,x.f) //true
Object.is((x.f),(0,x.f)) //true
1

There are 1 best solutions below

0
ruakh On

Does it mean (x.f) and (0,x.f) are actually two different object in the memory, so their this are also bounded to different objects.

No, it doesn't mean that at all.

In the below code-snippet, x.f and y.f are the same function object, yet x.f() and y.f() return different results.

const x = { value: 3 };
const y = { value: 4 };

x.f = y.f = function () { return this.value };

console.log(x.f());  // logs '3'
console.log(y.f());  // logs '4'

How can this be?

Well, it's because this isn't actually a characteristic of the function itself; rather, it's passed into the function when the function is called, in much the same way that arguments are passed in. Just as function f(arg) { return arg } returns 7 when called as f(7) but 8 when called as f(8), so function f() { return this } returns x when called as x.f() but y when called as y.f().

This is an essential aspect of how methods work in JavaScript; it's what enables inheritance. For example, [1, 2, 3].slice(2) and [4, 5, 6].slice(2) both call the same slice function, which is defined on the prototype instance that they both inherit from, but it's able to return the right information for whichever array it's called on.

So, returning to your example . . . x.f and (x.f) and (0, x.f) all evaluate to the same function, but whereas x.f() and (x.f)() both say to call that function and pass x as the this argument, (0, x.f)() does not say to pass x as the this argument (so it defaults to passing the global object, window, as the this argument).