如何检查对象在 JavaScript 中是否具有特定属性?

如何检查对象在 JavaScript 中是否具有特定属性?

考虑:

x = {'key': 1};
if ( x.hasOwnProperty('key') ) {
    //Do this
}

那是最好的方法吗?

答案

我对所给出的答案感到困惑 - 他们中的大多数都是完全错误的。当然,您可以拥有具有未定义,空值或假值的对象属性。因此,简单地将属性检查减少为x.key typeof this[property]或更糟糕的是, x.key会给您完全误导的结果。

这取决于您要查找的内容。如果您想知道一个对象是否物理上包含一个属性(它不是来自原型链上的某个位置),那么object.hasOwnPropertyobject.hasOwnProperty的方法。所有现代的浏览器都支持它。 (在 Safari 的较早版本(2.0.1 和更早的版本中不存在),但那些浏览器版本已很少使用。)

如果您要查找的是对象上具有可迭代的属性(当您遍历该对象的属性时,它将出现),则可以执行以下操作: prop in object将为您提供所需的效果。

由于可能需要使用hasOwnProperty ,并且考虑到可能需要回退方法,因此,我向您提供以下解决方案:

var obj = {
    a: undefined,
    b: null,
    c: false
};

// a, b, c all found
for ( var prop in obj ) {
    document.writeln( "Object1: " + prop );
}

function Class(){
    this.a = undefined;
    this.b = null;
    this.c = false;
}

Class.prototype = {
    a: undefined,
    b: true,
    c: true,
    d: true,
    e: true
};

var obj2 = new Class();

// a, b, c, d, e found
for ( var prop in obj2 ) {
    document.writeln( "Object2: " + prop );
}

function hasOwnProperty(obj, prop) {
    var proto = obj.__proto__ || obj.constructor.prototype;
    return (prop in obj) &&
        (!(prop in proto) || proto[prop] !== obj[prop]);
}

if ( Object.prototype.hasOwnProperty ) {
    var hasOwnProperty = function(obj, prop) {
        return obj.hasOwnProperty(prop);
    }
}

// a, b, c found in modern browsers
// b, c found in Safari 2.0.1 and older
for ( var prop in obj2 ) {
    if ( hasOwnProperty(obj2, prop) ) {
        document.writeln( "Object2 w/ hasOwn: " + prop );
    }
}

上面是hasOwnProperty跨浏览器的工作解决方案,但有一个警告:无法区分原型和实例上具有相同属性的情况 - 只是假设它来自原型。您可以根据自己的情况将其更改为宽容或严格,但是至少这应该会有所帮助。

随着Underscore.js或( 甚至更好lodash

_.has(x, 'key');

该方法调用Object.prototype.hasOwnProperty ,但(a)的类型较短,并且(b)使用 “对hasOwnProperty的安全引用”(即,即使hasOwnProperty被覆盖也可以使用)。

特别是 lodash 将_.has定义为:

function has(object, key) {
      return object ? hasOwnProperty.call(object, key) : false;
   }
   // hasOwnProperty = Object.prototype.hasOwnProperty

关于什么?

var x = {'key': 1};

if ('key' in x) {
    console.log('has');
}

注意 :由于采用严格模式和hasOwnProperty ,因此以下内容现已过时。正确的解决方案是使用严格模式,并使用obj.hasOwnProperty检查属性是否存在。这个答案早于这两件事,至少已经广泛实施了(是的,它已经很老了)。将以下内容作为历史记录。


请记住,如果您未使用严格模式,那么不幸的是, undefined在 JavaScript 中不是保留字。因此,某人(显然是其他人)可能有重新定义它的宏大想法,从而破坏了您的代码。

因此,一种更可靠的方法如下:

if (typeof(x.attribute) !== 'undefined')

另一方面,这种方法比较冗长,而且速度较慢。 :-/

常见的替代方法是确保undefined 实际上是未定义的,例如,通过将代码放入接受一个未传递值的附加参数(称为undefined的函数中。为确保未传递值,您可以立即自行调用它,例如:

(function (undefined) {
    … your code …
    if (x.attribute !== undefined)
        … mode code …
})();
if (x.key !== undefined)

Armin Ronacher似乎已经击败了我 ,但是:

Object.prototype.hasOwnProperty = function(property) {
    return this[property] !== undefined;
};

x = {'key': 1};

if (x.hasOwnProperty('key')) {
    alert('have key!');
}

if (!x.hasOwnProperty('bar')) {
    alert('no bar!');
}

Konrad RudolphArmin Ronacher 指出 ,一种更安全但较慢的解决方案是:

Object.prototype.hasOwnProperty = function(property) {
    return typeof this[property] !== 'undefined';
};

您可以使用in运算符来检查对象上是否存在该属性:

x = {'key': 1};
alert("key" in x);

您还可以使用for - in循环遍历对象的所有属性,然后检查特定属性:

for (prop in x) {
    if (prop == "key") {
        //Do something
    }
}

您必须考虑此对象属性是否可枚举,因为不可枚举的属性不会出现在for-in循环中。另外,如果可枚举属性遮盖了原型的不可枚举属性,则它将不会显示在Internet Explorer 8及更早版本中。

如果您想要所有实例属性的列表(无论是否可枚举),则可以使用

Object.getOwnPropertyNames(x);

这将返回对象上存在的所有属性的名称数组。

最后,您可以使用 typeof 运算符直接检查对象属性的数据类型:

if (typeof x.key == "undefined") {
    alert("undefined");
}

如果对象上不存在该属性,它将返回未定义的字符串。否则,它将返回适当的属性类型。但是,请注意,这并非始终是检查对象是否具有属性的有效方法,因为您可以将属性设置为 undefined,在这种情况下,使用typeof x.key仍将返回 true(即使键仍在对象中)。

更新:您可以通过与未定义的 javascript 属性进行比较来检查属性是否存在

if (x.key === undefined) {
    alert("undefined");
}

除非在 x 对象上将键专门设置为undefined ,否则这应该起作用

让我们在这里消除一些困惑。首先,通过假设hasOwnProperty已经存在进行简化。当前使用的绝大多数浏览器都是如此。

如果传递给它的属性名称已添加到对象,则hasOwnProperty返回 true。它完全独立于分配给它的实际值,而实际值可能是undefined

因此:

var o = {}
o.x = undefined

var a = o.hasOwnProperty('x')  // a is true
var b = o.x === undefined // b is also true

然而:

var o = {}

var a = o.hasOwnProperty('x')  // a is now false
var b = o.x === undefined // b is still true

问题是当原型链中的对象具有值为 undefined 的属性时会发生什么? hasOwnProperty会为 false,因此!== undefined也会为 false。但是, for..in仍将其列在枚举中。

最重要的是,没有跨浏览器的方式(因为 Internet Explorer 不公开__prototype__ )来确定特定标识符尚未附加到对象或其原型链中的任何内容。

如果要搜索属性,则为 “NO”。你要:

if ('prop' in obj) { }

通常,您不必关心该属性是否来自原型或对象。

但是,由于在示例代码中使用了 “键”,因此看起来您将对象视为哈希,在这种情况下,您的答案才有意义。所有哈希键都将是对象中的属性,并且可以避免原型带来的额外属性。

John Resig 的回答非常全面,但我认为还不清楚。特别是当在 obj 中使用 “prop” 时。

是的,它是:) 我想您也可以执行Object.prototype.hasOwnProperty.call(x, 'key') ,如果x具有一个名为hasOwnProperty的属性,它也应该可以工作:)

但这会测试自己的属性。如果要检查它是否具有也可以继承的属性,可以使用typeof x.foo != 'undefined'

要测试简单对象,请使用: if (obj[x] !== undefined)

如果您不知道它是什么对象类型,请使用: if (obj.hasOwnProperty(x))

所有其他选项都较慢。

细节

在 Nodejs 下,其他人建议的 5 个选项下的 100,000,000 个周期的性能评估:

function hasKey1(k,o) { return (x in obj); }
function hasKey2(k,o) { return (obj[x]); }
function hasKey3(k,o) { return (obj[x] !== undefined); }
function hasKey4(k,o) { return (typeof(obj[x]) !== 'undefined'); }
function hasKey5(k,o) { return (obj.hasOwnProperty(x)); }

评估告诉我们,除非我们特别想要检查对象的原型链以及对象本身,否则我们不应使用以下通用形式: if (X in Obj)... 慢 2 到 6 倍,具体取决于用例

hasKey1 execution time: 4s 510.427785ms
hasKey2 execution time: 0s 904.374806ms
hasKey3 execution time: 0s 760.336193ms
hasKey4 execution time: 0s 935.19901ms
hasKey5 execution time: 2s 148.189608ms

底线是,如果您的 Obj 不一定是简单的对象,并且您希望避免检查对象的原型链,并确保 x 直接由 Obj 拥有,请使用'if(obj.hasOwnProperty(x))...'。

否则,当使用简单对象并且不担心对象的原型链时,使用if (typeof(obj[x]) !== 'undefined')...是最安全,最快的方法。

如果您使用一个简单的对象作为哈希表并且从不做任何事情,那么我会使用if (obj[x])...因为我发现它更具可读性。

玩得开心。