シンボルとは何ですか?なぜそんな事があるのでしょうか?次の記事では、JavaScript の Symbol 型について紹介し、その使い方について説明します。
Symbol (シンボル) は、ES6 で追加された新しいデータ型です。シンボルはプリミティブ値 (基礎となるデータ型) であり、シンボル インスタンスは一意で不変です。これは、一意にマークを付けるために使用され、文字列以外の形式でオブジェクト属性として使用されるために生成され、オブジェクト属性が一意の識別子を使用し、属性の競合の危険がないようにするためです。 [関連する推奨事項: JavaScript 学習チュートリアル]
記号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
コード内の複数の場所で同じシンボル インスタンスを使用する必要がある場合は、文字列を渡すことができます。 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
オブジェクト内の属性は通常、次の形式になります。文字列だけでなく、シンボル インスタンスも属性として使用することもできます。この利点は、新しい属性が以前の属性を上書きしないことです。
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)
ES6 では、言語の内部動作を公開するために、一般的に使用される多くの組み込みシンボル (既知のシンボル) も導入されています。開発者は、直接アクセス、オーバーライド、またはこれらの動作をシミュレートします。これらのデフォルト属性を変更すると、一部の操作の最終的な実行結果が変更される可能性があります。たとえば、for-of ループは関連するオブジェクトの Symbol.iterator プロパティを使用するため、カスタム オブジェクトの Symbol.iterator の値を再定義することで、オブジェクトを反復するときの for-of の動作を変更できます。
は実際には Promise を返すジェネレーターであり、通常は
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
このプロパティは Array のプロトタイプで定義されています
ECMAScript 仕様によると、このシンボルはプロパティとして「ブール値、 true の場合、オブジェクトは Array.prototype.concat() を使用して配列要素をフラット化する必要があることを意味します。 ES6 の Array.prototype.concat() メソッドは、 受け取ったオブジェクト タイプに基づいて、配列のような (擬似配列) オブジェクトを配列インスタンスに結合する方法を選択します。したがって、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']
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
根据 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
这个符号作为一个属性表示“一个正则表达式方法,该方法返回字符串中 匹配正则表达式的索引。由 String.prototype.search()方法使用”
这个符号作为一个属性表示“一个函数值,该函数作为创建派生对象的构 造函数”。
这个符号作为一个属性表示“一个正则表达式方法,该方法在匹配正则表 达式的索引位置拆分字符串。由 String.prototype.split()方法使用”。
这个符号作为一个属性表示“一个方法,该方法将对象转换为相应的原始 值。由 ToPrimitive 抽象操作使用”
这个符号作为一个属性表示“一个字符串,该字符串用于创建对象的默认 字符串描述。由内置方法 Object.prototype.toString()使用”
这个符号作为一个属性表示“一个对象,该对象所有的以及继承的属性, 都会从关联对象的 with 环境绑定中排除
更多编程相关知识,请访问:编程视频!!
以上がなぜシンボル型があるのでしょうか?使い方?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。