ホームページ  >  記事  >  ウェブフロントエンド  >  なぜシンボル型があるのでしょうか?使い方?

なぜシンボル型があるのでしょうか?使い方?

青灯夜游
青灯夜游転載
2022-03-22 11:04:512715ブラウズ

シンボルとは何ですか?なぜそんな事があるのでしょうか?次の記事では、JavaScript の Symbol 型について紹介し、その使い方について説明します。

なぜシンボル型があるのでしょうか?使い方?

#シンボルとは何ですか?なぜそんな事があるのでしょうか?

Symbol (シンボル) は、ES6 で追加された新しいデータ型です。シンボルはプリミティブ値 (基礎となるデータ型) であり、シンボル インスタンスは一意で不変です。これは、一意にマークを付けるために使用され、文字列以外の形式でオブジェクト属性として使用されるために生成され、オブジェクト属性が一意の識別子を使用し、属性の競合の危険がないようにするためです。 [関連する推奨事項: JavaScript 学習チュートリアル]

使用法

1. 基本的な使用法

記号Symbol() 関数を使用して初期化する必要があります。シンボル自体はプリミティブ型であるため、typeof 演算子はシンボルごとにシンボルを返します。

let sym = Symbol();
console.log(typeof sym); // symbol

Symbol() 関数は、説明する文字列パラメータを受け取ることができ、この文字列を使用してコードをデバッグできます。ただし、複数の Symbol() 関数が同じパラメータを受け入れたとしても、それらの値は等しくないことに注意してください。

let genericSymbol = Symbol();
let otherGenericSymbol = Symbol();
let fooSymbol = Symbol("foo");
let otherFooSymbol = Symbol("foo");

console.log(genericSymbol == otherGenericSymbol); // false
console.log(fooSymbol == otherFooSymbol); // false

2. グローバル シンボル レジストリを使用する

コード内の複数の場所で同じシンボル インスタンスを使用する必要がある場合は、文字列を渡すことができます。 Symbol.for() メソッドを使用して、シングルトン モードと同様に、再利用可能なシンボルを作成します。Symbol.for() を初めて使用するときは、渡されたパラメータに基づいて、それを使用するかどうかをグローバルに検索します。 () は同じインスタンスを作成しました。存在する場合は再利用します。存在しない場合は、新しいインスタンスを作成します。

let fooGlobalSymbol = Symbol.for("foo"); // 创建新符号
let otherFooGlobalSymbol = Symbol.for("foo"); // 重用已有符号
console.log(fooGlobalSymbol === otherFooGlobalSymbol); // true

Symbol.for() で作成されたインスタンスと Symbol.for() で作成されたインスタンスの違いSymbol(): Symbol() によって作成されたインスタンスは常に一意であり、渡したパラメータが同じだからといって他のインスタンスと等しくなりません。ただし、Symbol.for() によって作成されたインスタンスは等しくなります。パラメータが同じ場合、同じシンボル インスタンスを共有するため

let fooSymbol = Symbol("foo");
let otherFooSymbol = Symbol("foo");
console.log(fooSymbol == otherFooSymbol); // false

let fooGlobalSymbol = Symbol.for("foo"); // 创建新符号
let otherFooGlobalSymbol = Symbol.for("foo"); // 重用已有符号
console.log(fooGlobalSymbol === otherFooGlobalSymbol); // true

3. シンボルを属性として使用する

オブジェクト内の属性は通常、次の形式になります。文字列だけでなく、シンボル インスタンスも属性として使用することもできます。この利点は、新しい属性が以前の属性を上書きしないことです。

let s1 = Symbol("foo"),
  s2 = Symbol("bar"),
  s3 = Symbol("baz"),
  s4 = Symbol("qux");
let o = {
  [s1]: "foo val",
};
// 这样也可以:o[s1] = 'foo val';
console.log(o);
// {Symbol(foo): foo val}
Object.defineProperty(o, s2, { value: "bar val" });
console.log(o);
// {Symbol(foo): foo val, Symbol(bar): bar val}
Object.defineProperties(o, {
  [s3]: { value: "baz val" },
  [s4]: { value: "qux val" },
});
console.log(o);
// {Symbol(foo): foo val, Symbol(bar): bar val,
// Symbol(baz): baz val, Symbol(qux): qux val}

注: シンボルを作成するときインスタンスをオブジェクト属性として変更する場合、シンボルが最初に受信用の変数を宣言していない場合は、オブジェクトのすべてのシンボル属性を調べて、対応する属性キーを見つける必要があります:

let o = {
  [Symbol("foo")]: "foo val",
  [Symbol("bar")]: "bar val",
};
console.log(o);
// {Symbol(foo): "foo val", Symbol(bar): "bar val"}
let barSymbol = Object.getOwnPropertySymbols(o).find(symbol => symbol.toString().match(/bar/));
console.log(barSymbol);
// Symbol(bar)

4一般的に使用される組み込みシンボル

ES6 では、言語の内部動作を公開するために、一般的に使用される多くの組み込みシンボル (既知のシンボル) も導入されています。開発者は、直接アクセス、オーバーライド、またはこれらの動作をシミュレートします。これらのデフォルト属性を変更すると、一部の操作の最終的な実行結果が変更される可能性があります。たとえば、for-of ループは関連するオブジェクトの Symbol.iterator プロパティを使用するため、カスタム オブジェクトの Symbol.iterator の値を再定義することで、オブジェクトを反復するときの for-of の動作を変更できます。

5. Symbol.asyncIterator

は実際には Promise を返すジェネレーターであり、通常は

#6 の await とともに使用されます。 hasInstance

ECMAScript 仕様によれば、このシンボルは属性として「オブジェクトのデフォルトの AsyncIterator を返すメソッド。for-await-of ステートメントで使用される」を表します。つまり、このシンボルは非同期イテレータ API を実装する関数を表します。

このプロパティは Function のプロトタイプで定義されます。オブジェクト インスタンスが特定のコンストラクターに属しているかどうかを判断するために、instanceof 演算子を使用できることは誰もが知っています。原則として、instanceof 演算子は Symbol.hasInstance 関数を使用して関係を決定します

function Foo() {}
let f = new Foo();
console.log(f instanceof Foo); // true
class Bar {}
let b = new Bar();
console.log(b instanceof Bar); // true

関数の Symbol.hasInstance プロパティを再定義すると、instanceof メソッドが予期しないものを返すようにできます

class Bar {}
class Baz extends Bar {
  static [Symbol.hasInstance]() {
    return false;
  }
}
let b = new Baz();
console.log(Bar[Symbol.hasInstance](b)); // true
console.log(b instanceof Bar); // true
console.log(Baz[Symbol.hasInstance](b)); // false
console.log(b instanceof Baz); // false

Symbol.isConcatSpreadbl

このプロパティは Array のプロトタイプで定義されています

ECMAScript 仕様によると、このシンボルはプロパティとして「ブール値、 true の場合、オブジェクトは Array.prototype.concat() を使用して配列要素をフラット化する必要があることを意味します。 ES6 の Array.prototype.concat() メソッドは、 受け取ったオブジェクト タイプに基づいて、配列のような (擬似配列) オブジェクトを配列インスタンスに結合する方法を選択します。したがって、Symbol.isConcatSpreadable の値を変更すると、この動作を変更できます。

Symbol.isConcatSpreadable 対応する効果

false: オブジェクト全体を配列に追加します true: オブジェクト全体を追加しますペアを配列に追加します

let initial = ["foo"];
let array = ["bar"];
console.log(array[Symbol.isConcatSpreadable]); // undefined
console.log(initial.concat(array)); // ['foo', 'bar']
array[Symbol.isConcatSpreadable] = false;
console.log(initial.concat(array)); // ['foo', Array(1)]
let arrayLikeObject = { length: 1, 0: "baz" };
console.log(arrayLikeObject[Symbol.isConcatSpreadable]); // undefined
console.log(initial.concat(arrayLikeObject)); // ['foo', {...}]

arrayLikeObject[Symbol.isConcatSpreadable] = true;
console.log(initial.concat(arrayLikeObject)); // ['foo', 'baz']
let otherObject = new Set().add("qux");
console.log(otherObject[Symbol.isConcatSpreadable]); // undefined
console.log(initial.concat(otherObject)); // ['foo', Set(1)]
otherObject[Symbol.isConcatSpreadable] = true;
console.log(initial.concat(otherObject)); // ['foo']

8. Symbol.iterator

ECMAScript仕様によれば、このシンボルは属性として「オブジェクトのデフォルトを返すメソッド」を表します。イテレータ。for-of ステートメントによって使用されます"

该属性会返回一个 Generator 函数,for of 就会依次的去调用 next()方法,这就是为什么 for of 可以使用在某些对象身上。

class Emitter {
  constructor(max) {
    this.max = max;
    this.idx = 0;
  }
  *[Symbol.iterator]() {
    while (this.idx < this.max) {
      yield this.idx++;
    }
  }
}
function count() {
  let emitter = new Emitter(5);
  for (const x of emitter) {
    console.log(x);
  }
}
count();
// 0
// 1
// 2
// 3
// 4

9. Symbol.match

根据 ECMAScript 规范,这个符号作为一个属性表示“一个正则表达式方法,该方法用正则表达式去匹配字符串。由 String.prototype.match()方法使用”。

String.prototype.match()方法会使用以 Symbol.match 为键的函数来对正则表达式求值。所以更改一个正则表达式的 Symbol.match 属性,可以让 String.prototype.match()得到你想要的值

console.log(RegExp.prototype[Symbol.match]);
// ƒ [Symbol.match]() { [native code] }
console.log("foobar".match(/bar/));
// ["bar", index: 3, input: "foobar", groups: undefined]

class FooMatcher {
  static [Symbol.match](target) {
    return target.includes("foo");
  }
}
console.log("foobar".match(FooMatcher)); // true
console.log("barbaz".match(FooMatcher)); // false
class StringMatcher {
  constructor(str) {
    this.str = str;
  }
  [Symbol.match](target) {
    return target.includes(this.str);
  }
}
console.log("foobar".match(new StringMatcher("foo"))); // true
console.log("barbaz".match(new StringMatcher("qux"))); // false

11. Symbol.search

这个符号作为一个属性表示“一个正则表达式方法,该方法返回字符串中 匹配正则表达式的索引。由 String.prototype.search()方法使用”

12. Symbol.species

这个符号作为一个属性表示“一个函数值,该函数作为创建派生对象的构 造函数”。

13. Symbol.split

这个符号作为一个属性表示“一个正则表达式方法,该方法在匹配正则表 达式的索引位置拆分字符串。由 String.prototype.split()方法使用”。

14. Symbol.toPrimitive

这个符号作为一个属性表示“一个方法,该方法将对象转换为相应的原始 值。由 ToPrimitive 抽象操作使用”

15. Symbol.toStringTag

这个符号作为一个属性表示“一个字符串,该字符串用于创建对象的默认 字符串描述。由内置方法 Object.prototype.toString()使用”

16. Symbol.unscopables

这个符号作为一个属性表示“一个对象,该对象所有的以及继承的属性, 都会从关联对象的 with 环境绑定中排除

更多编程相关知识,请访问:编程视频!!

以上がなぜシンボル型があるのでしょうか?使い方?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。