Rumah >hujung hadapan web >tutorial js >Pemahaman mendalam tentang cara menggunakan Symbol dalam pengetahuan JavaScript_Basic
Apakah itu Simbol?
Simbol bukan ikon, dan juga tidak bermaksud imej kecil boleh digunakan dalam kod:
juga bukan sintaks untuk merujuk kepada sesuatu yang lain. Jadi, apa sebenarnya Simbol?
Tujuh jenis data
Apabila JavaScript diseragamkan pada tahun 1997, terdapat 6 jenis data Sehingga kemunculan ES6, pembolehubah dalam program mestilah salah satu daripada 6 jenis data berikut:
. Tidak ditentukan
Batal
Boolean
Nombor
Rentetan
Objek
Setiap jenis data ialah gabungan siri nilai dan bilangan nilai lima jenis data pertama adalah terhad. Jenis Boolean hanya mempunyai dua nilai: benar dan salah Apabila memberikan nilai kepada pembolehubah jenis Boolean, tiada nilai baharu dijana (dua nilai benar dan salah dikongsi). Untuk Nombor dan Rentetan, nilainya lebih banyak. Pernyataan standard ialah terdapat 18,437,736,874,454,810,627 nilai jenis nombor (termasuk NAN). Bilangan jenis String sukar dikira pada asalnya (2144,115,188,075,855,872 ? 1) ÷ 65,535...tetapi mungkin saya silap.
Bilangan nilai objek tidak terhad, dan setiap objek adalah unik Setiap kali halaman web dibuka, satu siri objek dibuat.
Simbol dalam ES6 juga merupakan jenis data, tetapi ia bukan rentetan atau objek, tetapi jenis data baharu: jenis data ketujuh.
Mari kita lihat senario di mana Simbol mungkin berguna.
Soalan yang ditimbulkan oleh nilai Boolean
Kadangkala adalah sangat mudah untuk menyimpan sementara beberapa data kepunyaan objek lain dalam objek lain. Sebagai contoh, katakan anda menulis pustaka JS yang menggunakan peralihan dalam CSS untuk membuat elemen DOM terbang merentasi skrin Anda sudah tahu bahawa anda tidak boleh menggunakan berbilang peralihan pada div yang sama pada masa yang sama, jika tidak, animasi akan menjadi sangat tidak sedap dipandang. . Anda mempunyai cara untuk mengatasinya, tetapi pertama-tama anda perlu mengetahui sama ada div sudah bergerak.
Bagaimana untuk menyelesaikan masalah ini?
Salah satu cara ialah menggunakan API yang disediakan oleh penyemak imbas untuk mengesan sama ada elemen itu berada dalam keadaan animasi, tetapi ia membuang masa Apabila anda menetapkan elemen untuk bergerak, pustaka anda tahu bahawa elemen itu sedang bergerak.
Apa yang anda perlukan sebenarnya ialah mekanisme untuk menjejaki elemen mana yang bergerak, anda boleh menyimpan elemen bergerak dalam tatasusunan, dan setiap kali anda ingin menghidupkan elemen, semak dahulu sama ada elemen itu sudah ada dalam ini dalam senarai.
Ahem, tetapi jika tatasusunan anda sangat besar, walaupun carian linear seperti ini boleh mencipta isu prestasi.
Jadi, perkara yang anda mahu lakukan ialah tetapkan bendera terus pada elemen:
if (element.isMoving) { smoothAnimations(element); } element.isMoving = true; if (element.isMoving) { smoothAnimations(element); } element.isMoving = true;
Ini juga mempunyai beberapa masalah yang berpotensi, dan anda perlu mengakui hakikat bahawa terdapat kod lain yang mungkin juga beroperasi pada elemen ODM ini.
if (element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__) { smoothAnimations(element); } element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__ = true; if (element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__) { smoothAnimations(element); } element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__ = true;
Sintaks
// get 1024 Unicode characters of gibberish var isMoving = SecureRandom.generateName(); ... if (element[isMoving]) { smoothAnimations(element); } element[isMoving] = true; // get 1024 Unicode characters of gibberish var isMoving = SecureRandom.generateName(); ... if (element[isMoving]) { smoothAnimations(element); } element[isMoving] = true;
Kenapa susah sangat? Kami hanya menyimpan sedikit bendera.
Gunakan Simbol untuk menyelesaikan masalah
Nilai simbol boleh dibuat secara pengaturcaraan dan digunakan sebagai nama atribut tanpa perlu risau tentang konflik nama atribut.
调用 Symbol() 方法将创建一个新的 Symbol 类型的值,并且该值不与其它任何值相等。
与数字和字符串一样,Symbol 类型的值也可以作为对象的属性名,正是由于它不与任何其它值相等,对应的属性也不会发生冲突:
obj[mySymbol] = "ok!"; // guaranteed not to collide console.log(obj[mySymbol]); // ok! obj[mySymbol] = "ok!"; // guaranteed not to collide console.log(obj[mySymbol]); // ok!
下面是使用 Symbol 来解决上面的问题:
// create a unique symbol var isMoving = Symbol("isMoving"); ... if (element[isMoving]) { smoothAnimations(element); } element[isMoving] = true; // create a unique symbol var isMoving = Symbol("isMoving"); ... if (element[isMoving]) { smoothAnimations(element); } element[isMoving] = true;
上面代码需要注意几点:
由于 Symbol 的设计初衷是为了避免冲突,当遍历 JavaScript 对象时,并不会枚举到以 Symbol 作为建的属性,比如,for-in 循环只会遍历到以字符串作为键的属性,Object.keys(obj)和 Object.getOwnPropertyNames(obj) 也一样,但这并不意味着 Symbol 为键的属性是不可枚举的:使用 Object.getOwnPropertySymbols(obj) 这个新方法可以枚举出来,还有 Reflect.ownKeys(obj) 这个新方法可以返回对象中所有字符串和 Symbol 键。(我将在后面的文章中详细介绍 Reflect 这个新特性。)
库和框架的设计者将会发现很多 Symbol 的用途,稍后我们将看到,JavaScript 语言本身也对其有广泛的应用。
Symbol 究竟是什么呢
> typeof Symbol() "symbol" > typeof Symbol() "symbol"
Symbol 是完全不一样的东西。一旦创建后就不可更改,不能对它们设置属性(如果在严格模式下尝试这样做,你将得到一个 TypeError)。它们可以作为属性名,这时它们和字符串的属性名没有什么区别。
另一方面,每个 Symbol 都是独一无二的,不与其它 Symbol 重复(即便是使用相同的 Symbol 描述创建),创建一个 Symbol 就跟创建一个对象一样方便。
ES6 中的 Symbol 与传统语言(如 Lisp 和 Ruby)中的 Symbol 中的类似,但并不是完全照搬到 JavaScript 中。在 Lisp 中,所有标识符都是 Symbol;在 JavaScript 中,标识符和大多数属性仍然是字符串,Symbol 只是提供了一个额外的选择。
值得注意的是:与其它类型不同的是,Symbol 不能自动被转换为字符串,当尝试将一个 Symbol 强制转换为字符串时,将返回一个 TypeError。
> var sym = Symbol("<3"); > "your symbol is " + sym // TypeError: can't convert symbol to string > `your symbol is ${sym}` // TypeError: can't convert symbol to string > var sym = Symbol("<3"); > "your symbol is " + sym // TypeError: can't convert symbol to string > `your symbol is ${sym}` // TypeError: can't convert symbol to string
Paksaan sedemikian harus dielakkan dan String(sym) atau sym.toString() harus digunakan untuk penukaran.
Tiga cara untuk mendapatkan Simbol
Jika anda masih tidak pasti sama ada Simbol berguna, bahagian seterusnya akan menjadi sangat menarik kerana saya akan menunjukkan kepada anda Simbol dalam tindakan.
Aplikasi Simbol dalam spesifikasi ES6
Kami sudah tahu bahawa kami boleh menggunakan Simbol untuk mengelakkan konflik kod. Apabila memperkenalkan iterator sebelum ini, kami juga menganalisis bahawa untuk (var item myArray) secara dalaman bermula dengan memanggil myArray[Symbol.iterator](Pada masa itu, saya menyebut bahawa kaedah ini boleh digantikan dengan myArray.iterator(), tetapi menggunakan Simbol mempunyai keserasian ke belakang yang lebih baik.
Masih terdapat beberapa tempat di mana Simbol digunakan dalam ES6. (Ciri ini belum lagi dilaksanakan dalam FireFox.)
Penggunaan ini masih agak sempit, tetapi sukar untuk melihat kesan ketara ciri baharu ini hanya dengan melihat kod dalam artikel saya. Simbol JavaScript ialah versi __doubleUnderscores yang dipertingkatkan dalam PHP dan Python, dan organisasi standard akan menggunakannya untuk menambah ciri baharu pada bahasa tanpa menjejaskan kod sedia ada.