拥有多个属性的hasOwnProperty函数

8

我正在尝试查看一个对象是否具有某些属性,并且在使用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上使用一个数组。

我是否缺少某些理论概念?是否有一些方法可以解决这些问题?

6个回答

20

这里发生了两件事情。

首先,hasOwnProperty 只接受一个参数。因此,它会忽略你传给它的其他参数。

其次(我这里稍作简化),它将把第一个参数转换为 字符串,然后检查对象是否具有该属性。

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

之所以 { "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]}`));


2
根据文档,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);


2

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

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

这将返回一个简单的 true。 数组 .every 将为数组中的每个项运行一个条件,并仅在所有项的条件都为 true 时返回 true。 请参阅 Mozilla Web 文档


将其以更可重用的格式编写会更有帮助,例如创建一个小箭头函数或标准函数来接收参数。此外,按照当前的编写方式,每次调用 every 函数时都会在新对象上测试属性,虽然它可以工作,但这是具有误导性的,理想情况下,您应该测试单个对象的一组属性。 - Ralph

1

首先,就让第三个片段返回true而言,我认为这是不可能的。最好的办法是逐个检查每个属性:

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

这应该会给你想要的东西。
但是要理解为什么前两个返回true,但第三个返回false: hasOwnProperty方法只接受一个参数(额外的参数会被忽略),并且它期望该参数是一个字符串。如果参数不是一个字符串,那么JavaScript将尝试将其强制转换为一个字符串(通常使用.toString方法)。
所以你的前两个片段是等价的,因为: ["a"].toString() === "a",所以在参数被转换为字符串后,hasOwnProperty(["a"])hasOwnProperty("a")相同。
然后在你的第二个片段中,第二个参数"b"被简单地忽略了,使其等价于只有hasOwnProperty("a")
最后,你的第三个片段使用了["a", "b"]["a", "b"].toString() === "a,b",这不是你对象的属性。

0
你可以通过以下的 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]);
        }
}

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