JavaScript中如何判断一个对象是不是具有给定的属性
Posted
技术标签:
【中文标题】JavaScript中如何判断一个对象是不是具有给定的属性【英文标题】:How to determine whether an object has a given property in JavaScriptJavaScript中如何判断一个对象是否具有给定的属性 【发布时间】:2010-12-26 01:44:07 【问题描述】:无论x.y
的值如何,如何确定对象x
是否具有定义的属性y
?
我正在使用
if (typeof(x.y) !== 'undefined')
但这似乎有点笨拙。有没有更好的办法?
【问题讨论】:
不要用()
、it is an operator而不是函数“调用”typeof
【参考方案1】:
除了其他答案,我想建议使用Object.hasOwn()
方法来检查指定对象是否具有指定属性作为其自己的属性(即对象本身),您可以使用新的Object.hasOwn()
方法是一个静态方法,如果指定对象具有指定属性作为其自己的属性,则返回 true。如果该属性是继承的,或者不存在,则该方法返回 false。
const person = name: 'dan' ;
console.log(Object.hasOwn(person, 'name'));// true
console.log(Object.hasOwn(person, 'age'));// false
const person2 = Object.create(gender: 'male');
console.log(Object.hasOwn(person2, 'gender'));// false
建议在Object.hasOwnProperty()
上使用此方法,因为它也适用于使用Object.create(null)
创建的对象以及已覆盖继承的hasOwnProperty()
方法的对象。虽然可以通过在外部对象上调用Object.prototype.hasOwnProperty()
来解决这类问题,但Object.hasOwn()
克服了这些问题,因此是首选(参见下面的示例)
let person =
hasOwnProperty: function()
return false;
,
age: 35
;
if (Object.hasOwn(person, 'age'))
console.log(person.age); // true - the remplementation of hasOwnProperty() did not affect the Object
let person = Object.create(null);
person.age = 35;
if (Object.hasOwn(person, 'age'))
console.log(person.age); // true - works regardless of how the object was created
更多关于Object.hasOwn
的信息可以在这里找到:https://developer.mozilla.org/en-US/docs/Web/javascript/Reference/Global_Objects/Object/hasOwn
浏览器兼容性 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn#browser_compatibility
检查指定属性是否存在于对象本身或原型链中可以通过in
运算符进行验证,正如其他答案所建议的那样。
【讨论】:
【参考方案2】:与此线程中的其他示例不同,此实现仅断言该对象具有我们正在检查的属性。
const hasOwnProperty = <X extends , Y extends PropertyKey>(
object: X,
property: Y
): object is Record<Y, unknown> & X =>
return object.hasOwnProperty(property);
;
这是一个用于识别具有所需属性的分支的示例。
const hasOwnProperty = <X extends , Y extends PropertyKey>(
object: X,
property: Y
): object is Record<Y, unknown> & X =>
return object.hasOwnProperty(property);
;
type PaidProjectFeeType = 'FIXED_PRICE' | 'RATE' | '%future added value';
const PAID_PROJECT_FEE_TYPE_LABELS: Record<
'FIXED_PRICE' | 'RATE',
string
> =
FIXED_PRICE: 'Fixed Price',
RATE: 'Rate',
;
export const getPaidProjectFeeTypeLabel = (
feeType: PaidProjectFeeType
): string =>
if (hasOwnProperty(PAID_PROJECT_FEE_TYPE_LABELS, feeType))
PAID_PROJECT_FEE_TYPE_LABELS[feeType];
throw new Error('test');
;
https://tsplay.dev/m0LBOm
令人讨厌的是,现在PAID_PROJECT_FEE_TYPE_LABELS
被假定为:
Record<PaidProjectFeeType, unknown> & Record<"FIXED_PRICE" | "RATE", string>
即您无法返回结果,因为X[Y]
的可能值是unknown
。当您需要断言该对象具有所需的属性时,这很有用,但您需要添加更多断言以确保结果是您想要的。
不过,还有更好的方法。
我们将需要两个实用程序:
export const keys = <T extends Record<string, unknown>>(
object: T
): Array<keyof T> =>
return Object.keys(object);
;
keys
为我们提供了对象属性名称的类型化数组。
export const includes = <C extends M, M>(
collection: readonly C[],
member: M
): member is C =>
return collection.includes(member as C);
;
includes
允许断言属性是只读数组的成员。您可以在此blog post 中阅读有关包含的更多信息。
export const keys = <T extends Record<string, unknown>>(
object: T
): Array<keyof T> =>
return Object.keys(object);
;
export const includes = <C extends M, M>(
collection: readonly C[],
member: M
): member is C =>
return collection.includes(member as C);
;
type PaidProjectFeeType = 'FIXED_PRICE' | 'RATE' | '%future added value';
const PAID_PROJECT_FEE_TYPE_LABELS: Record<
'FIXED_PRICE' | 'RATE',
string
> =
FIXED_PRICE: 'Fixed Price',
RATE: 'Rate',
;
export const getPaidProjectFeeTypeLabel = (
feeType: PaidProjectFeeType
): string =>
if (includes(keys(PAID_PROJECT_FEE_TYPE_LABELS), feeType))
return PAID_PROJECT_FEE_TYPE_LABELS[feeType];
throw new Error('test');
;
https://tsplay.dev/N7gLDN
简而言之,这种方法允许我们将feeType
的值缩小到keys(PAID_PROJECT_FEE_TYPE_LABELS)
中存在的值,然后允许我们访问属性值。
这种方法效果最好,但需要注意的是,从技术上讲,keys
实现不是运行时安全的。存在(大部分是理论上的)场景,运行时返回的值与使用 tsc 推断的值不同。
【讨论】:
感谢您抽出宝贵时间回答!最好能解释一下你的答案,而不仅仅是代码。【参考方案3】:包括
Object.keys(x).includes('y');
Array.prototype.includes()
方法确定数组是否在其条目中包含某个值,根据需要返回 true 或 false。
和
Object.keys()
返回一个字符串数组,表示给定对象的所有可枚举属性。
.hasOwnProperty()
和 ES6+ ?.
-optional-chaining like: if (x?.y)
也是非常好的 2020+ 选项。
【讨论】:
【参考方案4】:const data = ["b":1,"c":100,"a":1,"b":1,"c":150,"a":1,"b":2,"c":100,"a":2,"b":1,"c":13]
const result = data.reduce((r, e) =>
r['a'] += (e['a'] ? e['a'] : 0)
r['d'] += (e['b'] ? e['b'] : 0)
r['c'] += (e['c'] ? e['c'] : 0)
return r
, 'a':0, 'd':0, 'c':0)
console.log(result)
`result` a: 4, d: 5, c: 363
【讨论】:
【参考方案5】:ES6+:
ES6+ 上有一个新特性,你可以像下面这样检查它:
if (x?.y)
实际上,解释器会检查x
的存在,然后调用y
,因为在if
括号内会发生强制转换并将x?.y
转换为布尔值。
【讨论】:
如果x.y
存在并且它是一个 falsy 值怎么办。【参考方案6】:
Underscore.js 或 Lodash
if (_.has(x, "y")) ...
:)
【讨论】:
不。它只是Object.prototype.hasOwnProperty.call(x, "y")
的别名。对于数组,我认为您可能需要 Array.prototype.indexOf
、_.indexOf
或 _.contains
【参考方案7】:
为什么不简单:
if (typeof myObject.myProperty == "undefined") alert("myProperty is not defined!");
或者,如果您期望特定类型:
if (typeof myObject.myProperty != "string") alert("myProperty has wrong type or does not exist!");
【讨论】:
因为它不好阅读并且不严格输入。我必须问你:为什么不简单地x.hasOwnProperty('y')
?【参考方案8】:
由于问题是关于属性检查的笨拙,以及一个用于验证函数参数选项对象的常规用例,我想我会提到一种测试多个属性是否存在的无库的简短方法。 免责声明:它确实需要 ECMAScript 5(但 IMO 任何仍在使用 IE8 的人都应该被破坏网络)。
function f(opts)
if(!["req1","req2"].every(opts.hasOwnProperty, opts))
throw new Error("IllegalArgumentException");
alert("ok");
f(req1: 123); // error
f(req1: 123, req2: 456); // ok
【讨论】:
【参考方案9】:对象有属性:
如果您正在测试对象本身(不是其原型链的一部分)上的属性,您可以使用.hasOwnProperty()
:
if (x.hasOwnProperty('y'))
// ......
对象或其原型有一个属性:
您也可以使用in
运算符来测试继承的属性。
if ('y' in x)
// ......
【讨论】:
或者更好——Object.prototype.hasOwnProperty.call(x, 'y')
,这样名为“hasOwnProperty”的属性就不会与检查过程发生冲突;)
甚至更短——.hasOwnProperty.call(x, 'y')
.
eslint.org/docs/rules/no-prototype-builtins【参考方案10】:
我的原始代码的一个功能
if ( typeof(x.y) != 'undefined' ) ...
在某些情况下可能有用的是,无论x
是否存在,使用它都是安全的。使用 gnarf 答案中的任何一种方法,如果有任何疑问,应该首先测试 x
是否存在。
所以也许这三种方法都在一个人的花招中占有一席之地。
【讨论】:
你总是可以使用(x && x.hasOwnProperty('y'))
或(x && 'y' in x)
我同意,对 x 的测试应该是一个单独的案例。还可以生成更好的错误报告。
这对我来说失败了。如果 x 未定义,则 typeof(x.y) 返回 ReferenceError
而不是字符串 'undefined'【参考方案11】:
如果您想知道对象是否在物理上 包含属性@gnarf's,则使用hasOwnProperty
回答即可。
如果您想知道该属性是否存在于任何地方,无论是在对象本身上还是在原型链中,您可以使用in
operator。
if ('prop' in obj)
// ...
例如:
var obj = ;
'toString' in obj == true; // inherited from Object.prototype
obj.hasOwnProperty('toString') == false; // doesn't contains it physically
【讨论】:
【参考方案12】:你可以像这样修剪一下:
if ( x.y !== undefined ) ...
【讨论】:
x = y:undefined
会失败
有人需要区分“未定义”和“定义为未定义”吗?
@darkporter 我有时会这样做 ;)
@jpsimons for and instance "defined to be undefined" 由 Firestore 在保存文档数据时使用。以上是关于JavaScript中如何判断一个对象是不是具有给定的属性的主要内容,如果未能解决你的问题,请参考以下文章
如何检查对象是不是在 JavaScript 中具有特定属性?
如何使用 JavaScript 判断 DOM 对象是不是在窗口外? [复制]