检查 JavaScript 对象中是否存在密钥?

How do I check if a particular key exists in a JavaScript object or array?

If a key doesn't exist, and I try to access it, will it return false? Or throw an error?

转载于:https://stackoverflow.com/questions/1098040/checking-if-a-key-exists-in-a-javascript-object

Checking for undefined-ness is not an accurate way of testing whether a key exists. What if the key exists but the value is actually undefined?

var obj = { key: undefined };
obj["key"] != undefined // false, but the key exists!

You should instead use the in operator:

"key" in obj // true, regardless of the actual value

If you want to check if a key doesn't exist, remember to use parenthesis:

!("key" in obj) // true if "key" doesn't exist in object
!"key" in obj   // ERROR!  Equivalent to "false in obj"

Or, if you want to particularly test for properties of the object instance (and not inherited properties), use hasOwnProperty:

obj.hasOwnProperty("key") // true

For performance comparison between the methods that are in, hasOwnProperty and key is undefined, see this benchmark

It will return undefined.

var aa = {hello: "world"};
alert( aa["hello"] );      // popup box with "world"
alert( aa["goodbye"] );    // popup box with "undefined"

undefined is a special constant value. So you can say, e.g.

// note the three equal signs so that null won't be equal to undefined
if( aa["goodbye"] === undefined ) {
    // do something
}

This is probably the best way to check for missing keys. However, as is pointed out in a comment below, it's theoretically possible that you'd want to have the actual value be undefined. I've never needed to do this and can't think of a reason offhand why I'd ever want to, but just for the sake of completeness, you can use the in operator

// this works even if you have {"goodbye": undefined}
if( "goodbye" in aa ) {
    // do something
}
"key" in obj

Is likely testing only object attribute values that are very different from array keys

Three ways to check if a property is present in a javascript object:

  1. !!obj.theProperty
    Will convert value to bool. returns TRUE for all but the 'false' value
  2. 'theProperty' in obj
    Will return true if the property exists, no matter its value (even empty)
  3. obj.hasOwnProperty('theProperty')
    Does not check the prototype chain. (since all objects have the 'toString' method, 1 and 2 will return true on it, while 3 can return false on it.)

Reference:

http://book.mixu.net/node/ch5.html

quick answer

How do I check if a particular key exists in a JavaScript object or array? If a key doesn't exist and I try to access it, will it return false? Or throw an error?

Accessing directly a missing property using (associative) array style or object style will return an undefined constant.

The slow and reliable in operator and hasOwnProperty method

As people have already mentioned here, you could have an object with a property associated with an "undefined" constant.

 var bizzareObj = {valid_key:  undefined};

In that case, you will have to use hasOwnProperty or in operator to know if the key is really there. But, but at what price?

so, I tell you...

in operator and hasOwnProperty are "methods" that use Property Descriptor mechanism in Javascript (similar to Java reflection in the Java language).

http://www.ecma-international.org/ecma-262/5.1/#sec-8.10

The Property Descriptor type is used to explain the manipulation and reification of named property attributes. Values of the Property Descriptor type are records composed of named fields where each field’s name is an attribute name and its value is a corresponding attribute value as specified in 8.6.1. In addition, any field may be present or absent.

On the other hand, calling an object method or key will use Javascript [[Get]] mechanism. That is far way faster!

benchmark

http://jsperf.com/checking-if-a-key-exists-in-a-javascript-array

Comparing key access in JS.

Using in operator
var result = "Impression" in array;

The result was

12,931,832 ±0.21% ops/sec      92% slower 
Using hasOwnProperty
var result = array.hasOwnProperty("Impression")

The result was

16,021,758 ±0.45% ops/sec     91% slower
Accessing elements directly (brackets style)
var result = array["Impression"] === undefined

The result was

168,270,439 ±0.13 ops/sec     0.02% slower 
Accessing elements directly (object style)
var result = array.Impression  === undefined;

The result was

168,303,172 ±0.20%     fastest

EDIT: What is the reason to assign to a property the undefined value?

That question puzzles me. In Javascript, there are at least two references for absent objects to avoid problems like this: null and undefined.

null is the primitive value that represents the intentional absence of any object value, or in short terms, the confirmed lack of value. On the other hand, undefined is unknown value (not defined). If there is a property that will be used later with a proper value consider use null reference instead of undefined because in the initial moment the property is confirmed to lack a value.

Compare:

var a = {1: null}; 
console.log(a[1] === undefined); // output: false. I know the value at position 1 of a[] is absent and this was by design, i.e.:  the value is defined. 
console.log(a[0] === undefined); // output: true. I cannot say anything about a[0] value. In this case, the key 0 was not in a[].

Advise

Avoid objects with undefined values. Check directly whenever possible and use null to initialize property values. Otherwise, use the slow in operator or hasOwnProperty() method.

EDIT: 12/04/2018 - NOT RELEVANT ANYMORE

As people have commented, modern versions of the Javascript engines (with firefox exception) has changed the approach for access properties. Current implementation is slower than the previous one for this particular case but difference between access key and object are neglectable.

If you are using underscore.js library then object/array operations become simple.

In your case _.has method can be used. Example:

yourArray = {age: "10"}

_.has(yourArray, "age")

returns true

But,

_.has(yourArray, "invalidKey")

returns false

The accepted answer refers to Object. Beware using the in operator on Array to find data instead of keys:

("true" in ["true", "false"])
// -> false (Because the keys of the above Array are actually 0 and 1)

To test existing elements in an Array: Best way to find if an item is in a JavaScript array?

Here's a helper function I find quite useful

This keyExists(key, search) can be used to easily lookup a key within objects or arrays!

Just pass it the key you want to find, and search obj (the object or array) you want to find it in.

function keyExists(key, search) {
    if (!search || (search.constructor !== Array && search.constructor !== Object)) {
        return false;
    }
    for (var i = 0; i < search.length; i++) {
        if (search[i] === key) {
            return true;
        }
    }
    return key in search;
}

How to use it:

Searching for keys in Arrays

keyExists('apple', ['apple', 'banana', 'orange']); // true
keyExists('fruit', ['apple', 'banana', 'orange']); // false

Searching for keys in Objects

keyExists('age', {'name': 'Bill', 'age': 29 }); // true
keyExists('title', {'name': 'Jason', 'age': 29 }); // false

It's been pretty reliable and works well cross-browser.

Answer:

if ("key" in myObj)
{
    console.log("key exists!");
}
else
{
    console.log("key doesn't exist!");
}

Explanation:

The in operator will check if the key exists in the object. If you checked if the value was undefined: if (myObj["key"] === 'undefined'), you could run into problems because a key could possibly exist in your object with the undefined value.

For that reason, it is much better practice to first use the in operator and then compare the value that is inside the key once you already know it exists.

We can use - hasOwnProperty.call(obj, key);

The underscore.js way -

if(_.has(this.options, 'login')){
  //key 'login' exists in this.options 
}

_.has = function(obj, key) {
  return hasOwnProperty.call(obj, key);
};

vanila js

yourObjName.hasOwnProperty(key) : true ? false;

If you want to check if the object has at least one property in es2015

Object.keys(yourObjName).length : true ? false

ES6 solution

using Array#some and Object.keys. It will return true if given key exists in the object or false if it doesn't.

var obj = {foo: 'one', bar: 'two'};
    
function isKeyInObject(obj, key) {
    var res = Object.keys(obj).some(v => v == key);
    console.log(res);
}

isKeyInObject(obj, 'foo');
isKeyInObject(obj, 'something');

One-line example.

console.log(Object.keys({foo: 'one', bar: 'two'}).some(v => v == 'foo'));

</div>

For those which have lodash included in their project:
There is a lodash _.get method which tries to get "deep" keys:

Gets the value at path of object. If the resolved value is undefined, the defaultValue is returned in its place.

var object = { 'a': [{ 'b': { 'c': 3 } }] };

console.log(
  _.get(object, 'a[0].b.c'),           // => 3
  _.get(object, ['a', '0', 'b', 'c']), // => 3
  _.get(object, 'a.b.c'),              // => undefined 
  _.get(object, 'a.b.c', 'default')    // => 'default'
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>


This will effectively check if that key, however deep, is defined and will not throw an error which might harm the flow of your program if that key is not defined.

</div>

This is an old question but I guess never to late to give an answer.

Imagine that you have an object "products" and two items. If you want to see if id already exists in this object you can use find()

products = [
    {
        "id": 1,
        "name": "Name 1"
    },
    {
        "id": 2,
        "name": "Name 2"
    },
  ]

  item1 = 
    {
        "id": 3,
        "name": "Name 3",
    }



  item2 = 
    {
        "id": 1,
        "name": "Name 1",
    }



  if(products.find(x => x.id === item1.id)){
    console.log('id is in products');
  }else {
    console.log('id is not in products');
  }
  if(products.find(x => x.id === item2.id)){
    console.log('id is in products');
  }else {
    console.log('id is not in products');
  }

log:

id is not in products
id is in products

While this necessarily check if a key exists, it does check for the truthiness of a value. Which undefined and null fall under.

Boolean(obj.foo)

This solution works best for me because I use typescript, and using strings like so 'foo' in obj or obj.hasOwnProperty('foo') to check whether a key exists or not does not provide me with intellisense.

These example can demonstrate the differences between defferent ways. Hope it will help you to pick the right one for your needs:

// Lets create object `a` using create function `A`
function A(){};
A.prototype.onProtDef=2;
A.prototype.onProtUndef=undefined;
var a=new A();
a.ownProp = 3;
a.ownPropUndef = undefined;

// Let's try different methods:

a.onProtDef; // 2
a.onProtUndef; // undefined
a.ownProp; // 3
a.ownPropUndef; // undefined
a.whatEver; // undefined
a.valueOf; // ƒ valueOf() { [native code] }

a.hasOwnProperty('onProtDef'); // false
a.hasOwnProperty('onProtUndef'); // false
a.hasOwnProperty('ownProp'); // true
a.hasOwnProperty('ownPropUndef'); // true
a.hasOwnProperty('whatEver'); // false
a.hasOwnProperty('valueOf'); // false

'onProtDef' in a; // true
'onProtUndef' in a; // true
'ownProp' in a; // true
'ownPropUndef' in a; // true
'whatEver' in a; // false
'valueOf' in a; // true (on the prototype chain - Object.valueOf)

Object.keys(a); // ["ownProp", "ownPropUndef"]

New awesome solution with JavaScript Destructuring:

let obj = {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3",
};

let {key1, key2, key3, key4} = obj;

// key1 = "value1"
// key2 = "value2"
// key3 = "value3"
// key4 = undefined

// Can easily use `if` here on key4
if(!key4) { console.log("key not present"); } // Key not present

Do check other use of JavaScript Destructuring

If you want to check for any key at any depth on an object and account for falsey values consider this line for a utility function:

var keyExistsOn = (o, k) => k.split(".").reduce((a, c) => a.hasOwnProperty(c) ? a[c] || 1 : false, Object.assign({}, o)) === false ? false : true;

Results

var obj = {
    test: "",
    locals: {
        test: "",
        test2: false,
        test3: NaN,
        test4: 0,
        test5: undefined,
        auth: {
            user: "hw"
        }
    }
}

keyExistsOn(obj, "")
> false
keyExistsOn(obj, "locals.test")
> true
keyExistsOn(obj, "locals.test2")
> true
keyExistsOn(obj, "locals.test3")
> true
keyExistsOn(obj, "locals.test4")
> true
keyExistsOn(obj, "locals.test5")
> true
keyExistsOn(obj, "sdsdf")
false
keyExistsOn(obj, "sdsdf.rtsd")
false
keyExistsOn(obj, "sdsdf.234d")
false
keyExistsOn(obj, "2134.sdsdf.234d")
false
keyExistsOn(obj, "locals")
true
keyExistsOn(obj, "locals.")
false
keyExistsOn(obj, "locals.auth")
true
keyExistsOn(obj, "locals.autht")
false
keyExistsOn(obj, "locals.auth.")
false
keyExistsOn(obj, "locals.auth.user")
true
keyExistsOn(obj, "locals.auth.userr")
false
keyExistsOn(obj, "locals.auth.user.")
false
keyExistsOn(obj, "locals.auth.user")
true

Also see this NPM package: https://www.npmjs.com/package/has-deep-value