【问题标题】:How do I check if an object has a specific property in JavaScript?如何检查对象是否在 JavaScript 中具有特定属性?
【发布时间】:2010-09-13 05:19:53
【问题描述】:

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

考虑:

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

这是最好的方法吗?

【问题讨论】:

  • 我用大家的答案写了一个jsperf测试,看看哪个最快:jsperf.com/dictionary-contains-key
  • (对象中的'propertyName')? '属性存在' : '属性不存在'
  • @styfle 感谢 jsperf 测试。 inhasOwnProperty 出来方式对我来说比其他人慢(慢 98%)。我对hasOwnProperty 变慢并不感到惊讶,但我对in 感到惊讶。
  • 有一个新的第 3 阶段提案Object.hasOwn,它解决了Object.prototype.hasOwnProperty 的一些问题。

标签: javascript


【解决方案1】:

我对给出的答案感到非常困惑——其中大多数都是完全不正确的。当然,您可以拥有具有 undefined、null 或 false 值的对象属性。所以简单地将属性检查减少到typeof this[property],或者更糟糕的是,x.key 会给你带来完全误导的结果。

这取决于您要查找的内容。如果您想知道一个对象是否物理上包含一个属性(并且它不是来自原型链上的某个地方),那么object.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 的一个有效的跨浏览器解决方案,但有一个警告:它无法区分原型和实例上的相同属性的情况 - 它只是假设它来自原型。您可以根据自己的情况将其更改为更宽松或更严格,但至少这应该更有帮助。

【讨论】:

  • @grantwparks 如果您正在构建一个简单的滑块插件并想要检查选项是否存在,那么这可能确实超出了需要。你可以做类似var w = opts.w || 100;的事情。但是,如果您正在研究图书馆之类的东西,您可能需要在某些部分走得更远。
  • @Kasztan __proto__ 是非标准的,在某些较旧的浏览器中不起作用。即使最近添加了Object.getPrototypeOf,该标准仍表示您仍然无法更改现有对象的原型。
  • John Resig 的答案似乎在 IE8 中不起作用,在这个现场演示 jsbin.com/tovaburefeva/1/edit?js,output 中看到它失败了。我认为这是因为hasOwnProperty() "is not supported on host objects for Internet Explorer 8 and below"msdn.microsoft.com/en-us/library/ie/328kyd6z(v=vs.94).aspxstackoverflow.com/questions/8157700/…
  • A for(prop in object) 循环仅迭代可枚举的属性。但是,prop in object 会检查 object 是否在原型链中的某处具有属性 prop,这与它是否可枚举无关。
  • 警告词:不要使用in检查原语。
【解决方案2】:

Underscore.js 或(even betterLodash

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

【讨论】:

  • 我猜这是因为“添加这个库”很少是一个流行的解决方案,即使问题是关于复杂的 DOM 操作并且答案是“去使用 jQuery”。
  • 我明白你的意思,@sudowned,谢谢。顺便说一句,如果不想包含整个 lodash 库,可以编译子组件或 npm install lodash.has,它公开了一个 npm 模块,其中只有一个 has 函数,在缩小时编译到 175 个字节。查看lodash.has/index.js 以了解一个非常受欢迎和值得信赖的图书馆是如何运作的也是很有见地的。
  • lodash 的版本适用于此:.has(undefined, 'someKey') => falseunderscore 返回undefined
  • 致所有抱怨将lodash 添加为“又一个”依赖项的人:对于这类事情来说,这是一个相当普遍(如果不是最常见的话)的库。玩得开心重新发明轮子。
  • 即使你想重新发明轮子,检查现有的轮子也不错。
【解决方案3】:

用途:

var x = {
  'key': 1
};

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

【讨论】:

  • 请注意,它适用于狭义的“对象”,因此声明为 {} 或使用构造函数创建,它不接受数组或原语。并不是说 OP 需要它,而是其他一些答案提供了更广泛的技术(使用数组、字符串等)
  • @РСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ 感谢您指出这一点(接受的答案没有详细说明为什么应该使用 in 运算符。另请注意,in 运算符具有出色的浏览器支持987654327@stackoverflow.com/questions/2920765/…
  • Operator in 也检查原型属性,而 hasOwnProperty 仅迭代用户定义的属性。参考:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • 'key' in x 使用数组。证明:stackoverflow.com/questions/33592385/…
【解决方案4】:

注意:由于严格模式和hasOwnProperty,以下内容如今已基本过时。正确的解决方案是使用严格模式并使用obj.hasOwnProperty 检查属性是否存在。这个答案早于这两件事,至少被广泛实施(是的,它就是那么旧)。将以下内容作为历史记录。


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

因此,一种更稳健的方法如下:

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

另一方面,这种方法更冗长,也更慢。 :-/

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

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

【讨论】:

  • 只是好奇,因为void 0 被定义为返回规范的undefined,可以做x.attribute !== void 0 吗?
  • Brian:我不是专家,但这确实是一个正确的方法。
  • 如果著名的“其他人”重新定义了 undefined 是什么,我认为最好的做法是重写该代码。
  • 拥有一个可靠的未定义变量的最佳方法是在闭包内工作,并拥有一个无与伦比的函数签名:(function (undefined) { // undefined is actually undefined here })();
  • @evanrmurphy 不要使用它,它已经严重过时了(请参阅我答案开头的注释)。
【解决方案5】:
if (x.key !== undefined)

Armin Ronacher好像已经有了beat me to it,但是:

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!');
}

as pointed out by Konrad RudolphArmin Ronacher 更安全但更慢的解决方案是:

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

【讨论】:

  • 我认为这还不够好。 x.hasOwnProperty('toString') === true;
  • 不是要求不同意,而是要理解。 x.hasOwnProperty 是否会返回除布尔值 true 或 false 之外的任何内容?如果没有,发布的代码应该每次都可以工作。我想也许如果方法被覆盖了,但是除非你知道覆盖方法,否则依赖结果永远不会可靠。
  • 我认为我们有误会。我的意思是使用你的方法,它会说'toString'是它自己的属性,但它不是。
  • Object.prototype 已经有一个内置的,正确的hasOwnProperty。用不正确的实现覆盖它(1. 属性可以有值undefined,2. 这会给继承的属性带来误报)只是一个非常糟糕的主意。不正确的答案可以而且应该被删除。我不知道你是否可以在 08 年 9 月 when you saw Resig's answer 这样做,所以评论建议现在就这样做。
【解决方案6】:

考虑 Javascript 中的以下对象

const x = {key: 1};

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

console.log("key" in x);

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

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

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

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

Object.getOwnPropertyNames(x);

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

Reflections 提供可用于与 Javascript 对象交互的方法。静态 Reflect.has() 方法的工作方式类似于 in 运算符作为函数。

console.log(Reflect.has(x, 'key'));
// expected output: true

console.log(Reflect.has(x, 'key2'));
// expected output: false

console.log(Reflect.has(object1, 'toString'));
// expected output: true

最后可以使用typeof操作符直接检查对象属性的数据类型:

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

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

同样,您可以通过直接比较 undefined Javascript 属性来检查属性是否存在

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

这应该可以工作,除非在 x 对象上将 key 专门设置为 undefined

【讨论】:

    【解决方案7】:

    让我们在这里消除一些混乱。首先,让我们通过假设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 将是错误的,!== undefined 也是如此。然而,for..in 仍会在枚举中列出它。

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

    【讨论】:

      【解决方案8】:

      如果您正在搜索属性,则“否”。你想要:

      if ('prop' in obj) { }
      

      一般来说,你不应该关心属性是来自原型还是对象。

      但是,由于您在示例代码中使用了“key”,因此您似乎将对象视为哈希,在这种情况下,您的答案将是有意义的。所有的哈希键都是对象中的属性,你可以避免原型贡献的额外属性。

      John Resig's answer 说的很全面,但是我觉得不太清楚。尤其是何时在 obj 中使用“'prop'”。

      【讨论】:

      • 请注意,in 运算符具有出色的浏览器支持 IE 5.5+, Chrome 1.0+, Firefox 1.0+, Safari 3.0+ stackoverflow.com/questions/2920765/…
      • 正如另一条关于使用 in 运算符的评论中指出的那样:“它适用于狭义的‘对象’,因此声明为 {} 或使用构造函数创建,它不接受数组或原语。不是 OP 需要它,而是其他一些答案提供了更广泛的技术(使用数组、字符串等)"
      • 评论因为我被否决了两次没有评论。但我还是喜欢我的回答。也许这样做的人想要一个“全面”的答案来测试所有类型的属性。但我的答案是概念性的,为此,简洁。回复:Adrien Be,一个不可枚举的属性并不适用于一般用户范围,所以从概念上讲“in”是可以的;)
      【解决方案9】:

      要测试简单的对象,请使用:

      if (obj[x] !== undefined)
      

      如果您不知道它是什么对象类型,请使用:

      if (obj.hasOwnProperty(x))
      

      所有其他选项都较慢...

      详情

      对 Node.js 下 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: 4.51 s
      hasKey2 execution time: 0.90 s
      hasKey3 execution time: 0.76 s
      hasKey4 execution time: 0.93 s
      hasKey5 execution time: 2.15 s
      

      最重要的是,如果您的 Obj 不一定是一个简单的对象,并且您希望避免检查对象的原型链并确保 x 直接归 Obj 所有,请使用if (obj.hasOwnProperty(x))...

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

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

      【讨论】:

        【解决方案10】:

        是的 :) 我认为你也可以这样做 Object.prototype.hasOwnProperty.call(x, 'key') 如果 x 有一个名为 hasOwnProperty 的属性也应该工作 :)

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

        【讨论】:

          【解决方案11】:

          你也可以使用the ES6 Reflect object:

          x = {'key': 1};
          Reflect.has( x, 'key'); // returns true
          

          Reflect.has 的 MDN 文档可以在 here 找到。

          静态Reflect.has() 方法与in operator 作为函数一样工作。

          【讨论】:

            【解决方案12】:

            不要这样做object.hasOwnProperty(key))。这真的很糟糕,因为这些方法可能会被相关对象的属性所遮蔽——考虑{ hasOwnProperty: false }——或者,该对象可能是一个空对象(Object.create(null))

            最好的方法是Object.prototype.hasOwnProperty.call(object, key) 或:

            const has = Object.prototype.hasOwnProperty; // Cache the lookup once, in module scope.
            console.log(has.call(object, key));
            /* Or */
            import has from 'has'; // https://www.npmjs.com/package/has
            console.log(has(object, key));
            

            【讨论】:

            • 我同意这种方法,它应该是公认的答案,因为它是在保持性能的同时最安全的方法! eslint.org/docs/rules/no-prototype-builtins 说“例如,Web 服务器解析来自客户端的 JSON 输入并直接在结果对象上调用 hasOwnProperty 是不安全的,因为恶意客户端可以发送像 {"hasOwnProperty": 1} 这样的 JSON 值并导致服务器崩溃。”
            【解决方案13】:
            if(x.hasOwnProperty("key")){
              // …
            }
            

            因为

            if(x.key){
              // …
            }
            

            如果x.key 是假的(例如,x.key === "")则失败。

            【讨论】:

              【解决方案14】:

              好吧,看来我的答案是正确的,除非你不想继承属性:

              if (x.hasOwnProperty('key'))
              

              以下是包含继承属性的其他一些选项:

              if (x.key) // Quick and dirty, but it does the same thing as below.
              
              if (x.key !== undefined)
              

              【讨论】:

              • 警告 x.hasOwnProperty('key') 可以为真,而 x.key !== undefined 不为真。
              • 对于var x = { key: false };x.key 方法不正确。
              • 如果(x.key)不正确,如x = {key:0},则检查不通过。
              【解决方案15】:

              另一种相对简单的方法是使用Object.keys。这将返回一个array,这意味着您可以获得数组的所有功能。

              var noInfo = {};
              var info = {something: 'data'};
              
              Object.keys(noInfo).length //returns 0 or false
              Object.keys(info).length //returns 1 or true
              

              尽管我们所处的世界拥有强大的浏览器支持。因为这个问题太老了,我想我会添加这个: 从JavaScript v1.8.5 开始,它可以安全使用。

              【讨论】:

              • 对,但是如果您想知道 info 是否有一个名为 someotherthing 的属性怎么办?这是 OP 正在寻找的想法。
              • 那你会做Object.keys(info).indexOf('someotherthing') !== -1
              • 什么是"JS v1.8.5"? “JavaScript v1.8.5”*?它似乎与任何 ECMAScript 版本都不匹配(版本 8 于 2017 年发布)。 jQuery 1.8 于 2012 年发布。
              • 好的,JavaScript 1.8.5 于 2011 年与 Firefox 4 (2011-03-22) 一起发布。 ECMAScript 5(链接到)的第一个版本来自 2009 年。
              【解决方案16】:

              hasOwnProperty "可以用来判断一个对象是否具有指定属性作为该对象的直接属性;与in运算符不同,该方法不向下检查对象的原型链。”

              因此,很可能,对于您的问题,您不想使用 hasOwnProperty,它确定属性是否存在为 直接附加到对象本身,。

              如果您想确定该属性是否存在于原型链中,您可能希望像这样使用它:

              if (prop in object) { // Do something }
              

              【讨论】:

              • 我得到“无法使用 'in' 运算符在 myObject 中搜索 'prop'”
              【解决方案17】:

              JavaScript 现在正在发展和成长,因为它现在有很好甚至有效的方法来检查它。

              以下是检查对象是否具有特定属性的一些简单方法:

              1. 使用hasOwnProperty()
              const hero = {
                name: 'Batman'
              };
              
              hero.hasOwnProperty('name');     // => true
              hero.hasOwnProperty('realName'); // => false
              
              1. 使用关键字/运算符in
              const hero = {
                name: 'Batman'
              };
              
              'name' in hero;     // => true
              'realName' in hero; // => false
              
              1. undefined关键字比较
              const hero = {
                name: 'Batman'
              };
              
              hero.name;     // => 'Batman'
              hero.realName; // => undefined
              
              // So consider this
              hero.realName == undefined // => true (which means property does not exists in object)
              hero.name == undefined // => false (which means that property exists in object)
              

              更多信息,请查看here

              【讨论】:

                【解决方案18】:

                您可以使用以下方法-

                var obj = {a:1}
                console.log('a' in obj)               // 1
                console.log(obj.hasOwnProperty('a'))  // 2
                console.log(Boolean(obj.a))         // 3
                

                以下几种方式的区别如下-

                1. 在第一种和第三种方法中,我们不仅搜索对象,还搜索其原型链。如果对象没有该属性,但该属性存在于其原型链中,则它会给出 true。

                var obj = {
                    a: 2,
                    __proto__ : {b: 2}
                }
                
                console.log('b' in obj)
                console.log(Boolean(obj.b))
                1. 第二种方法将只检查它自己的属性。示例 -

                var obj = {
                    a: 2,
                    __proto__ : {b: 2}
                }
                
                console.log(obj.hasOwnProperty('b'))
                1. 第一种方法和第三种方法之间的区别在于,如果有一个属性的值未定义,则第三种方法会给出 false,而第一种方法会给出 true。

                var obj = {
                    b : undefined
                }
                
                console.log(Boolean(obj.b))
                console.log('b' in obj);

                【讨论】:

                • Boolean({b:''}.b) -> false
                • @KamilKiełczewski 是的,它应该给出 false,在这种情况下任何虚假值都将返回 false
                【解决方案19】:

                给定 myObject 对象和 “myKey” 作为键名:

                Object.keys(myObject).includes('myKey')
                

                myObject.hasOwnProperty('myKey')
                

                typeof myObject.myKey !== 'undefined'
                

                最后一个被广泛使用,但(正如在其他答案和 cmets 中指出的那样)它也可以匹配从 Object 原型派生的键。

                【讨论】:

                  【解决方案20】:

                  这是针对特定情况的另一种选择。 :)

                  如果您想测试对象上的成员并想知道它是否已设置为以下内容:

                  • ''
                  • 未定义
                  • 0 ...

                  那么你可以使用:

                  var foo = {};
                  foo.bar = "Yes, this is a proper value!";
                  if (!!foo.bar) {
                      // member is set, do something
                  }
                  

                  【讨论】:

                  【解决方案21】:

                  性能

                  今天 2020 年 12 月 17 日,我在 Chrome v87、Safari v13.1.2 和 Firefox v83 上对 MacOs HighSierra 10.13.6 进行测试以获取所选解决方案。

                  结果

                  我只比较解决方案 A-F,因为它们给出了详细信息部分中 sn-p 中使用的所有 cased 的有效结果。适用于所有浏览器

                  • 基于in (A) 的解决方案很快或最快
                  • 如果键不存在,解决方案 (E) 对于大型对象的 chrome 最快,对于小型阵列的 firefox 最快
                  • 对于小型阵列,解决方案 (F) 最快(~ > 10 倍于其他解决方案)
                  • 解决方案 (D,E) 非常快
                  • 基于 losash has (B) 的解决方案最慢

                  详情

                  我执行了 4 个测试用例:

                  • 当对象有 10 个字段并且搜索到的键存在时 - 你可以运行它HERE
                  • 当对象有 10 个字段并且搜索到的键不存在时 - 你可以运行它HERE
                  • 当对象有 10000 个字段并且存在搜索键时 - 你可以运行它HERE
                  • 当对象有 10000 个字段并且搜索到的键存在时 - 你可以运行它HERE

                  下面的 sn-p 显示了解决方案之间的差异 A B C D E F G H I J K

                  // SO https://stackoverflow.com/q/135448/860099
                  
                  
                  // src: https://stackoverflow.com/a/14664748/860099
                  function A(x) {
                    return 'key' in x
                  }
                  
                  // src: https://stackoverflow.com/a/11315692/860099
                  function B(x) {
                    return _.has(x, 'key')
                  }
                  
                  // src: https://stackoverflow.com/a/40266120/860099
                  function C(x) {
                    return Reflect.has( x, 'key')
                  }
                  
                  // src: https://stackoverflow.com/q/135448/860099
                  function D(x) {
                    return x.hasOwnProperty('key')
                  }
                  
                  // src: https://stackoverflow.com/a/11315692/860099
                  function E(x) {
                    return Object.prototype.hasOwnProperty.call(x, 'key')
                  }
                  
                  // src: https://stackoverflow.com/a/136411/860099
                  function F(x) {
                    function hasOwnProperty(obj, prop) {
                        var proto = obj.__proto__ || obj.constructor.prototype;
                        return (prop in obj) &&
                            (!(prop in proto) || proto[prop] !== obj[prop]);
                    }
                    return hasOwnProperty(x,'key')
                  }
                  
                  // src: https://stackoverflow.com/a/135568/860099
                  function G(x) {
                    return typeof(x.key) !== 'undefined'
                  }
                  
                  // src: https://stackoverflow.com/a/22740939/860099
                  function H(x) {
                    return x.key !== undefined
                  }
                  
                  // src: https://stackoverflow.com/a/38332171/860099
                  function I(x) {
                    return !!x.key
                  }
                  
                  // src: https://stackoverflow.com/a/41184688/860099
                  function J(x) {
                    return !!x['key']
                  }
                  
                  // src: https://stackoverflow.com/a/54196605/860099
                  function K(x) {
                    return Boolean(x.key)
                  }
                  
                  
                  // --------------------
                  // TEST
                  // --------------------
                  
                  let x1 = {'key': 1};
                  let x2 = {'key': "1"};
                  let x3 = {'key': true};
                  let x4 = {'key': []};
                  let x5 = {'key': {}};
                  let x6 = {'key': ()=>{}};
                  let x7 = {'key': ''};
                  let x8 = {'key': 0};
                  let x9 = {'key': false};
                  let x10= {'key': undefined};
                  let x11= {'nokey': 1};
                  
                  
                  
                  let b= x=> x ? 1:0;
                  
                  console.log('  1 2 3 4 5 6 7 8 9 10 11');
                  
                  [A,B,C,D,E,F,G,H,I,J,K ].map(f=> {  
                    console.log(
                      `${f.name} ${b(f(x1))} ${b(f(x2))} ${b(f(x3))} ${b(f(x4))} ${b(f(x5))} ${b(f(x6))} ${b(f(x7))} ${b(f(x8))} ${b(f(x9))} ${b(f(x10))}  ${b(f(x11))} `
                    )})
                    
                  console.log('\nLegend: Columns (cases)');
                  console.log('1.  key = 1 ');
                  console.log('2.  key = "1" ');
                  console.log('3.  key = true ');
                  console.log('4.  key = [] ');
                  console.log('5.  key = {} ');
                  console.log('6.  key = ()=>{} ');
                  console.log('7.  key = "" ');
                  console.log('8.  key = 0 ');
                  console.log('9.  key = false ');
                  console.log('10. key = undefined ');
                  console.log('11. no-key ');
                  <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"> </script>
                    
                  This shippet only presents functions used in performance tests - it not perform tests itself!

                  以下是 chrome 的示例结果

                  【讨论】:

                    【解决方案22】:

                    对象上存在一个方法“hasOwnProperty”,但不建议直接调用此方法,因为有时对象可能为空或对象上存在某些属性,例如:{ hasOwnProperty: false }

                    所以更好的方法是:

                    // Good
                    var obj = {"bar": "here bar desc"}
                    console.log(Object.prototype.hasOwnProperty.call(obj, "bar"));
                    
                    // Best
                    const has = Object.prototype.hasOwnProperty; // Cache the lookup once, in module scope.
                    console.log(has.call(obj, "bar"));

                    【讨论】:

                      【解决方案23】:

                      带有反射的 ECMAScript 6 解决方案。创建一个像这样的包装器:

                      /**
                      Gets an argument from array or object.
                      The possible outcome:
                      - If the key exists the value is returned.
                      - If no key exists the default value is returned.
                      - If no default value is specified an empty string is returned.
                      @param obj    The object or array to be searched.
                      @param key    The name of the property or key.
                      @param defVal Optional default version of the command-line parameter [default ""]
                      @return The default value in case of an error else the found parameter.
                      */
                      function getSafeReflectArg( obj, key, defVal) {
                         "use strict";
                         var retVal = (typeof defVal === 'undefined' ? "" : defVal);
                         if ( Reflect.has( obj, key) ) {
                             return Reflect.get( obj, key);
                         }
                         return retVal;
                      }  // getSafeReflectArg
                      

                      【讨论】:

                      • 当你的目标是 >= ES6 时,这是最好的方法吗?
                      • 恕我直言,这是最短和最简单的答案,但可能不是执行代码中最快的。但速度不再是问题。
                      • 为什么要发两次the same answer?你可以只投票给现有的...?
                      【解决方案24】:

                      根据具体用例的一些更简单和简短的选项:

                      1. 要检查属性是否存在,无论值如何,使用in operator ("a" in b)
                      2. 要检查变量的属性值,请使用bracket notation (obj[v])
                      3. 要检查属性值是否真实,请使用optional chaining (?.)
                      4. 要检查属性值布尔值,使用double-not / bang-bang / (!!)
                      5. 为空/未定义检查设置默认值,使用nullish coalescing operator (??)
                      6. 要为错误值检查设置默认值,请使用短路logical OR operator (||)

                      运行代码sn-p查看结果:

                      let obj1 = {prop:undefined};
                      console.log(1,"prop" in obj1);
                      console.log(1,obj1?.prop);
                      
                      let obj2 = undefined;
                      //console.log(2,"prop" in obj2); would throw because obj2 undefined
                      console.log(2,"prop" in (obj2 ?? {}))
                      console.log(2,obj2?.prop);
                      
                      let obj3 = {prop:false};
                      console.log(3,"prop" in obj3);
                      console.log(3,!!obj3?.prop);
                      
                      let obj4 = {prop:null};
                      let look = "prop"
                      console.log(4,"prop" in obj4);
                      console.log(4,obj4?.[look]);
                      
                      let obj5 = {prop:true};
                      console.log(5,"prop" in obj5);
                      console.log(5,obj5?.prop === true);
                      
                      let obj6 = {otherProp:true};
                      look = "otherProp"
                      console.log(6,"prop" in obj6);
                      console.log(6,obj6.look); //should have used bracket notation
                      
                      let obj7 = {prop:""};
                      console.log(7,"prop" in obj7);
                      console.log(7,obj7?.prop || "empty"); 

                      我看到很少有正确使用hasOwn 的实例,尤其是考虑到它的inheritance issues

                      【讨论】:

                        【解决方案25】:

                        您需要使用方法object.hasOwnProperty(property)。如果对象具有该属性,则返回 true,如果对象没有,则返回 false。

                        【讨论】:

                          【解决方案26】:

                          展示如何使用this answer

                          const object= {key1: 'data', key2: 'data2'};
                          
                          Object.keys(object).includes('key1') //returns true
                          

                          我们也可以使用indexOf,我更喜欢includes

                          【讨论】:

                            【解决方案27】:

                            hasOwnProperty() 方法返回一个布尔值,指示对象是否具有指定的属性作为它自己的属性(而不是继承它)。

                            const object1 = {};
                            object1.property1 = 42;
                            
                            console.log(object1.hasOwnProperty('property1'));
                            // expected output: true
                            
                            console.log(object1.hasOwnProperty('toString'));
                            // expected output: false
                            
                            console.log(object1.hasOwnProperty('hasOwnProperty'));
                            // expected output: false
                            

                            Know more

                            【讨论】:

                              【解决方案28】:

                              当你可以做的时候不要把事情过度复杂化:

                              var isProperty =  (objectname.keyname || "") ? true : false;
                              

                              对于大多数情况来说,它简单明了……

                              【讨论】:

                              • 最简单的就是 var isProperty = !!objectname.keyname;
                              • 如果对象如下const objectName = { keyname: false };,它应该返回true,因为keynameobjectname的一个属性。但由于该值为 false,因此使用此逻辑将返回 false。
                              【解决方案29】:

                              迭代对象自身属性的更好方法:

                              如果你想迭代对象的属性而不使用hasOwnProperty() 检查, 使用for(let key of Object.keys(stud)){}方法:

                              for(let key of Object.keys(stud)){
                                console.log(key); // will only log object's Own properties
                              }
                              

                              完整示例和与for-in with hasOwnProperty()的比较

                              function Student() {
                                this.name = "nitin";
                              }
                              
                              Student.prototype = {
                                grade: 'A'
                              }
                              
                              let stud = new Student();
                              
                              // for-in approach
                              for(let key in stud){
                                if(stud.hasOwnProperty(key)){
                                  console.log(key); // only outputs "name"
                                }
                              } 
                              
                              //Object.keys() approach
                              for(let key of Object.keys(stud)){
                                console.log(key);
                              }
                              

                              【讨论】:

                                猜你喜欢
                                • 2012-04-16
                                • 2021-03-12
                                • 2017-10-09
                                • 2017-01-09
                                • 1970-01-01
                                • 2014-01-01
                                • 1970-01-01
                                • 2014-05-08
                                相关资源
                                最近更新 更多