Quoting from MDN
if the method is a function in non-strict mode,
nullandundefinedwill be replaced with the global object and primitive values will be converted to objects.
This explains why you get an object when you call test.call(null);. When null is passed here, this inside test() will be global object Window.
For the desired behavior, use strict mode.
function test() {
"use strict";
if (this === null) {
console.log("This is null");
} else {
console.log("This is Object");
}
}
test.call(null);
test.call({});
Quoting from ES6 Specifications for strict mode
If
thisis evaluated within strict mode code, then thethisvalue is not coerced to an object. Athisvalue ofnullorundefinedis not converted to the global object and primitive values are not converted to wrapper objects. Thethisvalue passed via a function call (including calls made usingFunction.prototype.applyandFunction.prototype.call) do not coerce the passed this value to an object