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,738
  • 21
  • 105
  • 131
Sang
  • 4,049
  • 3
  • 37
  • 47
  • 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)` – Sang 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` – Sang Aug 24 '18 at 05:11

5 Answers5

5

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
  • 17,588
  • 4
  • 32
  • 53
  • Please recheck the ''.bar = ''; case shown in the OP >> With node v14.0.0. This does not throw error. – Sang May 12 '20 at 14:29
  • there is `BigInt` type not mentioned in the answer – Sang 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 – Sang 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
  • 83,432
  • 35
  • 168
  • 231
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
  • 421
  • 1
  • 4
  • 19
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
  • 27,002
  • 5
  • 88
  • 78
  • I think your array and number problems come from incorrect syntax (lack of semicolons, lack of parentheses). Try `;[].hasOwnProperty('bar')` and `1..hasOwnProperty('bar')`. – Ry- Aug 24 '18 at 04:46
  • And maybe “you can’t call it on a class” came from mistakenly using `Foo` instead of `Car`? – Ry- Aug 24 '18 at 04:48
  • @Ry I fixed the class to be OK. – Steven Spungin Aug 24 '18 at 04:51
  • @Ry- whooo! never had the array on a second line do that. wow! learn something new every day. Thanks! – Steven Spungin Aug 24 '18 at 04:54
  • You can call it on a number. `1.hasOwnProperty` is parsed as the number `1.` (a trailing decimal point), then just a random `hasOwnProperty`. Use `1..hasOwnProperty` or `;(1).hasOwnProperty`. – Ry- Aug 24 '18 at 04:54
  • I already fixed that one. And add symbol/Symbol too, and string. – Steven Spungin Aug 24 '18 at 04:59
  • Your answer **You can't call it on undefined, null, or a number** is not correct. The code in my question says **I call it on a number**. Morever, You list `undefined, null, number` and another list of many. Is there any other type exist? – Sang Aug 24 '18 at 05:04
  • OK. I surrender. I can't find anything it doesn't exist on. – Steven Spungin Aug 24 '18 at 05:09
  • It looks like `Obeject.create(null)` does not have `hasOwnProperty` – Sang Aug 24 '18 at 07:41
  • Doesn’t that return null? – Steven Spungin Aug 24 '18 at 10:37
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 – Sang 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` – Sang 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