【问题标题】:hasOwnProperty with more than one propertyhasOwnProperty 具有多个属性
【发布时间】:2018-07-17 03:17:57
【问题描述】:

我正在尝试发现一个对象是否具有某些属性并且我在使用 hasOwnProperty 方法时遇到了问题。

我在数组上使用该方法(我知道文档说明了一个字符串)。

以下行返回 true:

{ "a": 1, "b": 2 }.hasOwnProperty( ["a"]);

此行也返回 true:

{ "a": 1, "b": 2 }.hasOwnProperty( "a", "b");

但是这个返回false:

{ "a": 1, "b": 2 }.hasOwnProperty( ["a", "b"])

我需要它返回 true。我正在使用 Object.keys(object) 来获取我正在使用的属性,它返回一个数组,所以我需要在 hasOWnProperty 上使用一个数组。

我缺少一些理论概念吗?有没有办法解决这个问题?

【问题讨论】:

    标签: javascript object methods hasownproperty


    【解决方案1】:

    这里发生了两件事。

    首先,hasOwnProperty 只接受一个参数。所以它会忽略你传递给它的任何其他参数。

    第二,(我在这里稍微简化一下)它将第一个参数转换为String,然后然后检查对象是否具有该属性.

    让我们看看你的测试用例:

    { "a": 1, "b": 2 }.hasOwnProperty( "a", "b"); 返回true 的原因是它忽略了第二个参数。所以实际上它只是检查“a”。

    { "a": 1, "b": 2 }.hasOwnProperty( ["a", "b"]) 返回false,因为第一个参数["a", "b"] 被转换为"a,b",并且没有{ "a": 1, "b": 2 }["a,b"]

    要确定给定对象是否具有数组中的所有属性,您可以遍历数组并检查每个属性,如下所示:

    function hasAllProperties(obj, props) {
        for (var i = 0; i < props.length; i++) {
            if (!obj.hasOwnProperty(props[i]))
                return false;
        }
        return true;
    }
    

    或者,如果您喜欢,可以使用 every 函数隐式执行此操作:

    var props = ["a", "b"];
    var obj = { "a": 1, "b": 2 };
    var hasAll = props.every(prop => obj.hasOwnProperty(prop));
    

    我希望这有助于澄清事情。祝你好运!

    【讨论】:

      【解决方案2】:

      如果要检查对象自身的属性,可以使用Object.getOwnPropertyNames 方法。它返回直接在给定对象上找到的所有属性(包括不可枚举的属性,使用 Symbol 的属性除外)的数组。

      let o = { "a": 1, "b": 2 };
      Object.getOwnPropertyNames(o).forEach(k => console.log(`key: ${k}, value: ${o[k]}`));

      【讨论】:

        【解决方案3】:

        根据文档,hasOwnProperty() 方法似乎将字符串或符号作为参数。所以我认为hasOwnProperty() 无法获取字符串集合并测试对象是否将每个字符串都作为属性。

        我认为另一种方法是获取字符串数组并遍历每个字符串。然后对于数组中的每个字符串(要测试的属性),您可以测试对象是否具有该属性。这是一个例子:

        const o = new Object();
        var propsToTest = ['a', 'b'];
        o.a = 42;
        o.b = 40;
        
        var hasProperties = true;
        propsToTest.forEach(function(element) {	// For each "property" in propsToTest, verify that o hasOwnProperty
          if(!o.hasOwnProperty(element))
            hasProperties = false;
        });
        
        console.log(hasProperties);

        【讨论】:

          【解决方案4】:

          首先,就让你的第三个 sn-p 返回 true 而言,我认为这是不可能的。最好的办法是单独检查每个属性:

          const obj = { "a": 1, "b": 2 };
          console.log(["a", "b"].every(p => obj.hasOwnProperty(p)))

          这应该给你你想要的。


          但要理解为什么前两个返回 true,而第三个返回 false:

          hasOwnProperty 方法只接受一个参数(忽略其他参数),并且它期望该参数是一个字符串。如果参数不是字符串,那么 JavaScript 会尝试将其强制为一个(通常使用.toString 方法)。

          所以你的前两个 sn-ps 是等价的,因为:

          ["a"].toString() === "a",所以hasOwnProperty(["a"])hasOwnProperty("a")在参数转换为字符串后是一样的。

          然后在您的第二个 sn-p 中,第二个参数 "b" 将被忽略,使其再次等同于 hasOwnProperty("a")

          最后,您的第三个 sn-p 使用 ["a", "b"]["a", "b"].toString() === "a,b",这不是您的对象的属性。

          【讨论】:

            【解决方案5】:

            您可以通过像这样的for...in 循环来实现这一点

            const obj = { "a": 1, "b": 2 };
            
            for (key in obj) {
                    if (obj.hasOwnProperty(key)) {
                       console.log('has', key, obj[key]);
                    } else {
                       console.log('not', key, obj[key]);
                    }
            }
            

            【讨论】:

              【解决方案6】:

              所以这是一个老问题,我有点惊讶没有人想到写它,但这通常可以在数组上使用.every 解决。所以对于原始问题,代码应该是这样的:

              ["a", "b"].every((item) => ({ "a": 1, "b": 2 }.hasOwnProperty(item)))
              

              这将返回一个简单的 true。 数组.every 将为数组中的每个项目运行一个条件,并且仅当条件对所有项目都为真时才返回真。 见the the mozilla web docs

              【讨论】:

              • 以更可重用的格式编写它会更有帮助,例如创建一个小箭头函数或标准函数来接收参数。同样的编写方式,您实际上是在每次调用 every 函数时测试新对象的属性,虽然它工作,但它会产生误导,理想情况下您想要测试单个对象的属性集.
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-02-13
              • 1970-01-01
              • 2021-06-11
              • 2019-04-15
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多