如何使用保存属性名称的变量检查对象属性是否存在?

830

我正在检查一个对象属性是否存在,变量中保存了所要查询的属性名称。

var myObj;
myObj.prop = "exists";
var myProp = "p"+"r"+"o"+"p";

if(myObj.myProp){
    alert("yes, i have that property");
};

这是因为它正在寻找 myObj.myProp 但我希望它检查 myObj.prop


3
可能有帮助:来自Pablo Cabrera在NCZOnline的评论中:「我认为值得注意的是,如果 hasOwnProperty 方法被覆盖了,你可以依靠 Object.prototype.hasOwnProperty.call(object, property)。」 - HumanInDisguise
12
这个问题 https://dev59.com/0W855IYBdhLWcg3wnFpO 是一个重复的问题吗?为什么?“检查存在性”和“访问值”是两回事吗?如果我错了,请纠正我.... - adnan2nd
这是不是重复的文本。 - Jeff Clayton
@HumanInDisguise 评论不应用于提供解决建议。您的评论最好放在包含静态引用建议和链接来源的答案中。现在,@adnan2d已经发布了这个建议,您的评论可以安全地删除了。 - mickmackusa
11个回答

1543
var myProp = 'prop';
if(myObj.hasOwnProperty(myProp)){
    alert("yes, i have that property");
}

或者

var myProp = 'prop';
if(myProp in myObj){
    alert("yes, i have that property");
}

或者

if('prop' in myObj){
    alert("yes, i have that property");
}
注意,hasOwnProperty 不会检查继承的属性,而 in 会检查。例如,'constructor' in myObj 是 true,但 myObj.hasOwnProperty('constructor') 不是。

36
与其他回答中的myObj[myProp]相比,hasOwnProperty()更好,因为即使myProp的值为0,它也能正常工作。 - Matt R
9
"in" 运算符不适用于字符串。例如,'length' in 'qqq' 将产生异常。因此,如果您想进行通用检查,需要使用 hasOwnProperty。 - Jacob
2
@Jacob,当你说“'in'运算符不能用于字符串”时,你是什么意思?使用“in”运算符时,左侧表达式必须是一个字符串或可以转换为字符串的值。是的,你不能在“qqq”中写入“length”,但你也不能写入“qqq”.hasOwnProperty('length')。 - Wachburn
2
@Wachburn: 'qqq'拥有'length'属性,所以返回值为true,你可以这样做。 - gen_Eric
4
为避免违反ESLint中的no-prototype-builtins规则,您应该使用Object.prototype.hasOwnProperty.call(myObj, myProp)代替myObj.hasOwnProperty(myProp) - Ilyich
显示剩余3条评论

61

6
这并不是 hasOwnProperty() 的实现方式。 - canon
7
这是错误的。通过给名称myProp加上引号,你不再引用myProp的值,而是声明了一个新的String()为'myProp',而在myObj中并没有名为'myProp'的属性。 - TriumphST
1
TriumpST:从上面链接的MDN中,“prop - 一个表示属性名称或数组索引的字符串或符号(非符号将被强制转换为字符串)。”。 - Ben Creasy
@KatinkaHesselink:您的评论是误导性的。问题是“如何使用保存属性名称的变量检查对象属性是否存在?” - Herbert Van-Vliet
1
"hasOwnProperty"并不等同于使用"in"运算符,正如Rocket Hazmat的回答所解释的那样。 - Max Barraclough
显示剩余2条评论

26

感谢大家的帮助和推动,以摆脱eval语句。需要用方括号而不是点符号表示变量。这段代码可以正常工作且代码整洁规范。

这些都是变量:appChoice、underI、underObstr。

if(typeof tData.tonicdata[appChoice][underI][underObstr] !== "undefined"){
    //enter code here
}

1
这对我来说看起来像是一个问题。如果tData.tonicdata[appChoice]的结果没有与underI匹配的属性/索引,那么就会抛出TypeError - Ynot
2
尽管您在最初的帖子中有意,但实际上您提出了一个与您提供答案的问题不同的问题。您想要检查属性的存在,但没有提及如何访问它。这使得这个答案与实际问题无关。 - Forage

24

自有财产:

var loan = { amount: 150 };
if(Object.prototype.hasOwnProperty.call(loan, "amount")) 
{ 
   //will execute
}
注意:使用 Object.prototype.hasOwnProperty 要比 loan.hasOwnProperty(..) 更好,因为如果原型链中定义了自定义的 hasOwnProperty(这里并没有),会产生影响。
var foo = {
      hasOwnProperty: function() {
        return false;
      },
      bar: 'Here be dragons'
    };

// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty

要查找包括继承的属性,请使用in运算符:(但您必须在'in'右侧放置一个对象,原始值会抛出错误,例如'length' in 'home'将抛出错误,但'length' in new String('home')不会)

const yoshi = { skulk: true };
const hattori = { sneak: true };
const kuma = { creep: true };
if ("skulk" in yoshi) 
    console.log("Yoshi can skulk");

if (!("sneak" in yoshi)) 
    console.log("Yoshi cannot sneak");

if (!("creep" in yoshi)) 
    console.log("Yoshi cannot creep");

Object.setPrototypeOf(yoshi, hattori);

if ("sneak" in yoshi)
    console.log("Yoshi can now sneak");
if (!("creep" in hattori))
    console.log("Hattori cannot creep");

Object.setPrototypeOf(hattori, kuma);

if ("creep" in hattori)
    console.log("Hattori can now creep");
if ("creep" in yoshi)
    console.log("Yoshi can also creep");

// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/in

注意:有人可能会尝试使用 typeof 和 [ ] 属性访问器,如下所示的代码,但这种方法并不总是有效...

var loan = { amount: 150 };

loan.installment = undefined;

if("installment" in loan) // correct
{
    // will execute
}

if(typeof loan["installment"] !== "undefined") // incorrect
{
    // will not execute
}

13

检查对象上是否存在属性的更安全方法是使用空对象或对象原型来调用hasOwnProperty()

var foo = {
  hasOwnProperty: function() {
    return false;
  },
  bar: 'Here be dragons'
};

foo.hasOwnProperty('bar'); // always returns false

// Use another Object's hasOwnProperty and call it with 'this' set to foo
({}).hasOwnProperty.call(foo, 'bar'); // true

// It's also possible to use the hasOwnProperty property from the Object
// prototype for this purpose
Object.prototype.hasOwnProperty.call(foo, 'bar'); // true

参考自MDN Web Docs - Object.prototype.hasOwnProperty()


5
如果你在引入 JavaScript 时可能会执行一些恶意操作,例如覆盖 hasOwnProperty,那么任何类似于这样的防护措施都无法使你的代码安全可靠。 - meustrus
@meustrus 我知道你的想法,但从商业角度来看,一个没有经验的开发者使用这个属性名是非常可能的,这并不一定意味着他们有恶意。 - skmasq

12

有更简单的解决方案,我没有看到对你实际问题的答案:

"它正在寻找 myObj.myProp,但我希望它检查 myObj.prop"

  1. 要从变量中获取属性值,请使用方括号表示法
  2. 要测试该属性的真值,请使用可选链
  3. 要返回布尔值,请使用双非 / 叹号叹号 / (!!)
  4. 如果您确定有一个对象并且只想检查属性是否存在(即使prop值为undefined也是true),请使用in运算符。或者,结合nullish coalescing运算符??以避免抛出错误。

var nothing = undefined;
var obj = {prop:"hello world"}
var myProp = "prop";

consolelog( 1,()=> obj.myProp); // obj does not have a "myProp"
consolelog( 2,()=> obj[myProp]); // brackets works
consolelog( 3,()=> nothing[myProp]); // throws if not an object
consolelog( 4,()=> obj?.[myProp]); // optional chaining very nice ⭐️⭐️⭐️⭐️⭐️
consolelog( 5,()=> nothing?.[myProp]); // optional chaining avoids throwing
consolelog( 6,()=> nothing?.[nothing]); // even here it is error-safe
consolelog( 7,()=> !!obj?.[myProp]); // double-not yields true
consolelog( 8,()=> !!nothing?.[myProp]); // false because undefined
consolelog( 9,()=> myProp in obj); // in operator works
consolelog(10,()=> myProp in nothing); // throws if not an object
consolelog(11,()=> myProp in (nothing ?? {})); // safe from throwing
consolelog(12,()=> myProp in {prop:undefined}); // true (prop key exists even though its value undefined)

// beware of 'hasOwnProperty' pitfalls
// it can't detect inherited properties and 'hasOwnProperty' is itself inherited
// also comparatively verbose
consolelog(13,()=> obj.hasOwnProperty("hasOwnProperty")); // DANGER: it yields false 
consolelog(14,()=> nothing.hasOwnProperty("hasOwnProperty")); // throws when undefined
obj.hasOwnProperty = ()=>true; // someone could overwrite it
consolelog(15,()=> obj.hasOwnProperty(nothing)); // DANGER: the foolish overwrite will now always return true
consolelog(16,()=> Object.prototype.hasOwnProperty.call(obj,"hasOwnProperty")); // explain?!
consolelog(17,()=> Object.hasOwn(obj,"hasOwnProperty")); // explain?!

function consolelog(num,myTest){
    try{
    console.log(num,myTest());
    }
    catch(e){
    console.log(num,'throws',e.message);
    }
}


6
你可以使用hasOwnProperty()方法以及in运算符。

4
以上内容就是我讨厌 JavaScript 的原因。 - pwaterz
2
@pwaterz 不要讨厌这个player - ArchNoob
2
"hasOwnProperty"并不等同于使用"in"运算符,正如Rocket Hazmat的回答所解释的那样。 - Max Barraclough
也许你可以尝试解释一下什么情况下使用任何一个选项都不重要,但是被接受的答案已经很清楚了。 - agbb

5

使用新的Object.hasOwn方法是另一种选择,其意图是替代Object.hasOwnProperty方法。

该静态方法返回true,如果指定的对象具有指定属性作为其自己的属性,否则返回false,如果该属性是继承的或者在该对象上不存在。

请注意,在生产环境中使用此方法之前,请仔细检查浏览器兼容性表,因为它仍被视为实验性技术,并且尚未得到所有浏览器的完全支持(即将到来)。

    var myObj = {};
    myObj.myProp = "exists";

    if (Object.hasOwn(myObj, 'myProp')){
        alert("yes, i have that property");
    }

了解更多关于Object.hasOwn的信息 - https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn

Object.hasOwn的浏览器兼容性 - https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn#browser_compatibility


2

检查对象属性是否存在的几种方法。

const dog = { name: "Spot" }

if (dog.name) console.log("Yay 1"); // Prints.
if (dog.sex) console.log("Yay 2"); // Doesn't print. 

if ("name" in dog) console.log("Yay 3"); // Prints.
if ("sex" in dog) console.log("Yay 4"); // Doesn't print.

if (dog.hasOwnProperty("name")) console.log("Yay 5"); // Prints.
if (dog.hasOwnProperty("sex")) console.log("Yay 6"); // Doesn't print, but prints undefined.

0

对我来说工作正常。

if (typeof receviedData?.d?.heartbeat_interval != "undefined") {
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接