Maison > interface Web > js tutoriel > Pourquoi y a-t-il un type de symbole ? Comment utiliser ?

Pourquoi y a-t-il un type de symbole ? Comment utiliser ?

青灯夜游
Libérer: 2022-03-22 11:04:51
avant
2746 Les gens l'ont consulté

Qu'est-ce que le symbole ? Pourquoi y a-t-il une telle chose ? L'article suivant vous présentera le type Symbole en JavaScript et expliquera comment l'utiliser. J'espère qu'il vous sera utile !

Pourquoi y a-t-il un type de symbole ? Comment utiliser ?

Qu'est-ce que le symbole ? Pourquoi y a-t-il une telle chose ?

Symbol (symbole) est un nouveau type de données dans ES6. Les symboles sont des valeurs primitives (le type de données sous-jacent) et les instances de symboles sont uniques et immuables. Il est généré car il est utilisé pour marquer de manière unique, puis être utilisé comme attributs d'objet sous forme non chaîne pour garantir que les attributs d'objet utilisent des identifiants uniques sans risque de conflits d'attributs. [Recommandations associées : Tutoriel d'apprentissage Javascript]

Utilisation

1. Les symboles d'utilisation de base

doivent être initialisés à l'aide de la fonction Symbol(). Étant donné que les symboles eux-mêmes sont des types primitifs, l'opérateur typeof renvoie symbole sur symboles.

let sym = Symbol();
console.log(typeof sym); // symbol
Copier après la connexion

La fonction Symbol() peut recevoir un paramètre de chaîne à décrire, puis vous pouvez utiliser cette chaîne pour déboguer le code. Mais il convient de noter que même si plusieurs fonctions Symbol() acceptent les mêmes paramètres, leurs valeurs ne sont pas égales.

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

console.log(genericSymbol == otherGenericSymbol); // false
console.log(fooSymbol == otherFooSymbol); // false
Copier après la connexion

2. Utilisez le registre global de symboles

Si vous devez utiliser la même instance de Symbol à plusieurs endroits dans le code, vous pouvez transmettre une chaîne, puis utiliser la méthode Symbol.for() pour créer un réutilisé. Symbol est similaire au mode singleton. Lors de la première utilisation de Symbol.for(), il recherchera globalement si la même instance a été créée à l'aide de Symbol.for() en fonction des paramètres transmis. Si oui, réutilisez-la. . Sinon, créez-en un nouveau

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

La différence entre l'instance créée par Symbol.for() et l'instance créée par Symbol() :L'instance créée par Symbol() est toujours unique et ne changera pas car vous passez-le Les paramètres d'entrée sont les mêmes et sont égaux aux autres instances, mais les instances créées par Symbol.for() seront égales si les paramètres sont les mêmes, car elles partageront la même instance de Symbol

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
Copier après la connexion

3. symboles comme attributs

Les attributs dans les objets se présentent généralement sous la forme de chaînes, mais en fait, vous pouvez également utiliser des instances de symboles comme attributs. L'avantage est que vos nouveaux attributs n'écraseront aucun attribut précédent

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}
Copier après la connexion

Remarque : Créer Lorsqu'une instance de symbole est utilisée comme attribut d'objet, si le symbole est modifié sans déclarer de variable pour réception au début, alors tous les attributs de symbole de l'objet doivent être parcourus pour trouver la clé d'attribut correspondante :

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)
Copier après la connexion

4 . Symboles intégrés couramment utilisés

ES6 Un certain nombre de symboles intégrés couramment utilisés (symboles bien connus) sont également introduits pour exposer le comportement interne du langage, et les développeurs peuvent directement accéder, remplacer ou simuler ces comportements. Si ces attributs par défaut sont modifiés, les résultats finaux d'exécution de certaines opérations peuvent être modifiés. Par exemple, une boucle for-of utilise la propriété Symbol.iterator sur l'objet concerné, vous pouvez donc modifier le comportement de for-of lors de l'itération de l'objet en redéfinissant la valeur de Symbol.iterator sur l'objet personnalisé.

5. Symbol.asyncIterator

est en fait un générateur qui renvoie une promesse, généralement utilisé avec l'attente de

6 Symbol.hasInstance

Selon la spécification ECMAScript, ce symbole en tant qu'attribut représente ". une méthode, cette méthode renvoie l'AsyncIterator par défaut de l'objet utilisé par l'instruction for-await-of. En d’autres termes, ce symbole représente une fonction qui implémente l’API d’itérateur asynchrone.

Cette propriété est définie sur le prototype de Function. Nous savons tous que l'opérateur instanceof peut être utilisé pour déterminer si une instance d'objet appartient à un certain constructeur. Le principe est que l'opérateur instanceof utilisera la fonction Symbol.hasInstance pour déterminer la relation

function Foo() {}
let f = new Foo();
console.log(f instanceof Foo); // true
class Bar {}
let b = new Bar();
console.log(b instanceof Bar); // true
Copier après la connexion

Si vous redéfinissez la propriété Symbol.hasInstance d'une fonction, vous pouvez laisser la méthode instanceof renvoyer quelque chose d'inattendu

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
Copier après la connexion

Symbol.isConcatSpreadabl

Cet attribut est défini sur le prototype d'Array

Selon la spécification ECMAScript, ce symbole en tant qu'attribut représente "une valeur booléenne. Si vrai, cela signifie que l'objet doit aplatir ses éléments du tableau en utilisant Array.prototype.concat( )". La méthode Array.prototype.concat() dans ES6 Sélectionnez comment fusionner un objet de type tableau (pseudo-tableau) en une instance de tableau en fonction du type d'objet reçu. Ainsi, modifier la valeur de Symbol.isConcatSpreadable peut modifier ce comportement.

Effet correspondant Symbol.isConcatSpreadable

false : Ajoutez un objet entier au tableau true : Ajoutez une paire entière au tableau

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']
Copier après la connexion

8.Symbol.iterator

Selon la spécification ECMAScript, ce symbole en tant qu'attribut représente "une méthode qui renvoie l'itérateur par défaut de l'objet. Utilisé par l'instruction 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
Copier après la connexion

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
Copier après la connexion

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 环境绑定中排除

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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:juejin.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal