390 Stimmen

Wie man feststellt, ob ein Objekt eine bestimmte Eigenschaft in JavaScript hat

Wie kann ich feststellen, ob ein Objekt x hat eine definierte Eigenschaft y unabhängig vom Wert von x.y ?

Ich verwende derzeit

if (typeof(x.y) !== 'undefined')

aber das scheint ein bisschen klobig zu sein. Gibt es einen besseren Weg?

6voto

J Rod Punkte 576

enthält

Object.keys(x).includes('y');

Die Array.prototype.includes() bestimmt, ob ein Array einen bestimmten Wert enthält, und gibt je nach Fall true oder false zurück.

Object.keys() gibt ein Array von Strings zurück, die alle aufzählbaren Eigenschaften des angegebenen Objekts darstellen.

.hasOwnProperty() und die ES6+ ?. -optionale Verkettung wie: if (x?.y) sind ebenfalls sehr gute Optionen für 2020+.

3voto

ES6+:

Es gibt eine neue Funktion in ES6+, die Sie wie unten beschrieben überprüfen können:

if (x?.y)

Eigentlich prüft der Interpret das Vorhandensein von x und rufen dann die y und wegen des Hineinlegens if Klammern die Nötigung geschieht und x?.y in einen booleschen Wert umgewandelt.

3voto

Ran Turner Punkte 8004

Zusätzlich zu den anderen Antworten möchte ich vorschlagen, die Object.hasOwn() Methode zur Überprüfung, ob das angegebene Objekt die angegebene Eigenschaft als eigene Eigenschaft hat (d.h. auf dem Objekt selbst), können Sie die neue Object.hasOwn() die eine statische Methode ist, die true zurückgibt, wenn das angegebene Objekt die angegebene Eigenschaft als eigene Eigenschaft hat. Ist die Eigenschaft geerbt oder existiert sie nicht, gibt die Methode false zurück.

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

Es wird empfohlen, diese Methode über die Object.hasOwnProperty() weil es auch für Objekte funktioniert, die mit Hilfe von Object.create(null) und für Objekte, die die geerbte hasOwnProperty() Methode. Obwohl es möglich ist, diese Art von Problemen zu lösen, indem man Object.prototype.hasOwnProperty() auf ein externes Objekt, Object.hasOwn() diese Probleme zu überwinden, wird daher bevorzugt (siehe Beispiele unten)

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
}

Mehr über Object.hasOwn finden Sie hier: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn

Browser-Kompatibilität - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn#browser_compatibility

Die Überprüfung, ob die angegebene Eigenschaft auf dem Objekt selbst oder weiter oben in der Prototypenkette existiert, könnte über die in Operator, wie in anderen Antworten vorgeschlagen.

1voto

stt Punkte 222

Da Frage war in Bezug auf Klobigkeit der Eigenschaft Überprüfung, und eine regelmäßige Usecase für die Validierung von Funktion Argument Optionen Objekte, dachte ich, ich würde erwähnen, eine Bibliothek-freie kurze Weise der Prüfung der Existenz von mehreren Eigenschaften. Disclaimer: Es erfordert ECMAScript 5 (aber IMO jeder, der noch IE8 verwendet, verdient ein kaputtes Web).

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

1voto

Gajus Punkte 61796

Im Gegensatz zu anderen Beispielen in diesem Thread wird in dieser Implementierung nur behauptet, dass das Objekt eine Eigenschaft hat, auf die wir prüfen wollen.

const hasOwnProperty = <X extends {}, Y extends PropertyKey>(
  object: X,
  property: Y
): object is Record<Y, unknown> & X => {
  return object.hasOwnProperty(property);
};

Hier ein Beispiel, wie ein Zweig mit der gewünschten Eigenschaft identifiziert werden kann.

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

Der Haken an der Sache ist, dass nun PAID_PROJECT_FEE_TYPE_LABELS angenommen wird:

Record<PaidProjectFeeType, unknown> & Record<"FIXED_PRICE" | "RATE", string>

d.h. Sie können das Ergebnis nicht zurückgeben, weil ein möglicher Wert von X[Y] es unknown . Dies ist nützlich, wenn Sie behaupten müssen, dass ein Objekt eine gewünschte Eigenschaft hat, aber Sie müssen weitere Behauptungen hinzufügen, um sicherzustellen, dass das Ergebnis Ihren Vorstellungen entspricht.

Es gibt jedoch einen besseren Weg.

Wir brauchen zwei Versorgungsunternehmen:

export const keys = <T extends Record<string, unknown>>(
  object: T
): Array<keyof T> => {
  return Object.keys(object);
};

keys gibt uns ein typisiertes Array von Objekteigenschaftsnamen.

export const includes = <C extends M, M>(
  collection: readonly C[],
  member: M
): member is C => {
  return collection.includes(member as C);
};

includes erlaubt es zu behaupten, dass eine Eigenschaft Mitglied eines schreibgeschützten Arrays ist. Sie können mehr über Includes in diesem Artikel lesen Blogbeitrag .

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

Kurz gesagt, dieser Ansatz ermöglicht es uns, die feeType Wert zu den Werten in keys(PAID_PROJECT_FEE_TYPE_LABELS) die uns dann den Zugriff auf den Eigenschaftswert ermöglicht.

Dieser Ansatz funktioniert am besten, allerdings mit dem Vorbehalt, dass technisch keys Implementierung ist nicht laufzeitsicher. Es gibt ein (meist theoretisches) Szenario, in dem die zur Laufzeit zurückgegebenen Werte sich von den mit tsc abgeleiteten unterscheiden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X