20

I have the following javascript function that fails a jslint check

  function hasActiveX() {
    return ('ActiveXObject' in window);
  }

jslint error

Unexpected 'in'. Compare with undefined, or use the hasOwnProperty method instead.

should I just live with the jslint error, or is there a better way to determine ActiveXObject? I could not find a jslint flag to skip this check?

house9
  • 20,359
  • 8
  • 55
  • 61

2 Answers2

21

Ignore the error. The "in" operator is clearly defined in ECMA 262-5.1 / June 2011 sec-11.8.7

There appear to be only three outcomes for 'someProperty' in anObject which is one of: true, false, or a TypeError exception is thrown. When it evaluates to true, then there is definitely 'someProperty' in anObject. When it evaluates to false there is definitely not 'someProperty' in anObject. When a TypeError is thrown there is definitely not 'someProperty' in anObject because anObject is either null or it isn't an object at all. This all seems very clear to me. When I want to know if an object has a property and, I don't care if that property is the object's own property or being inherited and, I don't care what the value of the property is, then I simply look for 'someProperty' in anObject.

Warning

Caution: some would have you check for anObject.someProperty !== undefined but that isn't really checking whether or not the object has the property. What it's doing is checking whether the object has the property AND that the value of that property is NOT undefined. Some would have you check for anObject.hasOwnProperty('someProperty'); but that will only tell you if the object has that property AND has NOT inherited it somehow. Don't believe me? Try the following:

console.log(document.body.tagName);
// BODY

console.log(document.body.hasOwnProperty('tagName'));
// false, it's inherited

console.log('tagName' in document.body);
// true, it does have the property

document.body.wobbles = undefined;
// new property added to document.body

console.log('wobbles' in document.body);
// true, it does have the property

console.log(document.body.wobbles !== undefined);
// false, the value really IS undefined

I've written an article about the "in" operator that goes into more detail. If you want to read it it's at: http://matthewkastor.blogspot.com/2012/09/Unexpected--in---Compare-with-undefined--or-use-the-hasOwnProperty-method-instead.html The bottom line is that you should just ignore this error and wrap things up in a try catch block if the object might be null or not an object.

function hasProperty(prop, obj) {
    try {
        return prop in obj;
    } catch(e) {
        return e;
    }
}
Kastor
  • 617
  • 5
  • 14
  • This is a great discussion of reasons why you should use `in`. But do you have any idea why JSLint thinks you should not use it? If you don't know why jslint makes recommends against it, then you don't know if you're addressing its concerns. – algal Mar 18 '13 at 13:45
  • 4
    @user577888 Yes, I know why JSLint gives the notice and that the notice can not be suppressed. The above post explains the usage of `in` and why it can safely be ignored. To put it simply, the warning comes up for performance reasons. It makes no sense to search the entire prototype chain when you're expecting the property to be directly assigned to the object in question. Using `in` without the `hasOwnProperty` guard isn't really an error and there aren't any harmful side effects in doing so. – Kastor Mar 23 '13 at 04:57
17

I think JSLint is asking you to try:

function hasActiveX() {
    return window.hasOwnProperty('ActiveXObject');
}

Or the other suggestion of comparing against "undefined":

return (typeof(window.ActiveXObject) != "undefined");

Personally, I prefer the former.

After reading the comments, it seems like in is actually useful if JSLint would stop complaining about it, otherwise I would try option 2 above.

Cᴏʀʏ
  • 105,112
  • 20
  • 162
  • 194
  • 1
    hasOwnProperty is probably too strict, since the code using the ActiveX probably doesn't bother about the "own" part. (Not that it matters though, as window doesn't have a prototype anyway) – hugomg Jul 26 '11 at 03:35
  • 6
    Calling `window.hasOwnProperty` will fail on *IE <= 8*, since the global object doesn't inherit from `Object.prototype` (e.g. `Object.prototype.isPrototypeOf(window); // false`, you need to call it indirectly, e.g. `Object.prototype.hasOwnPrototype.call(window, 'ActiveXObject');`, but as @missingno says, there's no guarantee that the method is an own property, it could be declared up in the prototype chain of the global object (thing that is completely implementation dependent), usually for testing *host* properties, the `in` operator is useful... Come on jslint, don't hurt our code :P – Christian C. Salvadó Jul 26 '11 at 05:21
  • @above, thanks for the insight guys. If you had to pick a method that doesn't use `in`, would you go for method 2 or something entirely different? – Cᴏʀʏ Jul 26 '11 at 13:43
  • Thanks everybody, going to go with typeof !== undef - also here is some jsfiddle with the code for reference http://jsfiddle.net/5uxmU/6/ – house9 Jul 26 '11 at 23:33
  • 3
    typeof !== undef is useless, just check the property for undefined `return window.ActiveXObject !== undefined;` – Matt Esch Aug 26 '12 at 16:23
  • 1
    @MattEsch typeof !== undefined is not useless since outside ES5 strict mode, undefined can be easily reassigned, and the var x !== undefined check could fail, that's the reason behind typeof :) – ArtoAle Aug 14 '13 at 08:37
  • 1
    @ArtoAle I guess technically it's not useless, but practically it is. You have worse problems if someone has redefined undefined. It's not a strict mode only requirement that undefined is readonly and you can always use `void 0` if you want to ensure undefined. – Matt Esch Aug 14 '13 at 18:33
  • 1
    @MattEsch, of course...but (not considering that void 0 is usually considered bad practise as it could be confusing), it's another technique to achieve the same result, I don't see why labeling it as "useless" – ArtoAle Aug 16 '13 at 13:38