With some values, calling hasOwnProperty
throws an error.
Let's check the following code:
null.hasOwnProperty('bar') // Error
undefined.hasOwnProperty('bar') // Error
(0).hasOwnProperty('bar') // Returns false
Are there any other variables rather than null
and undefined
that throws an error when calling with .hasOwnProperty
?
The same question for setting an object's property:
null.bar // Error
undefined.bar // Error
(0).bar === undefined // Returns true
=========
Another case where it throws an error in my Node.js environment:
In a browser
'use strict';
(0).bar = 0; // Nothing happens
In Node.js v.10.3.0:
(0).bar = 0; // Nothing
'use' strict';
(0).bar === undefined; // Returns true
true.bar === undefined; // Returns true
''.bar = '';// STILL NOTHING HAPPENS
(0).bar = 0; //TypeError: Cannot create property 'bar' on number '0'
(true).bar = true; // TypeError: Cannot create property 'bar' on boolean 'true'
========
Eventually, I found Check if a value is an object in JavaScript:
if (obj instanceof Object) obj.hasOwnProperty(...) // Or set a property on it
This solution totally fulfills my needs.
TLDR;
Object.prototype.hasOwnProperty
can be called directly on
Object.prototype
,
The subset of objects which have Object.prototype
in their inheritance chain and don't redefine hasOwnProperty
in either the inheritance chain or on the object, and
BigInt, Boolean, Number, String and Symbol primitive values. Calling it on primitive values is generally superfluous however as
(primitiveValue).hasOwnProperty(propertyName)
always rerturns false
- primitive values do not have own properties.
Data Types
JavaScript currently supports eight different data types in the ECMAScript 2020 specification:
BigInt (introduced in ECMAScript 2020), Boolean, Null, Undefined, Number, String, Symbol (new in ECMAScript 2015)
and Object.
The first seven of these are primitive values rather than object values - including null
which is of data type Null. (Yes, typeof null
returns "object" instead of "null", but this is an artifact of early JavaScript engine design that can't be fixed because it would break the web.)
Number, Boolean and String
Values of type Number, Boolean and String are automatically converted into "wrapper" object instances of global constructors Number
, Boolean
and String
respectively when used with property value lookup syntax.
Hence
(1).hasOwnProperty("MAX_SAFE_INTEGER")
returns false because the property is inherited from Number.prototype
. Similarly hasOwnProperty
calls on Boolean values return false because Boolean wrapper objects don't have any innate own properties themselves. But
("hello folks").hasOwnProperty("length");
returnstrue
because "length" is an own property of the String wrapper object.
Undefined and Null
Primitive values of data type Undefined (undefined
) or Null (null
) are not converted to wrapper objects and generate syntax errors when attempting to call hasOwnProperty
on them as a method:
(undefined).hasOwnProperty("example") // TypeError
(null).hasOwnProperty("example") // TypeError
Symbol and BigInt
Symbol and BigInt data type values have separate treatment - they were both introduced following a decision that new data types in ECMAScript would not have object wrappers.
Effectively this means that the JavaScript engine internally implements the syntax of applying Symbol.prototype
and BigInt.prototype
methods to symbol
and bigint
data types respectively, but only allows read access to prototyped methods and properties - any attempt to set a property on a symbol
or bigint
data type generates an error.
Neither the Symbol
nor BigInt
global functions allow the use of new
before calls to them.
Symbol
acts a factory function and returns a new symbol value.
BigInt
is a type conversion function to convert strings and numbers to bigint
data type.
Unlike older object wrappers for boolean
, number
and string
data types, attempting to set properties on a symbol
or bigint
data type never quietly succeeds.
Object
Objects ( of data type Object) generally inherit hasOwnProperty
from Object.prototype
. This inheritance can fail if either hasOwnProperty
is redefined somewhere later in the inheritance chain (not a good idea), or if the object was created with null
in its inheritance chain before reaching Object.prototype
.
The easiest way to create an object with null
at the start of its inheritance chain is by calling
Object.create( null);
Extending such an object will also create objects which don't inherit from Object.prototype
and so can't use hasOwnProperty
.
Note that applying instanceof Object
to an object whose prototype chain does not include Object.prototype
returns false
. Do not use instanceof
to determine Object data type.
In early versions of JavaScript, setting properties on wrapper objects automatically created from primitive values was syntactically correct and did not generate errors. However, the wrapper object was discarded as soon as the wrapper object expression was evaluated. Trying to look up a custom property in later code fails because a new, different wrapper object, lacking the custom property, is used for the lookup.
Strict mode generates an error if an attempt is made to assign a property value to any primitive value.
const checkOwnProperty = (obj, propertyName) =>
(obj && (typeof obj == "object" || typeof obj == "function") &&
Object.prototype.hasOwnProperty.call( obj, propertyName))
? true : false;
// Test:
var o = {name: "foo"};
console.log ( "name " + checkOwnProperty( o, "name"))
console.log ( "foo " + checkOwnProperty( o, "foo"))
console.log ( "0 " + checkOwnProperty( 0, "foo"))
CheckOwnProperty
returns a boolean reflecting if the first argument is of Object data type and has an own property with the same name as the second argument. It returns false for all primitive values.