3

Here we can see which types of objects in JavaScript/ECMAScript evaluate to false.

My question is: if a variable evaluates to true, is it guaranteed to have a hasOwnProperty method?

In other words, is the following test safe?

if (bar && bar.hasOwnProperty("foo")) { ... }

My goal is to prevent exceptions like Cannot read property 'hasOwnProperty' of null.

My application scenario: in an AngularJS $http service error handler I want to be prepared for all situations. This is a little difficult for me, because I am not tremendously experienced with JavaScript and the different situations in which this error handler might be called can not easily be tested for. The error handler function has the following signature:

function(data, status, headers, config) {}

In the function body I evaluate data like so:

if (data && data.hasOwnProperty("error")) {
    alert(data.error);
}

Does this look safe to you under all circumstances? Safe in the sense that this test does not throw an exception, no matter how AngularJS actually calls the error handler.

Community
  • 1
  • 1
Dr. Jan-Philip Gehrcke
  • 33,287
  • 14
  • 85
  • 130
  • `Cannot read property 'hasOwnProperty' of null` since `null` is falsey, this shouldn't be a problem. @DenysSéguret: If you are dealing with a variable, this should be okay. For example `var a = 1;` then `a.hasOwnProperty` is a function. – Matt Burland May 26 '15 at 19:04
  • 1
    @DenysSéguret: Still `var n=1; (n && n.hasOwnProperty("bar"))` does not raise an exception. – Dr. Jan-Philip Gehrcke May 26 '15 at 19:04
  • You have to check if the variable is an `object` first: `if (typeof bar == 'object' && ... ` – hindmost May 26 '15 at 19:05
  • 2
    If you want to be really sure, you could probably do something like: `if (data && data.hasOwnProperty && data.hasOwnProprety("error"))` – Matt Burland May 26 '15 at 19:06
  • @hindmost: wrong, non-objects inherit the method also: `alert(1 .hasOwnProperty)` – dandavis May 26 '15 at 19:32
  • @dandavis More precisely, you primitive value is boxed in an object (here an instance of Number) when you call a method on it. The primitive value doesn't have or inherit the method. – Denys Séguret May 27 '15 at 06:49
  • @DenysSéguret: another good reason to use `hasOwnProperty.call(5, "hasOwnProperty")` instead of owns, apparent or actual. – dandavis May 27 '15 at 07:13

1 Answers1

4

No.

Here's one:

var bar = Object.create(null);

Here's another one with hasOwnProperty, but not much better:

var bar = {hasOwnProperty:function(){ throw "bouh" }};

But you can call

Object.prototype.hasOwnProperty.call(bar, "foo")

Note that you may avoid the evaluation to truthy by doing

if (Object.prototype.hasOwnProperty.call(Object(bar), "foo")) {
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • Thanks. Is that maybe the only case? How would you change my test to even cover that scenario? – Dr. Jan-Philip Gehrcke May 26 '15 at 19:05
  • 1
    @Jan-PhilipGehrcke: Test that `.hasOwnProperty` is truthy first. So `if (data && data.hasOwnProperty && data.hasOwnProprety("error"))` – Matt Burland May 26 '15 at 19:08
  • There are now three proposals for a safe test, right? i) `if (Object.prototype.hasOwnProperty.call(Object(data), "error"))`. ii) `if (data && data.hasOwnProperty && data.hasOwnProperty("error"))` and iii) `if (typeof data == 'object' && data.hasOwnProperty("error"))`. Which one do you prefer? – Dr. Jan-Philip Gehrcke May 26 '15 at 19:10
  • @Jan-PhilipGehrcke mine ;) – Denys Séguret May 26 '15 at 19:11
  • 1
    @DenysSéguret: semantically, I like Matt's approach most. Does yours have technical advantages? Thanks for all the input already. – Dr. Jan-Philip Gehrcke May 26 '15 at 19:12
  • Null is the only value that has no default inherited properties correct? – Organiccat May 26 '15 at 19:15
  • 1
    @Jan-PhilipGehrcke Seriously: it doesn't really matter. The main point was to identify the risks and what needed to be done. Those ways to ensure it can't fail are basically equivalent. Mine is a little stronger as it also works if hasOwnProperty has been shadowed. – Denys Séguret May 26 '15 at 19:15
  • Thanks. Nice to point out the case of an overridden hasOwnProperty method. I guess I do not need to plan for this in my scenario, otherwise AngularJS is to be beaten. – Dr. Jan-Philip Gehrcke May 26 '15 at 19:20