Inovasi JavaScript: hasil Google I / O 2019. Bagian 2

Hari ini kami menerbitkan bagian kedua dari terjemahan inovasi JavaScript. Di sini kita berbicara tentang pemisah angka angka, tentang angka besar, tentang bekerja dengan array dan objek, tentang globalThis , tentang penyortiran, tentang API internasionalisasi dan tentang janji.



Bagian pertama

Pemisah Angka


Nomor panjang yang ditemukan dalam program sulit dibaca. Misalnya, 1000000000 adalah satu miliar dalam desimal. Tetapi sekilas sulit untuk dipahami. Oleh karena itu, jika pembaca program menemukan sesuatu yang serupa, ia harus hati-hati mempertimbangkan nol agar dapat melihatnya dengan benar.

Dalam JavaScript modern, Anda dapat menggunakan pemisah digit angka - garis bawah ( _ ), yang penggunaannya meningkatkan keterbacaan angka panjang. Inilah cara angka yang ditulis menggunakan pembatas terlihat dalam kode:

 var billion = 1_000_000_000; console.log( billion ); // 1000000000 

Pemisah dapat digunakan untuk secara acak membagi angka menjadi beberapa bagian. JavaScript, ketika berhadapan dengan angka, mengabaikan pemisah. Mereka dapat digunakan saat menulis angka apa saja: bilangan bulat, titik apung, biner, heksadesimal, oktal.

 console.log( 1_000_000_000.11 ); // 1000000000.11 console.log( 1_000_000_000.1_012 ); // 1000000000.1012 console.log( 0xFF_00_FF ); // 16711935 console.log( 0b1001_0011 ); // 147 console.log( 0o11_17 ); // 591 

→ Dukungan


  • TC39: Tahap 3
  • Chrome: 75+
  • Node: 12.5+

Tipe data Bigint


Angka dalam JavaScript dibuat menggunakan fungsi konstruktor Number .

Nilai maksimum yang dapat direpresentasikan dengan aman menggunakan tipe data Number adalah (2⁵³ - 1), yaitu, 9007199254740991. Anda dapat melihat nomor ini menggunakan konstruksi Number.MAX_SAFE_INTEGER .

Harap perhatikan bahwa ketika literal numerik digunakan dalam kode JS, JavaScript memprosesnya, membuat objek berdasarkannya menggunakan konstruktor Number . Prototipe objek ini berisi metode untuk bekerja dengan angka. Ini terjadi dengan semua tipe data primitif .

Apa yang akan terjadi jika kita mencoba menambahkan sesuatu ke nomor 9007199254740991?

 console.log( Number.MAX_SAFE_INTEGER ); // 9007199254740991 console.log( Number.MAX_SAFE_INTEGER + 10 ); // 9007199254741000 

Hasil dari penambahan Number.MAX_SAFE_INTEGER dan 10, output kedua console.log() , salah. Hal ini disebabkan oleh fakta bahwa JS tidak dapat melakukan perhitungan dengan benar dengan angka lebih besar dari nilai Number.MAX_SAFE_INTEGER . Anda dapat mengatasi masalah ini dengan menggunakan bigint data bigint .

Jenis bigint memungkinkan bigint untuk mewakili bilangan bulat yang lebih besar dari Number.MAX_SAFE_INTEGER . Bekerja dengan nilai BigInt mirip dengan bekerja dengan nilai-nilai tipe Number . Secara khusus, bahasa tersebut memiliki fungsi BigInt() , yang dengannya Anda dapat membuat nilai yang sesuai, dan tipe data bigint primitif bigint digunakan untuk mewakili bilangan bulat besar.

 var large = BigInt( 9007199254740991 ); console.log( large ); // 9007199254740991n console.log( typeof large ); // bigint 

JavaScript menambahkan n ke akhir BigInt literals. Bagi kami, ini berarti bahwa literal seperti itu dapat ditulis dengan menambahkan n pada akhir bilangan bulat.

Sekarang kita memiliki angka BigInt yang dapat kita gunakan, kita dapat melakukan operasi matematika dengan aman pada sejumlah besar tipe bigint .

 var large = 9007199254740991n; console.log( large + 10n ); // 9007199254741001n 

Sejumlah nomor jenis tidak sama dengan jumlah jenis bigint . Secara khusus, kita berbicara tentang fakta bahwa angka BigInt hanya bisa bilangan bulat. Akibatnya, ternyata Anda tidak dapat melakukan operasi aritmatika yang menggunakan jenis bigint dan number .

Perlu dicatat bahwa fungsi BigInt() dapat mengambil berbagai angka: desimal, biner, heksadesimal, oktal. Di dalam fungsi ini, mereka akan dikonversi menjadi angka, untuk representasi yang menggunakan sistem angka desimal.

Jenis bigint juga mendukung pemisah bit:

 var large = 9_007_199_254_741_001n; console.log( large ); // 9007199254741001n 

→ Dukungan



Metode Array Baru: .flat () dan .flatMap ()


Di sini kita akan berbicara tentang metode prototipe baru untuk objek Array - metode .flat() dan .flatMap() .

▍ metode .at ()


Sekarang objek tipe Array memiliki metode baru - .flat(n) . Ini mengembalikan array baru, memungkinkan secara rekursif untuk menaikkan elemen array ke level yang ditentukan n . Secara default, n adalah 1. Metode ini dapat memberikan n sama dengan Infinity , yang memungkinkan Anda untuk mengubah array dengan array bersarang menjadi array satu dimensi.

 var nums = [1, [2, [3, [4, 5]]]]; console.log( nums.flat() ); // [1, 2, [3, [4,5]]] console.log( nums.flat(2) ); // [1, 2, 3, [4,5]] console.log( nums.flat(Infinity) ); // [1, 2, 3, 4, 5] 

→ Dukungan



▍ .flatMap () metode


Ketika menyelesaikan tugas sehari-hari, programmer kadang-kadang mungkin perlu memproses array menggunakan metode .map() dengan transformasi selanjutnya menjadi struktur datar. Misalnya, buat array yang berisi angka dan kuadrat dari angka-angka ini:

 var nums = [1, 2, 3]; var squares = nums.map( n => [ n, n*n ] ) console.log( squares ); // [[1,1],[2,4],[3,9]] console.log( squares.flat() ); // [1, 1, 2, 4, 3, 9] 

Solusi untuk masalah ini dapat disederhanakan dengan menggunakan metode .flatMap() . Ia mengubah array yang dikembalikan oleh fungsi callback yang diteruskan ke sana, sama seperti mereka akan mengonversi metode .flat() dengan parameter n sama dengan 1.

 var nums = [1, 2, 3]; var makeSquare = n => [ n, n*n ]; console.log( nums.flatMap( makeSquare ) ); // [1, 1, 2, 4, 3, 9] 

→ Dukungan



▍ Metode Object.fromEntries ()


Dimungkinkan untuk mengekstraksi pasangan tipe- : dari suatu objek : dapat digunakan dengan menggunakan Object Method statis, yang mengembalikan sebuah array, setiap elemen di antaranya adalah array yang mengandung, sebagai elemen pertama, kunci, dan sebagai yang kedua - sebuah nilai.

 var obj = { x: 1, y: 2, z: 3 }; var objEntries = Object.entries( obj ); console.log( objEntries ); // [["x", 1],["y", 2],["z", 3]] 

Sekarang kita sudah punya metode statis Object.fromEntries() , yang memungkinkan kita untuk mengubah struktur yang sama kembali menjadi objek.

 var entries = [["x", 1],["y", 2],["z", 3]]; var obj = Object.fromEntries( entries ); console.log( obj ); // {x: 1, y: 2, z: 3} 

Metode entries() digunakan untuk memfasilitasi penyaringan dan pemetaan data yang disimpan dalam objek. Hasilnya adalah sebuah array. Namun sejauh ini, tugas mengubah array menjadi objek belum memiliki solusi yang indah. Untuk mengatasi masalah ini Anda dapat menggunakan metode Object.fromEntries() .

 var obj = { x: 1, y: 2, z: 3 }; // [["x", 1],["y", 2],["z", 3]] var objEntries = Object.entries( obj ); // [["x", 1],["z", 3]] var filtered = objEntries.filter( ( [key, value] ) => value % 2 !== 0 //  ,     ); console.log( Object.fromEntries( filtered ) ); // {x: 1, z: 3} 

Jika Map : struktur data digunakan untuk menyimpan pasangan : , maka data di dalamnya disimpan dalam urutan yang ditambahkan ke dalamnya. Pada saat yang sama, bagaimana data disimpan menyerupai larik yang dikembalikan oleh metode Object.entries() . Metode Object.fromEntries() mudah digunakan untuk mengubah struktur data Map menjadi objek.

 var m = new Map([["x", 1],["y", 2],["z", 3]]); console.log( m ); // {"x" => 1, "y" => 2, "z" => 3} console.log( Object.fromEntries( m ) ); // {x: 1, y: 2, z: 3} 

→ Dukungan



▍ Properti global global


Kami terbiasa dengan this digunakan dalam JavaScript. Itu tidak memiliki nilai tetap. Sebaliknya, makna this tergantung pada konteks di mana ia diakses. Di lingkungan apa pun, this menunjuk ke objek global saat diakses dari konteks level tertinggi. Inilah makna global dari this .

Dalam JavaScript berbasis browser, misalnya, nilai global untuk this adalah objek window . Anda dapat memverifikasi ini dengan menggunakan console.log(this) di tingkat atas file JavaScript (dalam konteks paling eksternal) atau di konsol JS browser.


Mengakses ini di konsol browser

Nilai global this di Node.js menunjuk ke objek global . Di dalam pekerja web, itu menunjuk pada pekerja itu sendiri. Namun, mendapatkan nilai global this bukanlah tugas yang mudah. Faktanya adalah bahwa Anda tidak dapat merujuk this mana pun. Misalnya, jika Anda mencoba melakukan ini di konstruktor kelas, ternyata this menunjuk ke turunan dari kelas yang sesuai.

Di beberapa lingkungan, this self dapat digunakan untuk mengakses nilai global this . Kata kunci ini memainkan peran yang sama dengan mekanisme untuk mengakses nilai ini di browser, di Node.js, dan di pekerja web. Menggunakan pengetahuan tentang bagaimana nilai global this disebut di lingkungan yang berbeda, Anda dapat membuat fungsi yang mengembalikan nilai ini:

 const getGlobalThis = () => { if (typeof self !== 'undefined') return self; if (typeof window !== 'undefined') return window; if (typeof global !== 'undefined') return global; if (typeof this !== 'undefined') return this; throw new Error('Unable to locate global `this`'); }; var globalThis = getGlobalThis(); 

Sebelum kita adalah polyfill primitif untuk mendapatkan objek global this . Baca lebih lanjut tentang ini di sini . JavaScript sekarang memiliki kata kunci globalThis . Ini memberikan cara universal untuk mengakses nilai global this untuk lingkungan yang berbeda dan tidak bergantung pada lokasi program dari mana ia diakses.

 var obj = { fn: function() {  console.log( 'this', this === obj ); // true  console.log( 'globalThis', globalThis === window ); // true } }; obj.fn(); 

→ Dukungan



Penyortiran stabil


Standar ECMAScript tidak menawarkan algoritma penyortiran array spesifik yang harus diimplementasikan mesin JavaScript. Itu hanya menjelaskan API yang digunakan untuk menyortir. Akibatnya, dengan menggunakan mesin JS yang berbeda, orang dapat menemukan perbedaan dalam kinerja operasi penyortiran dan dalam stabilitas (stabilitas) dari algoritma penyortiran.

Sekarang standar mengharuskan array penyortiran menjadi stabil. Detail tentang stabilitas penyortiran dapat ditemukan di sini . Inti dari karakteristik algoritma pengurutan ini adalah sebagai berikut. Algoritma stabil jika hasil pengurutan, yang merupakan array yang dimodifikasi, berisi elemen dengan nilai yang sama yang tidak terpengaruh oleh pengurutan dalam urutan yang sama di mana mereka ditempatkan dalam array asli. Pertimbangkan sebuah contoh:

 var list = [  { name: 'Anna', age: 21 },  { name: 'Barbra', age: 25 },  { name: 'Zoe', age: 18 },  { name: 'Natasha', age: 25 } ]; //      age [  { name: 'Natasha', age: 25 }  { name: 'Barbra', age: 25 },  { name: 'Anna', age: 21 },  { name: 'Zoe', age: 18 }, ] 

Di sini, array list berisi objek diurutkan berdasarkan bidang age objek-objek ini. Dalam array list , objek dengan properti name sama dengan Barbra terletak di depan objek dengan properti name sama dengan Natasha . Karena nilai age dari objek-objek ini sama, kita dapat berharap bahwa dalam array yang diurutkan elemen-elemen ini akan mempertahankan urutan pengaturan sebelumnya relatif satu sama lain. Namun, dalam praktiknya hal ini tidak dapat diharapkan. Bagaimana tepatnya susunan yang disortir akan dibentuk bergantung sepenuhnya pada mesin JS yang digunakan.

Sekarang semua browser modern dan Node.js menggunakan algoritma penyortiran yang stabil, dipanggil saat mengakses metode array .sort() . Ini memungkinkan Anda untuk selalu, untuk data yang sama, mendapatkan hasil yang sama:

 //    [  { name: 'Barbra', age: 25 },  { name: 'Natasha', age: 25 }  { name: 'Anna', age: 21 },  { name: 'Zoe', age: 18 }, ] 

Di masa lalu, beberapa mesin JS mendukung penyortiran stabil, tetapi hanya untuk array kecil. Untuk meningkatkan kinerja saat memproses array besar, mereka dapat menggunakan algoritma lebih cepat dan mengorbankan stabilitas semacam.

→ Dukungan


  • Chrome: 70+
  • Node: 12+
  • Firefox: 62+

API Internasionalisasi


API internasionalisasi dimaksudkan untuk mengatur perbandingan string, untuk memformat angka, tanggal dan waktu, seperti biasa dalam berbagai standar regional (lokal). Akses ke API ini diatur melalui objek Intl . Objek ini menyediakan konstruktor untuk membuat objek penyortir dan objek yang memformat data. Daftar lokal yang didukung oleh objek Intl dapat ditemukan di sini .

▍Intl.RelativeTimeFormat ()


Dalam banyak aplikasi, seringkali perlu untuk menghasilkan waktu dalam format relatif. Mungkin terlihat seperti "5 menit yang lalu," "kemarin," "1 menit yang lalu," dan seterusnya. Jika materi situs web diterjemahkan ke dalam bahasa yang berbeda, Anda harus menyertakan semua kemungkinan kombinasi konstruksi relatif yang menggambarkan waktu dalam perakitan situs.

JS sekarang memiliki Intl.RelativeTimeFormat(locale, config) , yang memungkinkan Anda membuat sistem pemformatan tanggal dan waktu untuk lokal yang berbeda. Secara khusus, kita berbicara tentang objek yang memiliki metode .format(value, unit) , yang memungkinkan Anda untuk menghasilkan berbagai cap waktu relatif. Ini terlihat seperti ini:

 // español ( ) var rtfEspanol= new Intl.RelativeTimeFormat('es', {  numeric: 'auto' }); console.log( rtfEspanol.format( 5, 'day' ) ); // dentro de 5 días console.log( rtfEspanol.format( -5, 'day' ) ); // hace 5 días console.log( rtfEspanol.format( 15, 'minute' ) ); // dentro de 15 minutos 

→ Dukungan



▍Intl.ListFormat ()


Konstruktor Intl.ListFormat memungkinkan Intl.ListFormat untuk menggabungkan item daftar menggunakan kata-kata and ( ) dan or ( ). Saat membuat objek yang sesuai, konstruktor dilewatkan lokal dan objek dengan parameter. Parameter type dapat berupa conjunction , disjunction dan unit . Sebagai contoh, jika kita ingin menggabungkan elemen [apples, mangoes, bananas] menggunakan objek konjungsi, kita mendapatkan string dari bentuk apples, mangoes and bananas . Jika kita menggunakan objek disjungsi, kita mendapatkan string berupa apples, mangoes or bananas .

Objek yang dibuat oleh konstruktor Intl.ListFormat memiliki metode .format(list) yang menggabungkan daftar. Pertimbangkan sebuah contoh:

 // español ( ) var lfEspanol = new Intl.ListFormat('es', {  type: 'disjunction' }); var list = [ 'manzanas', 'mangos', 'plátanos' ]; console.log( lfEspanol.format( list ) ); // manzanas, mangos o plátanos 

→ Dukungan



▍Intl.Locale ()


Konsep "standar regional" biasanya lebih dari sekadar nama bahasa. Ini mungkin termasuk jenis kalender, informasi tentang siklus waktu yang digunakan, dan nama-nama bahasa. Konstruktor Intl.Locale(localeId, config) digunakan untuk membuat string Intl.Locale(localeId, config) diformat berdasarkan objek config diteruskan ke sana.

Objek yang dibuat menggunakan Intl.Locale berisi semua pengaturan regional yang ditentukan. Metode .toString() menghasilkan string standar regional yang diformat.

 const krLocale = new Intl.Locale( 'ko', {  script: 'Kore', region: 'KR',  hourCycle: 'h12', calendar: 'gregory' } ); console.log( krLocale.baseName ); // ko-Kore-KR console.log( krLocale.toString() ); // ko-Kore-KR-u-ca-gregory-hc-h12 

Di sini Anda dapat membaca tentang pengidentifikasi dan tag lokal di Unicode.

→ Dukungan



Janji


Sampai sekarang, JS memiliki metode statis Promise.all() dan Promise.race() . Metode Promise.all([...promises]) mengembalikan janji yang berhasil diselesaikan setelah semua janji yang diteruskan ke metode sebagai argumen diselesaikan. Janji ini ditolak dalam hal bahwa setidaknya satu dari janji yang ditransfer ke dalamnya ditolak. Metode Promise.race([...promises]) mengembalikan janji, yang diselesaikan setelah salah satu janji yang ditransfer ke itu diselesaikan, dan ditolak jika setidaknya salah satu dari janji tersebut ditolak.

Komunitas pengembang JS sangat membutuhkan metode statis, janji yang dikembalikan yang akan diselesaikan setelah semua janji yang diberikan kepadanya akan lengkap (diizinkan atau ditolak). Selain itu, kami membutuhkan metode yang mirip dengan race() , yang akan mengembalikan janji yang menunggu resolusi dari salah satu janji yang diberikan kepadanya.

▍ Metode Promise.allSettled ()


Metode Promise.allSettled() menerima berbagai janji. Janji yang dikembalikan olehnya diizinkan setelah semua janji ditolak atau diizinkan. Hasilnya adalah bahwa janji yang dikembalikan dengan metode ini tidak memerlukan catch .

Faktanya adalah bahwa janji ini selalu berhasil diselesaikan. Blok then menerima status dan value dari setiap janji dalam urutan yang muncul.

 var p1 = () => new Promise(  (resolve, reject) => setTimeout( () => resolve( 'val1' ), 2000 ) ); var p2 = () => new Promise(  (resolve, reject) => setTimeout( () => resolve( 'val2' ), 2000 ) ); var p3 = () => new Promise(  (resolve, reject) => setTimeout( () => reject( 'err3' ), 2000 ) ); var p = Promise.allSettled( [p1(), p2(), p3()] ).then(  ( values ) => console.log( values ) ); //  [ {status: "fulfilled", value: "val1"}  {status: "fulfilled", value: "val2"}  {status: "rejected", value: "err3"} ] 

→ Dukungan



▍ Method Promise.any ()


Metode Promise.any() mirip dengan Promise.race() , tetapi janji yang dikembalikan olehnya tidak mengeksekusi catch ketika salah satu janji yang diteruskan ke metode ini ditolak.

Sebaliknya, ia menunggu resolusi dari semua janji. Jika tidak ada janji yang diizinkan, maka catch block akan dieksekusi. Jika salah satu janji berhasil diselesaikan, then akan dieksekusi.

Ringkasan


Pada artikel ini, kami melihat beberapa inovasi JavaScript yang dibahas pada konferensi Google I / O 2019 . Kami harap Anda menemukan sesuatu di antara mereka yang berguna bagi Anda.

Pembaca yang budiman! Apa yang terutama Anda lewatkan dalam JavaScript?

Source: https://habr.com/ru/post/id464131/


All Articles