JavaScript プリミティブデータ型シンボルの詳細な説明

JavaScript プリミティブデータ型シンボルの詳細な説明

導入

シンボル変数を作成する最も簡単な方法は、Symbol() 関数を使用することです。 sysmbol 変数には 2 つの特別な機能があります。

1. オブジェクト属性名として使用できます。オブジェクト属性名として使用できるのは、文字列型とシンボル型のみです。

2. 2 つのシンボルが同じ値を持つことはありません。

const シンボル1 = シンボル();
const シンボル2 = シンボル();

シンボル1 === シンボル2; // 偽

定数obj = {};
obj[symbol1] = 'こんにちは';
obj[symbol2] = 'ワールド';

obj[シンボル1]; // 'こんにちは'
obj[symbol2]; // 'ワールド'

Symbol() を呼び出すとオブジェクトのように見えますが、シンボルは実際には JavaScript のプリミティブ データ型です。 Symbol をコンストラクターとして new を使用すると、エラーが発生します。

const シンボル1 = シンボル();

typeof symbol1; // 'シンボル'
symbol1 instanceof Object; // false

// "TypeError: シンボルはコンストラクタではありません" をスローします
新しいシンボル();

説明

Symbol() 関数は、文字列の説明という 1 つのパラメータのみを取ります。この文字列パラメータの唯一の用途は、デバッグを支援すること、つまりその toString() 値です。ただし、同じ説明を持つ 2 つのシンボルは等しくないことに注意してください。

const symbol1 = Symbol('私のシンボル');
const symbol2 = Symbol('私のシンボル');

シンボル1 === シンボル2; // 偽
console.log(symbol1); // 'Symbol(私のシンボル)'

グローバル シンボル レジストリがあり、Symbol.for() で作成されたシンボルはこのレジストリに追加され、その説明を使用してインデックスが付けられます。つまり、Symbol.for() を使用して同じ説明を持つ 2 つのシンボルを作成した場合、それらは等しくなります。

const symbol1 = Symbol.for('test');
const symbol2 = Symbol.for('test');

シンボル1 === シンボル2; // 真
console.log(symbol1); // 'シンボル(テスト)'

一般的に、名前の競合が発生する可能性があるため、特別な理由がない限り、グローバル レジストリを使用しないでください。

名前の競合

JavaScript には組み込みシンボルがあり、ES6 では Symbol.iterator です。 Symbol.iterator 関数を持つオブジェクトは反復可能オブジェクトと呼ばれ、オブジェクトに対して for/of ループを使用できることを意味します。

定数フィボナッチ = {
  [シンボル.イテレータ]: 関数*() {
    a = 1 とします。
    b = 1 とします。
    温度を調節する

    b を生成します。

    (真)の間{
      温度 = ;
      a = a + b;
      b = 温度;
      b を生成します。
    }
  }
};

// 100 未満のすべてのフィボナッチ数を出力します
(フィボナッチの定数x) {
  (x >= 100)の場合{
    壊す;
  }
  コンソールログ(x);
}

ここで文字列ではなく Symbol.iterator を使用するのはなぜですか? Symbol.iterator が使用されていないと仮定すると、反復可能なオブジェクトには、次の反復可能なオブジェクト クラスのように、'iterator' という名前の文字列属性が必要です。

クラス MyClass {
  コンストラクタ(obj) {
    オブジェクトに代入します。
  }

  イテレータ() {
    const keys = Object.keys(this);
    i = 0 とします。
    戻り値 (関数*() {
      i >= キーの長さの場合{
        戻る;
      }
      keys[i++]を生成します。
    })();
  }
}

MyClass のインスタンスは反復可能なオブジェクトであり、オブジェクトのプロパティを走査できます。しかし、上記のクラスには潜在的な欠陥があります。悪意のあるユーザーが、反復子プロパティを持つオブジェクトを MyClass コンストラクターに渡すとします。

const obj = new MyClass({ iterator: '関数ではありません' });

このように、obj に対して for/of を使用すると、JavaScript は TypeError: obj is not iterable 例外をスローします。オブジェクトに渡されたイテレータ関数がクラスのイテレータ プロパティをオーバーライドしていることがわかります。これは、プロトタイプ汚染のセキュリティ問題に多少似ています。ユーザーデータを無意識にコピーすると、__proto__ やコンストラクターなどの一部の特殊なプロパティに問題が発生します。

ここで重要な点は、シンボルがオブジェクトの内部データとユーザー データを分離して保持することです。 sysmbol は JSON で表現できないため、不適切な Symbol.iterator プロパティを持つデータを Express API に渡すことについて心配する必要はありません。さらに、Mongoose モデルなど、組み込み関数とユーザー データを混在させるオブジェクトの場合、シンボルを使用して、ユーザー データが組み込み属性と競合しないようにすることができます。

私有財産

2 つのシンボルは等しくないため、JavaScript でプライベート プロパティをシミュレートするために簡単に使用できます。シンボルは Object.keys() の結果には表示されないため、シンボルを明示的にエクスポートするか、Object.getOwnPropertySymbols() を使用して取得しない限り、他のコードはこのプロパティにアクセスできません。

関数 getObj() {
  const シンボル = シンボル('テスト');
  定数obj = {};
  obj[シンボル] = 'テスト';
  obj を返します。
}

定数obj = getObj();

オブジェクト.keys(obj); // []

// このシンボルへの参照がない限り、このプロパティにアクセスすることはできません obj[Symbol('test')]; // undefined

// getOwnPropertySymbols() を使用して、シンボルへの参照を取得します。const [symbol] = Object.getOwnPropertySymbols(obj);
obj[シンボル]; // 'テスト'

もう 1 つの理由は、シンボルが JSON.stringify() の結果に表示されないことです。より正確に言うと、JSON.stringify() はシンボルの属性名と属性値を無視します。

const シンボル = シンボル('テスト');
const obj = { [シンボル]: 'テスト', テスト: シンボル };

JSON.stringify(obj); // "{}"

要約する

オブジェクトの内部状態を表すためにシンボルを使用すると、ユーザー データとプログラムの状態を効果的に分離できます。これにより、内部プロパティを「$」で始めるなどの特定の命名規則は必要なくなります。次回プライベート プロパティを定義する必要がある場合は、Symbol 型を試してください。

上記は、JavaScript プリミティブ データ型 Symbol の詳細な説明です。JavaScript プリミティブ データ型 Symbol の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • JavaScript のプリミティブデータ型 Null と Undefined の詳細な説明
  • JavaScript の 2 つの新しいプリミティブ データ型 (レコードとタプル) の詳細な説明

<<:  mysql8.0.0 winx64.zip 解凍バージョンのインストールと設定のチュートリアル

>>:  Linux でローカル コンピューターとリモート サーバーのポートが接続されているかどうかを確認する方法

推薦する

MySQLデータベースのマスタースレーブレプリケーションの原理と機能の分析

目次1. データベースのマスター/スレーブ分類: 2. MySQL マスタースレーブの紹介3. マス...

DOSBox を起動後に自動的にコマンドを実行する方法

DOSBox を使用すると、Windows で DOS をシミュレートし、楽しい作業を行うことができ...

k8s に ingress-nginx をデプロイする手順

目次序文1. Ingressの展開と構成2. httpsを使用する序文k8sクラスタサービスがデプロ...

我々は自らの力でIE6を絶滅に追い込んでいる

実際、IE6 が本当にいつ消滅するのか私たちは毎日疑問に思っていますが、2001 年のリリース以来、...

テキストスクロール後の自動停止効果の例

効果は非常にシンプルで、次のコードを自分のページにコピーして実行するだけです。コードをコピーコードは...

Avue でカスタム検索バーを実装し、検索イベントをクリアする実践

目次1. 検索バーの内容をカスタマイズする2. 検索ボタンをカスタマイズする検索バーをカスタマイズし...

Linux で LVGL エミュレータをコンパイルする際のエラーの解決方法

目次1. エラー現象2. エラー分析3. エラー解決1. エラー現象仮想マシンでLVGLエミュレータ...

Prometheus を使用して、MySQL の自動増分主キーの残りの使用可能パーセンテージをカウントします。

最近、本番環境のデータベースがログデータを狂ったように書き込み、主キー値のオーバーフローを引き起こし...

一般的な MySQL 関数の例の概要 [集計関数、文字列、数値、時刻と日付の処理など]

この記事では、よく使用される MySQL 関数について説明します。ご参考までに、詳細は以下の通りです...

MySQL マスタースレーブレプリケーションプロセスの詳細な説明

1. マスタースレーブレプリケーションとは何ですか?マスター データベースの DDL および DML...

MySQL 8.0.12 のインストールと環境変数の設定チュートリアル (Win10 の場合)

Windows 10 プラットフォームでの MySQL のインストール、構成、起動、ログイン、環境...

Tomcat を使用して Centos 環境に SpringBoot WAR パッケージをデプロイする

戦争パッケージを準備する1. 既存のSpringBootプロジェクトを準備し、pomに依存関係を追加...

Linux で ping は成功するがポートが利用できない問題を解決する方法

ping は成功したがポートにアクセスできない場合のポート可用性検出の説明ポート可用性検出ツールの紹...

CSS の無効な行の高さ設定の問題の解決策

CSS の無効な行の高さ設定についてまず、次のコード文字列を記述します。 <!DOCTYPE ...

Linux での tcpdump コマンド例の詳細な説明

序文簡単に言えば、tcpdump は、ネットワーク上のトラフィックをダンプし、ユーザーの定義に従って...