1

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.

Peter Mortensen
  • 30,030
  • 21
  • 100
  • 124
transang
  • 3,349
  • 2
  • 32
  • 43
  • 1
    `null` and `undefined` are not **variables**, they are **types**. Conceptually, it would be impossible for something that doesn't exist (`null`) or something that isn't defined (`undefined`) to have any properties. – Claies Aug 24 '18 at 04:36
  • 1
    Any object you derive from `null` has not `hasOwnProperty` method, you can create the method, though. – Teemu Aug 24 '18 at 04:36
  • hasOwnProperty requires an Object (or something that inherits from Object). To see what are *not* objects, see here: https://www.quora.com/Is-everything-an-object-in-Javascript – Chris Cousins Aug 24 '18 at 04:36
  • Not sure what `(0).bar = 0` has to do with your original question…? See https://stackoverflow.com/questions/49682661/why-does-foo-bar-42-throw-typeerror-in-strict-mode-in-es6, anyway. – Ry- Aug 24 '18 at 04:44
  • @Ry- I am recursively set property on object. I just want to cover all cases can ever happen.For example, `recursivelySet(obj, path, value)`. If someone passes `recursivelySet(1, 'foo.bar', 0)`,I want the function to detect this case and do nothing. Or more obivious case, `recursivelySet({foo: 1}, 'foo.bar', 0)` – transang Aug 24 '18 at 04:56
  • Are you sure you don’t want your function to throw on a task that doesn’t make sense? That’s what exceptions are for. – Ry- Aug 24 '18 at 05:06
  • I want to recursively set something on `req.body`, and it can be anything because it is passed from client. I think it would be better if the server returns `parameter error` in the next middleware, rather than throws `Server Internal Error` – transang Aug 24 '18 at 05:11

5 Answers5

3

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.

Wrapper objects and strict mode.

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.

Possible Check Function

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.

traktor
  • 15,221
  • 4
  • 27
  • 50
  • Please recheck the ''.bar = ''; case shown in the OP >> With node v14.0.0. This does not throw error. – transang May 12 '20 at 14:29
  • there is `BigInt` type not mentioned in the answer – transang May 12 '20 at 14:35
  • @transang I didn't notice in 2018: "use strict"; must be the first statement/expression in JavaScript source to be recognized. Moving it to the first line (and correcting the string syntax) generated an error trying to add a property to a string in both Node 10.15.3 and Node 14.2.0 when tested. – traktor May 13 '20 at 03:16
  • you are correct. I have tested and successfully reproduced. It eventually throws error if 'use strict' is placed at the begin – transang May 13 '20 at 05:05
2

Using hasOwnProperty as a property name:

var foo = {
  hasOwnProperty: function() {
    return false;
  },
  bar: 'Here be dragons'
};

foo.hasOwnProperty('bar'); // always returns false

// Use another Object's hasOwnProperty
// and call it with 'this' set to foo
({}).hasOwnProperty.call(foo, 'bar'); // true

// It's also possible to use the hasOwnProperty property
// from the Object prototype for this purpose
Object.prototype.hasOwnProperty.call(foo, 'bar'); // true

Also take care to the latest draft:

When the hasOwnProperty method is called with argument V, the following steps are taken:

  1. Let P be ? ToPropertyKey(V).
  2. Let O be ? ToObject(this value).
  3. Return ? HasOwnProperty(O, P).

NOTE

The ordering of steps 1 and 2 is chosen to ensure that any exception that would have been thrown by step 1 in previous editions of this specification will continue to be thrown even if the this value is undefined or null.

Community
  • 1
  • 1
Bhojendra Rauniyar
  • 78,842
  • 31
  • 152
  • 211
0

I think you can call it on any variable which is not undefined nor null.

console.log([1].hasOwnProperty(0)); // true
console.log([1,2].hasOwnProperty(1)); // true
console.log([1,2].hasOwnProperty(2)); // false

console.log({ a: 's'}.hasOwnProperty('a')); // true
console.log({ b: 's'}.hasOwnProperty('a')); // false
console.log({}.hasOwnProperty('a')); // false

console.log((555).hasOwnProperty('a')); // false
console.log((false).hasOwnProperty('a')); // false
console.log((true).hasOwnProperty('a')); // false
console.log(("skjhkdasj").hasOwnProperty('a')); // false
console.log((1.045).hasOwnProperty('a')); // false
// console.log((null).hasOwnProperty('a')); // error
// console.log((undefined).hasOwnProperty('a')); // error
Shanaka Rusith
  • 353
  • 3
  • 17
0

YOU ARE CORRECT. IT EXIST ON EVERYTHING BUT UNDEFINED AND NULL

class Vehicle {
  constructor(name, type) {
    this.name = name;
    this.type = type;
  }
}

class Car extends Vehicle {
  constructor(color) {
    super()
    this.color = color
  }
}

console.log(new Car().hasOwnProperty('color'))
console.log(new Car().hasOwnProperty('name'))

console.log(new Vehicle().hasOwnProperty('color'))
console.log(new Vehicle().hasOwnProperty('name'))

function foo() {}
foo.hasOwnProperty('bar')
true.hasOwnProperty('bar')

const symbol = Symbol();
Symbol.hasOwnProperty('bar')
symbol.hasOwnProperty('bar')

Boolean.hasOwnProperty('bar')
String.hasOwnProperty('bar')
Array.hasOwnProperty('bar')
Number.hasOwnProperty('bar')
Object.hasOwnProperty('bar')
Car.hasOwnProperty('bar');
[].hasOwnProperty('bar');
"".hasOwnProperty('bar');
(1).hasOwnProperty('bar');

//null.hasOwnProperty('bar')
//undefined.hasOwnProperty('bar')
Steven Spungin
  • 22,681
  • 5
  • 73
  • 65
0

If you just want to check for the existence of properties, and not necessarily what their value might be, then you have two safe options: hasOwnProperty() and the in operator. The hasOwnProperty() property method should be used if you want to detect own properties only. If you want to test property existence and don’t care if it’s an own property or an object property, then the in operator is the one to use.

reference for more information click here

  • **safe options**: it throws error (my question), it does **not safe**, I think – transang Aug 24 '18 at 04:59
  • about the function error A handler function with request.query.hasOwnProperty('whatever') will result in a "request.query.hasOwnProperty is not a function" error. Changing to Object.prototype.hasOwnProperty.call(request.query, 'whatever') work This is expected. nodejs modified the query object returned by the querystring module such that it uses a null prototype, and therefore does not inherit the base properties and methods of ordinary Object instances. – Ahmed amin shahin Aug 24 '18 at 05:09
  • did you check the code? `Object.prototype.hasOwnProperty.call(null, 'whatever')` throw `Cannot convert undefined or null to object` – transang Aug 24 '18 at 05:13
  • please give me more details ... you may also refer to this link [link]https://stackoverflow.com/questions/29721205/how-to-resolve-typeerror-cannot-convert-undefined-or-null-to-object/29721434 – Ahmed amin shahin Aug 24 '18 at 05:35