Talk is cheap; show me the code.
// equals to this.test = "inside window"
var test = "inside window";
function f () {
console.log(this.test)
};
var obj = {
test: "inside object",
fn: f
};
obj.fn(); // "inside object" --> fine
(obj).fn(); // "inside object" --> fine
(1, obj).fn(); // "inside object" --> fine
(obj.fn)(); // "inside object" --> fine
(0 || obj.fn)(); // "inside window" --> why?
// reference equality check
console.log(
f === obj.fn &&
(obj.fn) === f &&
f === (1, obj.fn)
); // all equal :/
I had read ydkjs book and Im familiar with call-site and dynamic this
binding, but I don't understand why the last function call has window
as its this
context; in this controlled experiment that only thing
that is changed ()
and comma operator
and as you can see in the last statement comma operator
is doing something weird. I suspect it does an assignment when it returns the value (since if we do an assignment the same result happens) but I'm not sure.
The effect is also seen on &&
, ||
operators: (0 || obj.fn)()
Given:
foo.bar()
Inside bar
, this
will be foo
.
(There are exceptions, such as when bar
is defined with an arrow function, but they don't apply in this case).
Given:
const bar = foo.bar;
bar();
Now the function has been called without the context of foo
so this
is now the default object (which is window
in a browser).
The expression: (1, foo.bar)
evaluates as the right-hand side. This is the function.
Just as if you had copied it to a variable, this disconnects the function from the object before you call it, so you get the same effect.
There's no assignment because you haven't involved a variable, but you are calling the result of an expression and not the object method directly.