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 !
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]
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
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
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
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
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}
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)
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é.
est en fait un générateur qui renvoie une promesse, généralement utilisé avec l'attente de
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
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
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.
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']
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
根据 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 环境绑定中排除
更多编程相关知识,请访问:编程视频!!
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!