简体   繁体   中英

How can I detect whether it is safe to use `in` operator in Javascript?

This statement

 if ('foo' in bar)

throws a TypeError if bar is a string. I presume it's possible to have the same error for other types of object.

How can I tell if bar is an object which supports the in operator?

This code isn't sufficient: if foo is a string, it passes through to the in statement and throws.

if (foo instanceof Object && ! (foo instanceof String))
{
    if ('foo' in foo) {}
}

The in operator throws a TypeError is the right operand is not an object.

You can check if a value is an object using

Object(value) === value;

Additionally, in operator calls internal [[HasProperty]] method. For ordinary objects it should never throw , but it might be the case in some exotic objects. For example,

var proxy = new Proxy({}, {has: () => {throw "Can't use `in`"}});
"property" in proxy; // Error: Can't use `in`

To handle these cases, I think you can only use a try statement, as ringø suggested .

var o = {};

console.log(o.constructor === Object && o !== null); //true

To catch any error

try { 
   if ('foo' in bar) { 
   }
}
catch(e) {
   // 'foo' is not in bar
}

or if you want just to catch errors for 'foo' in bar

var inbar = false;
try { if ('foo' in bar) inbar = true; } 
catch(e) {}

if (inbar) {
   ...
}

How can I detect whether it is safe to use in operator in Javascript?

From the ES5 spec

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).

Emphasis mine.

In ES5 Type() can be

  • Undefined
  • Null
  • Boolean
  • String
  • Number
  • Object

So to prevent TypeError s from happening, you have to make sure that it's not

  • undefined
  • null
  • true or false
  • any string value
  • any number value

EcmaScript 2015 introduces the Symbol type as well.

An example function might look like:

function canCallIn(arg) {
    if (arg === null ||
        arg === undefined)
        return false;
    switch (typeof arg) {
        case 'boolean':
        case 'string':
        case 'symbol':
        case 'number':
            return false;
    }
    return true;
}

Although you may be able to make various optimizations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM