オブジェクトの新しいメソッド

この章では、Object オブジェクトの新しいメソッドを紹介します。

##オブジェクト.is()

ES5 には、2 つの値が等しいかどうかを比較するための演算子が 2 つだけあります。等価演算子 (==) と厳密等価演算子 (===) です。どちらにも欠点があり、前者はデータ型を自動的に変換し、後者の NaN はそれ自体と等しくなく、+0-0 と等しくなります。 JavaScript には、2 つの値が同じである限り、どのような状況でも等しくなるという操作がありません。

ES6 では、この問題を解決するために「同値等価」アルゴリズムを提案しています。 「Object.is」は、このアルゴリズムを導入する新しい方法です。 2 つの値が厳密に等しいかどうかを比較するために使用され、動作は基本的に厳密比較演算子 (===) と同じです。

Object.is('foo', 'foo')
// 真実
Object.is({}, {})
// 間違い

違いは 2 つだけです。1 つは +0-0 と等しくないこと、もう 1 つは NaN がそれ自体と等しいことです。

+0 === -0 //true
NaN === NaN // false

Object.is(+0, -0) // false
Object.is(NaN, NaN) // true

ES5 は、次のコードを通じて「Object.is」をデプロイできます。

Object.defineProperty(Object, 'is', {
  値: 関数(x, y) {
    if (x === y) {
      // +0 が -0 と等しくない場合
      戻り値 x !== 0 || 1 / x === 1 / y;
    }
    //NaNの場合
    戻り x !== x && y !== y;
  }、
  構成可能: true、
  列挙可能: false、
  書き込み可能: true
});

##Object.assign()

基本的な使い方

Object.assign() メソッドはオブジェクトをマージするために使用され、ソース オブジェクト (source) の列挙可能なすべてのプロパティをターゲット オブジェクト (target) にコピーします。

const ターゲット = { a: 1 };

const ソース 1 = { b: 2 };
const ソース 2 = { c: 3 };

Object.assign(ターゲット, ソース1, ソース2);
ターゲット // {a:1、b:2、c:3}

Object.assign() メソッドの最初のパラメータはターゲット オブジェクトで、後続のパラメータはソース オブジェクトです。

ターゲット オブジェクトとソース オブジェクトに同じ名前の属性がある場合、または複数のソース オブジェクトに同じ名前の属性がある場合、後の属性が前の属性を上書きすることに注意してください。

const ターゲット = { a: 1, b: 1 };

const ソース 1 = { b: 2, c: 2 };
const ソース 2 = { c: 3 };

Object.assign(ターゲット, ソース1, ソース2);
ターゲット // {a:1、b:2、c:3}

パラメータが 1 つしかない場合、Object.assign() はパラメータを直接返します。

const obj = {a: 1};
Object.assign(obj) === obj // true

パラメータがオブジェクトでない場合は、まずオブジェクトに変換されてから返されます。

typeof Object.assign(2) // "オブジェクト"

「unknown」と「null」はオブジェクトに変換できないため、パラメータとして使用するとエラーが報告されます。

Object.assign(unknown) // エラーレポート
Object.assign(null) // エラーを報告する

非オブジェクト パラメータがソース オブジェクトの位置に出現する場合 (つまり、最初のパラメータではない場合)、処理規則は異なります。まず、これらのパラメータはオブジェクトに変換されますが、オブジェクトに変換できない場合はスキップされます。これは、最初のパラメータに「未定義」と「null」が含まれていない場合、エラーは報告されないことを意味します。

obj = {a: 1} とします。
Object.assign(obj, unknown) === obj // true
Object.assign(obj, null) === obj // true

他のタイプの値 (数値、文字列、ブール値など) は最初のパラメーターに含まれないため、エラーは報告されません。ただし、文字列が配列の形式でターゲット オブジェクトにコピーされることを除いて、他の値は効果がありません。

const v1 = 'abc';
const v2 = true;
const v3 = 10;

const obj = Object.assign({}, v1, v2, v3);
console.log(obj); // { "0": "a"、"1": "b"、"2": "c" }

上記のコードでは、v1v2v3はそれぞれ文字列、ブール値、数値です。結果として、文字列のみがターゲットオブジェクトに結合されます(文字配列の形式で)。 )、数値およびブール値は無視されます。これは、文字列ラッパー オブジェクトのみが列挙可能なプロパティを生成するためです。

Object(true) // {[[PrimitiveValue]]: true}
Object(10) // {[[PrimitiveValue]]: 10}
Object('abc') // {0: "a", 1: "b", 2: "c", 長さ: 3, [[PrimitiveValue]]: "abc"}

上記のコードでは、ブール値、数値、文字列がそれぞれ対応するパッケージング オブジェクトに変換されており、その元の値がパッケージング オブジェクト [[PrimitiveValue]] の内部プロパティの上にあることがわかります。このプロパティは、コピーされた Object .assign() では使用されません。文字列ラッパー オブジェクトのみが列挙可能なリテラル プロパティを生成し、それらのプロパティはコピーされます。

Object.assign() によってコピーされるプロパティは制限されており、ソース オブジェクト自身のプロパティのみがコピーされ (継承されたプロパティはコピーされません)、列挙不可能なプロパティ (enumerable: false) はコピーされません。

Object.assign({b: 'c'},
  Object.defineProperty({}, 'invisible', {
    列挙可能: false、
    値: 'こんにちは'
  })
)
// { b: 'c' }

上記のコードでは、Object.assign() によってコピーされるオブジェクトには、列挙不可能なプロパティである invisible が 1 つだけあり、このプロパティはコピーされません。

プロパティ名が Symbol 値であるプロパティも Object.assign() によってコピーされます。

Object.assign({ a: 'b' }, { [Symbol('c')]: 'd' })
// { a: 'b'、シンボル(c): 'd' }

注記

(1)浅いコピー

Object.assign() メソッドは、深いコピーではなく、浅いコピーを実行します。つまり、ソース オブジェクトの特定の属性の値がオブジェクトの場合、ターゲット オブジェクトのコピーはこのオブジェクトへの参照を取得します。

const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);

obj1.a.b = 2;
obj2.a.b // 2

上記のコードでは、ソースオブジェクト「obj1」の「a」属性の値がオブジェクトであり、「Object.assign()」でコピーされるのはこのオブジェクトへの参照です。このオブジェクトに対する変更はターゲット オブジェクトに反映されます。

(2) 同名の属性の置換

このようなネストされたオブジェクトの場合、同じ名前のプロパティが見つかると、Object.assign() の処理メソッドは追加ではなく置換を行います。

const ターゲット = { a: { b: 'c', d: 'e' } }
const ソース = { a: { b: 'こんにちは' } }
Object.assign(ターゲット, ソース)
// { a: { b: 'こんにちは' } }

上記のコードでは、target オブジェクトの a 属性は、{ a: { b: 'hello', d: 'e' を取得することなく、sourceオブジェクトのa属性によって完全に置き換えられます。 } }結果。これは通常、開発者が望んでいることではないため、特別な注意が必要です。

一部の関数ライブラリは、ディープ コピー マージを実現できるカスタマイズされたバージョンの Object.assign() (Lodash の _.defaultsDeep() メソッドなど) を提供します。

(3) 配列処理

Object.assign() は配列の処理に使用できますが、配列はオブジェクトとして扱われます。

Object.assign([1, 2, 3], [4, 5])
// [4、5、3]

上記のコードでは、Object.assign() は配列をプロパティ名 0、1、および 2 を持つオブジェクトとして扱うため、ソース配列 4 のプロパティ 0 はターゲット配列 1 のプロパティ 0 を上書きします。

(4) 値関数の処理

Object.assign() は値をコピーすることしかできません。コピーされる値が値関数の場合、評価されてからコピーされます。

const ソース = {
  get foo() { return 1 }
};
const ターゲット = {};

Object.assign(ターゲット, ソース)
// { foo: 1 }

上記のコードでは、「source」オブジェクトの「foo」属性は値関数です。「Object.assign()」は値を取得した後にのみ値をコピーします。

一般的な用途

Object.assign() メソッドには多くの用途があります。

(1) オブジェクトに属性を追加します

クラスポイント{
  コンストラクター(x, y) {
    Object.assign(this, {x, y});
  }
}

上記のメソッドは、「Object.assign()」メソッドを通じて「Point」クラスのオブジェクト インスタンスに「x」属性と「y」属性を追加します。

(2) オブジェクトにメソッドを追加する

Object.assign(SomeClass.prototype, {
  someMethod(arg1, arg2) {
    ・・・
  }、
  anotherMethod() {
    ・・・
  }
});

// 以下の記述と同等
SomeClass.prototype.someMethod = function (arg1, arg2) {
  ・・・
};
SomeClass.prototype.anotherMethod = function () {
  ・・・
};

上記のコードは、オブジェクト属性の簡潔な表記法を使用しており、2 つの関数を中括弧内に直接配置し、assign() メソッドを使用してそれらを SomeClass.prototype に追加しています。

(3)オブジェクトのクローンを作成

関数クローン(原点) {
  return Object.assign({}, 原点);
}

上記のコードは、元のオブジェクトを空のオブジェクトにコピーし、それによって元のオブジェクトのクローンを取得します。

ただし、このメソッドを使用してクローンを作成する場合、元のオブジェクトが継承する値ではなく、元のオブジェクト自体の値のみクローンを作成できます。継承チェーンを維持したい場合は、次のコードを使用できます。

関数クローン(原点) {
  オリジンプロト = Object.getPrototypeOf(origin); にします。
  return Object.assign(Object.create(originProto), 原点);
}

(4) 複数のオブジェクトを結合する

複数のオブジェクトを 1 つのオブジェクトに結合します。

const マージ =
  (ターゲット, ...ソース) => Object.assign(ターゲット, ...ソース);

マージ後に新しいオブジェクトを返したい場合は、空のオブジェクトをマージするように上記の関数を書き直すことができます。

const マージ =
  (...ソース) => Object.assign({}, ...ソース);

(5) 属性のデフォルト値を指定

const デフォルト = {
  ログレベル: 0、
  出力形式: 'html'
};

関数 processContent(オプション) {
  options = Object.assign({}, DEFAULTS, options);
  console.log(オプション);
  // ...
}

上記のコードでは、「DEFAULTS」オブジェクトはデフォルト値であり、「options」オブジェクトはユーザーが指定したパラメータです。 Object.assign() メソッドは、DEFAULTSoptions を新しいオブジェクトにマージします。両方に同じ名前のプロパティがある場合、options のプロパティ値は DEFAULTS のプロパティ値を上書きします。

浅いコピーの問題により、DEFAULTS オブジェクトと options オブジェクトのすべてのプロパティの値は単純型の中で最も優れており、別のオブジェクトを指していないことに注意してください。それ以外の場合、DEFAULTS オブジェクトのこのプロパティはおそらく効果がありません。

const デフォルト = {
  URL: {
    ホスト: 'example.com'、
    ポート: 7070
  }、
};

processContent({ url: {ポート: 8000} })
// {
// URL: {ポート: 8000}
// }

上記のコードの本来の目的は、「url.host」を変更せずに「url.port」を 8000 に変更することです。実際の結果は、options.urlDEFAULTS.url を上書きするため、url.host は存在しません。

Object.getOwnPropertyDescriptors()

ES5 の Object.getOwnPropertyDescriptor() メソッドは、オブジェクト プロパティの記述子を返します。 ES2017 では、指定されたオブジェクトのすべての独自のプロパティ (非継承プロパティ) の説明オブジェクトを返す Object.getOwnPropertyDescriptors() メソッドが導入されました。

const obj = {
  ふー: 123get bar() { return 'abc' }
};

Object.getOwnPropertyDescriptors(obj)
// { foo:
// { 値: 123,
// 書き込み可能: true,
// 列挙可能: true,
// 設定可能: true },
// バー:
// { get: [関数: get bar],
// 設定: 未定義、
// 列挙可能: true,
// 設定可能: true } }

上記のコードでは、Object.getOwnPropertyDescriptors() メソッドはオブジェクトを返します。元のオブジェクトのすべてのプロパティ名はオブジェクトのプロパティ名であり、対応するプロパティ値はプロパティの説明オブジェクトです。

このメソッドの実装は非常に簡単です。

関数 getOwnPropertyDescriptors(obj) {
  const 結果 = {};
  for (Reflect.ownKeys(obj) のキーを許可) {
    result[key] = Object.getOwnPropertyDescriptor(obj, key);
  }
  結果を返します。
}

このメソッドを導入する目的は、主に Object.assign()get 属性と set 属性を正しくコピーできないという問題を解決することです。

const ソース = {
  set foo() {
    console.log(値);
  }
};

const ターゲット 1 = {};
Object.assign(ターゲット1, ソース);

Object.getOwnPropertyDescriptor(target1, 'foo')
// { 値: 未定義,
// 書き込み可能: true,
// 列挙可能: true,
// 設定可能: true }

上記のコードでは、「source」オブジェクトの「foo」プロパティの値は代入関数であり、「Object.assign」メソッドはこのプロパティを「target1」オブジェクトにコピーし、その結果、プロパティは「未定義」になります。これは、「Object.assign」メソッドは常にプロパティの値をコピーしますが、その背後にある代入メソッドやゲッター メソッドはコピーしないためです。

このとき、Object.getOwnPropertyDescriptors() メソッドと Object.defineProperties() メソッドを使用することで正しくコピーできます。

const ソース = {
  set foo() {
    console.log(値);
  }
};

const ターゲット 2 = {};
Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source));
Object.getOwnPropertyDescriptor(target2, 'foo')
// { 取得: 未定義,
// set: [関数: set foo],
// 列挙可能: true,
// 設定可能: true }

上記のコードでは、2 つのオブジェクトをマージするロジックを関数として記述することができます。

constshallowMerge = (ターゲット, ソース) => Object.defineProperties(
  ターゲット、
  Object.getOwnPropertyDescriptors(ソース)
);

Object.getOwnPropertyDescriptors() メソッドのもう 1 つの用途は、Object.create() メソッドとともに使用して、オブジェクト プロパティを新しいオブジェクトに複製することです。これは浅いコピーです。

const clone = Object.create(Object.getPrototypeOf(obj),
  Object.getOwnPropertyDescriptors(obj));

// または

constshallowClone = (obj) => Object.create(
  Object.getPrototypeOf(obj)、
  Object.getOwnPropertyDescriptors(obj)
);

上記のコードはオブジェクト「obj」のクローンを作成します。

さらに、「Object.getOwnPropertyDescriptors()」メソッドを使用すると、あるオブジェクトが別のオブジェクトを継承できます。以前は、別のオブジェクトの継承は次のように記述されることがよくありました。

const obj = {
  __proto__: プロット、
  ふー: 123、
};

ES6 では、「proto」はブラウザにデプロイするだけでよく、他の環境にデプロイする必要はないと規定されています。 proto を削除すると、上記のコードは次のように変更されます。

const obj = Object.create(prot);
obj.foo = 123;

// または

const obj = Object.assign(
  Object.create(prot)、
  {
    ふー: 123、
  }
);

Object.getOwnPropertyDescriptors() を使用すると、別の記述方法があります。

const obj = Object.create(
  プロット、
  Object.getOwnPropertyDescriptors({
    ふー: 123、
  })
);

Object.getOwnPropertyDescriptors() を使用して Mixin モードを実装することもできます。

let mix = (オブジェクト) => ({
  条件: (...mixins) => mixins.reduce(
    (c, mixin) => Object.create(
      c、Object.getOwnPropertyDescriptors(ミックスイン)
    )、 物体)
});

// 複数のミックスインの例
a = {a: 'a'}; とします。
b = {b: 'b'}; とします。
let c = {c: 'c'};
d = mix(c).with(a, b); とします。

d.c // "c"
d.b // "b"
d.a // 「あ」

上記のコードは、オブジェクト c に混合されるオブジェクト ab の操作を表す新しいオブジェクト d を返します。

完全を期すため、Object.getOwnPropertyDescriptors() が標準規格に入った後、Reflect.getOwnPropertyDescriptors() メソッドが将来追加される予定です。

__proto__ 属性、Object.setPrototypeOf()、Object.getPrototypeOf()

JavaScript 言語でのオブジェクトの継承は、プロトタイプ チェーンを通じて実装されます。 ES6 は、プロトタイプ オブジェクトを操作するためのメソッドをさらに提供します。

__proto__ 属性

__proto__ 属性 (前後 2 つのアンダースコア) は、現在のオブジェクトのプロトタイプ オブジェクト (prototype) の読み取りまたは設定に使用されます。現在、すべてのブラウザ (IE11 を含む) がこのプロパティをデプロイしています。

// es5の書き方
const obj = {
  メソッド: function() { ... }
};
obj.__proto__ = someOtherObj;

// es6の書き方
var obj = Object.create(someOtherObj);
obj.method = function() { ... };

この属性は ES6 の本文には書かれておらず、付録に書かれています。その理由は、__proto__ の前後にある二重アンダースコアが、それが正式な外部 API ではなく、本質的に内部プロパティであることを示しているだけだからです。ブラウザの幅広いサポートにより、ES6 にのみ追加されました。この標準では、ブラウザーのみがこの属性をデプロイする必要があり、他のオペレーティング環境では必ずしもこの属性をデプロイする必要はなく、新しいコードではこの属性が存在しないと想定することが最善であると明確に規定されています。したがって、セマンティックの観点や互換性の観点に関係なく、この属性を使用せず、代わりに次の Object.setPrototypeOf() (書き込み操作)、Object.getPrototypeOf() (読み取り操作) を使用してください。 )、代わりに Object.create() (操作の作成) を使用します。

実装面では、__proto__Object.prototype.__proto__を呼び出しており、具体的な実装は以下の通りです。

Object.defineProperty(Object.prototype, '__proto__', {
  得る() {
    let _thisObj = オブジェクト(this);
    戻り値 Object.getPrototypeOf(_thisObj);
  }、
  set(プロト) {
    if (this === 未定義 || this === null) {
      新しい TypeError() をスローします。
    }
    if (!isObject(this)) {
      未定義を返します。
    }
    if (!isObject(proto)) {
      未定義を返します。
    }
    let status = Reflect.setPrototypeOf(this, proto);
    if (!ステータス) {
      新しい TypeError() をスローします。
    }
  }、
});

関数 isObject() {
  オブジェクト(値) === 値を返します。
}

オブジェクト自体が __proto__ 属性を展開する場合、この属性の値はオブジェクトのプロトタイプになります。

Object.getPrototypeOf({ __proto__: null })
// null

Object.setPrototypeOf()

Object.setPrototypeOf メソッドは、オブジェクトのプロトタイプ オブジェクト (プロトタイプ) を設定し、パラメータ オブジェクトそのものを返すために使用される __proto__ と同じ機能を持ちます。これは、ES6 でプロトタイプ オブジェクトを設定するために公式に推奨されている方法です。

// フォーマット
Object.setPrototypeOf(オブジェクト, プロトタイプ)

// 使用法
const o = Object.setPrototypeOf({}, null);

このメソッドは以下の関数と同等です。

関数 setPrototypeOf(obj, proto) {
  obj.__proto__ = プロト;
  オブジェクトを返します。
}

以下に例を示します。

プロト = {} にします。
obj = { x: 10 }; とします。
Object.setPrototypeOf(obj, proto);

プロト.y = 20;
proto.z = 40;

obj.x // 10
obj.y // 20
obj.z // 40

上記のコードは、proto オブジェクトを obj オブジェクトのプロトタイプとして設定するため、proto オブジェクトのプロパティを obj オブジェクトから読み取ることができます。

最初のパラメータがオブジェクトでない場合は、自動的にオブジェクトに変換されます。ただし、最初のパラメータが返されるため、この操作は何の効果もありません。

Object.setPrototypeOf(1, {}) === 1 // true
Object.setPrototypeOf('foo', {}) === 'foo' // true
Object.setPrototypeOf(true, {}) === true // true

unknownnull はオブジェクトに変換できないため、最初のパラメータが unknownnull の場合はエラーが報告されます。

Object.setPrototypeOf(未定義, {})
// TypeError: null または未定義で呼び出された Object.setPrototypeOf

Object.setPrototypeOf(null, {})
// TypeError: null または未定義で呼び出された Object.setPrototypeOf

Object.getPrototypeOf()

このメソッドは Object.setPrototypeOf メソッドと一致し、オブジェクトのプロトタイプ オブジェクトを読み取るために使用されます。

Object.getPrototypeOf(obj);

以下に例を示します。

関数 Rectangle() {
  // ...
}

const rec = new Rectangle();

Object.getPrototypeOf(rec) === Rectangle.prototype
// 真実

Object.setPrototypeOf(rec, Object.prototype);
Object.getPrototypeOf(rec) === Rectangle.prototype
// 間違い

パラメータがオブジェクトでない場合は、自動的にオブジェクトに変換されます。

// Object.getPrototypeOf(Number(1)) と同等
Object.getPrototypeOf(1)
//数値 {[[PrimitiveValue]]: 0}

// Object.getPrototypeOf(String('foo')) と同等
Object.getPrototypeOf('foo')
// 文字列 {length: 0, [[PrimitiveValue]]: ""}

// Object.getPrototypeOf(Boolean(true)) と同等
Object.getPrototypeOf(true)
// ブール値 {[[PrimitiveValue]]: false}

Object.getPrototypeOf(1) === Number.prototype // true
Object.getPrototypeOf('foo') === String.prototype // true
Object.getPrototypeOf(true) === Boolean.prototype // true

パラメータが「未定義」または「null」の場合、オブジェクトに変換できないため、エラーが報告されます。

Object.getPrototypeOf(null)
// TypeError: 未定義または null をオブジェクトに変換できません

Object.getPrototypeOf(未定義)
// TypeError: 未定義または null をオブジェクトに変換できません

Object.keys()、Object.values()、Object.entries()

###Object.keys()

ES5 では、「Object.keys」メソッドが導入されました。このメソッドは、パラメータ オブジェクト自体のすべての列挙可能なプロパティ (継承されたプロパティを除く) のキーをメンバーとする配列を返します。

var obj = { foo: 'bar', baz: 42 };
オブジェクト.キー(obj)
// ["foo", "baz"]

ES2017 導入 オブジェクトの走査の補足として Object.keys に一致する Object.valuesObject.entries の使用方法「for...of」ループ内。

let {キー、値、エントリ} = オブジェクト;
obj = { a: 1, b: 2, c: 3 }; とします。

for (let key of key(obj)) {
  console.log(key); // 'a'、'b'、'c'
}

for (values(obj) の値を許可) {
  console.log(値); // 1、2、3
}

for (let [キー, 値] of events(obj)) {
  console.log([キー, 値]); // ['a', 1], ['b', 2], ['c', 3]
}

Object.values()

Object.values メソッドは、パラメータ オブジェクト自体のすべての列挙可能なプロパティ (継承されたプロパティを除く) のキー値をメンバーとする配列を返します。

const obj = { foo: 'bar', baz: 42 };
オブジェクト.値(obj)
// ["バー", 42]

返された配列のメンバーの順序は、この章の「属性トラバーサル」セクションで紹介された配置規則と一致しています。

const obj = { 100: 'a'2: 'b'7: 'c' };
オブジェクト.値(obj)
// ["b", "c", "a"]

上記のコードでは、属性名が数値である属性を数値の小さい順にたどっていくので、返される順序は「b」、「c」、「a」になります。

Object.values は、オブジェクト自体の走査可能なプロパティのみを返します。

const obj = Object.create({}, {p: {値: 42}});
Object.values(obj) // []

上記のコードでは、Object.create メソッドの 2 番目のパラメータによって追加されたオブジェクト属性 (属性 p) は、明示的に宣言されていない場合、デフォルトでは走査できません。これは、p の属性が enumerable を記述するためです。オブジェクトの デフォルトはfalse です。Object.valuesはこのプロパティを返しません。enumerabletrue に変更されている限り、Object.valuesは属性p` の値を返します。

const obj = Object.create({}, {p:
  {
 値: 42、
 列挙可能: true
 }
});
Object.values(obj) // [42]

Object.values は、プロパティ名が Symbol value であるプロパティをフィルタリングします。

Object.values({ [Symbol()]: 123, foo: 'abc' });
//['abc']

Object.values メソッドのパラメータが文字列の場合、個々の文字の配列が返されます。

Object.values('foo')
// ['f', 'o', 'o']

上記のコードでは、まず文字列が配列のようなオブジェクトに変換されます。文字列の各文字はオブジェクトの属性です。したがって、「Object.values」は、個々の文字の配列である各プロパティのキー値を返します。

パラメータがオブジェクトではない場合、Object.values は最初にそれをオブジェクトに変換します。数値とブール値のラッパー オブジェクトのため、継承されていないプロパティはインスタンスに追加されません。したがって、「Object.values」は空の配列を返します。

Object.values(42) // []
Object.values(true) // []

###Object.entries()

Object.entries() メソッドは、パラメータ オブジェクト自体のすべての列挙可能なプロパティ (継承されたプロパティを除く) のキーと値のペアをメンバーとする配列を返します。

const obj = { foo: 'bar', baz: 42 };
オブジェクト.エントリ(obj)
// [ ["foo", "bar"], ["baz", 42] ]

戻り値が異なることを除けば、このメソッドの動作は基本的に Object.values と同じです。

元のオブジェクトのプロパティ名が Symbol 値である場合、そのプロパティは無視されます。

Object.entries({ [Symbol()]: 123, foo: 'abc' });
// [ [ 'foo', 'abc' ] ]

上記のコードでは、元のオブジェクトには 2 つの属性があり、Object.entries は属性名が Symbol 値ではない属性のみを出力します。将来的には、オブジェクト自体のすべてのプロパティを返す Reflect.ownEntries() メソッドが登場する可能性があります。

Object.entries の基本的な使用法は、オブジェクトのプロパティを反復処理することです。

let obj = { 1 つ: 12 つ: 2 };
for (let [k, v] of Object.entries(obj)) {
  コンソール.log(
    `${JSON.stringify(k)}: ${JSON.stringify(v)}`
  );
}
// "1": 1
// "2": 2

Object.entries メソッドのもう 1 つの用途は、オブジェクトを実際の Map 構造に変換することです。

const obj = { foo: 'bar', baz: 42 };
const map = new Map(Object.entries(obj));
map // マップ { foo: "バー", baz: 42 }

Object.entries メソッドを自分で実装するのは非常に簡単です。

//ジェネレーター関数のバージョン
function* エントリ(obj) {
  for (Object.keys(obj) のキーを許可) {
    yield [キー, obj[キー]];
  }
}

// ジェネレーター関数以外のバージョン
関数エントリ(obj) {
  arr = []; とします。
  for (Object.keys(obj) のキーを許可) {
    arr.push([キー, obj[キー]]);
  }
  arrを返します。
}

Object.fromEntries()

Object.fromEntries() メソッドは Object.entries() の逆演算であり、キーと値のペアの配列をオブジェクトに変換するために使用されます。

Object.fromEntries([
  ['フー', 'バー'],
  [「バズ」、42]
])
// { foo: "バー", baz: 42 }

このメソッドの主な目的は、キーと値のペアのデータ構造をオブジェクトに復元することであるため、Map 構造をオブジェクトに変換するのに特に適しています。

//例1
const エントリ = 新しい Map([
  ['フー', 'バー'],
  [「バズ」、42]
]);

Object.fromEntries(エントリ)
// { foo: "バー", baz: 42 }

//例2
const map = new Map().set('foo', true).set('bar', false);
Object.fromEntries(マップ)
// { foo: true、bar: false }

このメソッドの使用法の 1 つは、URLSearchParams オブジェクトを使用してクエリ文字列をオブジェクトに変換することです。

Object.fromEntries(new URLSearchParams('foo=bar&baz=qux'))
// { foo: "バー"、baz: "qux" }

##Object.hasOwn()

JavaScript オブジェクトのプロパティは、独自のプロパティと継承されたプロパティの 2 種類に分類されます。オブジェクト インスタンスには、プロパティがネイティブ プロパティかどうかを判断できる hasOwnProperty() メソッドがあります。 ES2022 は、Object オブジェクトに新しい静的メソッド Object.hasOwn() を追加します。これは、それが独自のものであるかどうかも判断できます。財産。 。

Object.hasOwn() は 2 つのパラメータを受け取ることができます。1 つ目は判定対象のオブジェクト、2 つ目はプロパティ名です。

const foo = Object.create({ a: 123 });
foo.b = 456;

Object.hasOwn(foo, 'a') // false
Object.hasOwn(foo, 'b') // true

上記の例では、オブジェクト foo のプロパティ a は継承プロパティであり、プロパティ b はネイティブ プロパティです。 Object.hasOwn() は、プロパティ a に対して false を返し、プロパティ b に対して true を返します。

Object.hasOwn() の利点の 1 つは、Object.prototype を継承しないオブジェクトについてはエラーが報告されないのに対し、hasOwnProperty() はエラーを報告することです。

const obj = Object.create(null);

obj.hasOwnProperty('foo') // エラーレポート
Object.hasOwn(obj, 'foo') // false

上記の例では、「Object.create(null)」によって返されるオブジェクト「obj」にはプロトタイプがなく、プロパティも継承しません。これにより、「obj.hasOwnProperty()」を呼び出すときにエラーが報告されますが、「Object」は返されません。 .hasOwn()` はこの状況を正しく処理できます。


作者: wangdoc

アドレス: https://wangdoc.com/

ライセンス: クリエイティブ・コモンズ 3.0