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

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

Problem: JsLint Confusion

I don't understand why JsLint is giving me this error message: Unexpected 'in'. Compare with undefined, or use the hasOwnProperty method instead.(see infix_in at http://www.jslint.com/msgs.html). The "in" operator seems to be very clearly defined. 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
        

Let's test this "in" operator for undefined behavior.

function hasProperty(prop, obj) {
    try {
        return prop in obj;
    } catch(e) {
        return e;
    }
}

var unDef, nll, notHasProp, hasProp;
// unDef is left undefined
nll = null;
notHasProp = {};
// hasProp.someProperty exists but it's value is null
hasProp = {'someProperty': nll};

console.log('someProperty in undefined will throw a TypeError');
console.log(hasProperty('someProperty', unDef)); // throws error
console.log('someProperty in null will throw a TypeError');
console.log(hasProperty('someProperty', nll)); // throws error
console.log('someProperty in notHasProp will be false');
console.log(hasProperty('someProperty', notHasProp)); // false
console.log('someProperty in hasProp will be true: ');
console.log(hasProperty('someProperty', hasProp)); // true

Summary

The "in" operator is behaving as defined and is serving a useful purpose.

Quotes from ECMA-262 5.1 / June 2011

The following are quotes from the standard which define the "in" operator. I need to know what isn't covered here. The full standard in HTML format is available at http://ecma-international.org/ecma-262/5.1/ or may be browsed through in the frame following the quotes.

11.8.7 The in operator

The production RelationalExpression : RelationalExpression in ShiftExpression is evaluated as follows:

  1. Let lref be the result of evaluating RelationalExpression.
  2. Let lval be GetValue(lref).
  3. Let rref be the result of evaluating ShiftExpression.
  4. Let rval be GetValue(rref).
  5. If Type(rval) is not Object, throw a TypeError exception.
  6. Return the result of calling the [[HasProperty]] internal method of rval with argument ToString(lval).

8.12.6 [[HasProperty]] (P)

When the [[HasProperty]] internal method of O is called with property name P, the following steps are taken:

  1. Let desc be the result of calling the [[GetProperty]] internal method of O with property name P.
  2. If desc is undefined, then return false.
  3. Else return true.

Standard ECMA-262 5.1 Edition / June 2011