Maybe this is a newbie question, but I cannot find or think out the explanation.
Start the Node.js console, and:
> global.hasOwnProperty === hasOwnProperty
true
Then why
> global.hasOwnProperty("x")
false
but
> hasOwnProperty("x")
TypeError: Cannot convert undefined or null to object
at hasOwnProperty (<anonymous>)
at repl:1:1
at sigintHandlersWrap (vm.js:22:35)
at sigintHandlersWrap (vm.js:96:12)
at ContextifyScript.Script.runInThisContext (vm.js:21:12)
at REPLServer.defaultEval (repl.js:313:29)
at bound (domain.js:280:14)
at REPLServer.runBound [as eval] (domain.js:293:12)
at REPLServer.<anonymous> (repl.js:513:10)
at emitOne (events.js:101:20)
?
The issue here is that hasOwnProperty()
is a method of an object and its entire function is to operate on properties of that object. As such, it only works if, when it is called, it is given a proper object context. Normally they are written methods, expect that object context is to arrive in the value of this
when the method is invoked.
In most cases in JavaScript (except for functions defined with the arrow syntax), the value of this
is determined by how a method is called. The usual and most common way to invoke a method on the appropriate object is with:
obj.method()
This will cause JavaScript to set this
to obj
when it called method()
.
If you do something like this:
var myFunction = obj.method;
And, then you call that method with no object reference as in:
var myFunction = obj.method;
myFunction();
Then, the object reference in obj
is lost and is not given to the method in any way. The JavaScript interpreter will pick a default value for this
.
In strict mode, this
will be set to undefined
and any method that attempts to use that value, expecting it to be an object reference, will fail.
In non-strict mode, a browser will set this
to point to "some default value". In a browser, that is the window
object. So, if you were trying to use the method on the window object, lo and behold, it would happen to work. I consider this somewhat of an accident, not good code.
IMO, the moral of the story is that any method that expects to be associated with an object should be called with an explicit object reference. Then, that removes all confusion, removes all difference between strict mode and non-strict mode and removes all difference between a browser and Node.js.
So why does this happen:
hasOwnProperty("x")
TypeError: Cannot convert undefined or null to object
If you're trying to call hasOwnProperty()
to test a property of the global object in node.js, then call the method with the context of the global
object as in:
global.hasOwnProperty("a")
That will work everywhere and is considered good and proper Javascript code. Calling it without the proper object context causes the this
value to be set to a default value. In node.js, that default value will not necessarily be the global object. But, in all cases, you should NEVER rely on what that default value will be. Program correctly by always specifying the desired object reference and your code will work fine everywhere.
FYI, there are more ways to control what this
is passed a function than just obj.method()
. You can read about the other ways here in this other answer. They include things such as .call()
, .apply()
, arrow functions (in ES6), etc...