如何检查变量是否包含某个属性?

假设:

var x = 'some string';

然后我想这样做:

if ('trim' in x)

但这给了我一个:

Uncaught TypeError: Cannot use 'in' operator to search for 'trim' in string

我可以通过使用以下方法使其工作:

'trim' in x.__proto__

但根据 __proto__说法,它已被弃用,并且它的使用(引用)“存在争议且不鼓励”

那么我该如何实现这个目标呢?

我曾尝试使用Object.keys(x),但它仅列出了作为索引有效的键,而不是属性。

我知道,在这个特定的例子中,我可以简单地使用typeof x === 'string',但这不是一个通用的解决方案。

10

  • 这个变量是字符串还是对象?


    – 

  • 您可以使用。因此'trim' in Object.getPrototypeOf(x)返回true


    – 


  • 1
    为什么不呢x.trim


    – 

  • 1
    @JaromandaX 我猜可能是鸭子类型的原因。您可能想检查原始类型或对象上可能存在的属性。如果存在,则使用它。但原始类型不适用于inx.someProp并不一定意味着它缺失,例如{ someProp: undefined }


    – 

  • 1
    @AnthonyHeremans 这根本不是问题所要表达的?它清楚地说明并演示了如何检查属性。


    – 


最佳答案
4

如果由于某种原因您想要避免通过直接访问该属性x[prop],您可以先将值传递给Object函数,然后再使用进行测试in

let x = 'some string';
console.log(x != null && 'trim' in Object(x));

4

  • 为什么你要更改答案以包含对 null 的检查?如果x = null你原来的答案工作正常,不是吗?(​​返回 false)


    – 

  • 1
    @LukasKroess"toString" in Object(null)true


    – 

  • 1
    @LukasKroessObject(null)Object(undefined)返回一个空对象,这样你就会得到'toString' in Object(null)真实的结果。


    – 

  • @VLAZ (+还有@Unmitigated) 我明白了。感谢你们两位的提醒。


    – 

运算符不适用于原始值。还有一个与之相同的运算符in,但也有相同的限制。

但是,解决这个问题的一个简单方法是通过传递值而不使用new。这样做会将原语转换为其包装器类,而如果输入是对象,则会按原样返回。因此,Object("a string")与 相同,new String("a string")Object({ some: "object" })与 相同{ some: "object" }。这将允许通过in(或Reflect.has())查找这些值。

需要注意的是,Object(null)Object(undefined)将创建一个普通对象。这可能会对类似的东西返回假阳性"toString in Object(null)。由于这两个值不能具有属性,因此可以使用以下方法将它们排除在检查之外:

target != null && prop in Object(target)

演示:

const prop = "trim";

function propIn(target, prop) {
  return target != null && prop in Object(target);
}

const string = "a string";
const number = 42;
const bigint = 42n;
const boolean = true;
const symbol = Symbol("a symbol");
const obj = {an: "object"};
const objWithProp = {trim() { return "object with a .trim() method"; } }

console.log( propIn(string     , prop));
console.log( propIn(number     , prop));
console.log( propIn(bigint     , prop));
console.log( propIn(boolean    , prop));
console.log( propIn(symbol     , prop));
console.log( propIn(null       , prop));
console.log( propIn(undefined  , prop));
console.log( propIn(obj        , prop));
console.log( propIn(objWithProp, prop));
.as-console-wrapper { max-height: 100% !important; }

1

  • 1
    谢谢。这似乎确实是完整的答案。我只是觉得将@Unmitigated 的答案标记为已接受是公平的,因为他们几分钟前发布了完全相同的方法。


    – 

hasProperty您可以验证任何变量是否具有类似以下代码片段中的函数的属性。

function hasProperty ( mySubject, myProperty )
{
  if ( ! ((mySubject === null) || (mySubject === undefined)) )
  {
    if ( (typeof mySubject == 'function') || (typeof mySubject == 'object') )
    {
      return Reflect.has(mySubject, myProperty);
    }
    
    else if ( typeof mySubject[myProperty] != 'undefined' )
    {
      // Note that here mySubject is a primitive value.
      // Properties can not be defined in primitives, but
      // can be defined on primitive prototypes.
      return true;
    }
  }
  
  return false;
}

// TESTING //

const mySubject1 = 'Anything goes here';
const mySubject2 = 300;
const mySubject3 = new Object;
const mySubject4 = undefined;
const mySubject5 = { valueOf: undefined };
const mySubject6 = Object.create(null);

mySubject6.valueOf = Object.prototype.valueOf;

console.log('mySubject1 =', mySubject1);
console.log('mySubject2 =', mySubject2);
console.log('mySubject3 =', mySubject3);
console.log('mySubject4 =', mySubject4);
console.log('mySubject5 =', mySubject5);
console.log('mySubject6 =', mySubject6);

console.log('Is mySubject1.valueOf defined?', hasProperty(mySubject1, 'valueOf'));
// Outputs: Is mySubject1.valueOf defined? true

console.log('Is mySubject2.valueOf defined?', hasProperty(mySubject2, 'valueOf'));
// Outputs: Is mySubject2.valueOf defined? true

console.log('Is mySubject3.valueOf defined?', hasProperty(mySubject3, 'valueOf'));
// Outputs: Is mySubject3.valueOf defined? true

console.log('Is mySubject4.valueOf defined?', hasProperty(mySubject4, 'valueOf'));
// Outputs: Is mySubject3.valueOf defined? false

console.log('Is mySubject5.valueOf defined?', hasProperty(mySubject5, 'valueOf'));
// Outputs: Is mySubject5.valueOf defined? true

console.log('Is mySubject6.valueOf defined?', hasProperty(mySubject6, 'valueOf'));
// Outputs: Is mySubject6.valueOf defined? true

注意,你可以使用Reflect.has(obj, prop)。但是如果obj没有通过obj instanceof Object,则会引发异常,这就是使用mySubject1mySubject2mySubject4作为obj参数时发生的情况。

7

  • 请解释如何解决这个问题。仅提供代码的答案不是好答案


    – 

  • 1
    @DarkBee 我觉得这个可能是。我还问“我该如何检查”,他回答说“你可以这样检查”,然后提供了代码。你还希望他写什么?


    – 

  • 1
    你可以这样检查”不是一个答案。答案不只是针对 OP,还针对未来遇到类似问题的读者。


    – 


  • typeof mySubject[myProperty] != 'undefined'不会告诉您是否缺少某个属性。它可能存在,但其值可能是undefined:考虑obj = { hello: undefined }然后hasProperty(obj, "hello")两者hasProperty(obj, "world")都返回false,但只有其中一个属性缺失。


    – 

  • @VLAZ 谢谢。我编辑了脚本,现在它已经完成了。现在无论如何它都可以工作了。


    – 

要检查变量是否包含某个属性或方法,可以将 typeof 运算符与 Object.getPrototypeOf() 结合使用,以安全地访问原型,而无需使用proto。具体操作如下:

var x = 'some string';

function hasMethod(obj, method) {
    return typeof Object.getPrototypeOf(obj)[method] === 'function';
}

if (hasMethod(x, 'trim')) {
    console.log("The string has the 'trim' method.");
} else {
    console.log("The string does not have the 'trim' method.");
}

Object.getPrototypeOf(obj):这将获取对象的原型,而无需使用已弃用的proto

typeof … === ‘function’:检查指定的方法是否存在并且确实是一个函数。

这种方法用途广泛,可用于检查任何对象的方法,而不仅仅是字符串。只需将对象和方法名称作为字符串传递给 hasMethod 函数即可。

1

  • 1
    hasMethod({trim() { return "has a trim method" } }, "trim")将会回归false


    –