diff --git a/1-js/03-code-quality/02-coding-style/article.md b/1-js/03-code-quality/02-coding-style/article.md index 7f550115b..1ba318295 100644 --- a/1-js/03-code-quality/02-coding-style/article.md +++ b/1-js/03-code-quality/02-coding-style/article.md @@ -328,7 +328,7 @@ Berikut contoh file `.eslintrc`: }, "rules": { "no-console": 0, - "indent": ["warning", 2] + "indent": 2 } } ``` diff --git a/1-js/03-code-quality/06-polyfills/article.md b/1-js/03-code-quality/06-polyfills/article.md index 880a819b7..26527f424 100644 --- a/1-js/03-code-quality/06-polyfills/article.md +++ b/1-js/03-code-quality/06-polyfills/article.md @@ -29,7 +29,12 @@ Sebenarnya, ada dua bagian dari Babel: Seperti disebutkan diatas, JavaScript adalah sebuah bahasa pemrograman yang sangat dinamis. Skrip-skrip baru terus ditambahkan kedalam JavaScript dengan tujuan untuk membuat fungsi-fungsi baru menjadi dapat dibaca oleh penerjemah JavaScript standar. +<<<<<<< HEAD Skrip-skrip tambahan inilah yang disebut Polyfill. Skrip-skrip ini biasanya berupa fungsi-fungsi yang bertujuan menambah atau memodifikasi perbendaharaan JavaScript standar agar mampu mengenal fitur-fitur modern. +======= + New language features may include not only syntax constructs, but also built-in functions. + The transpiler rewrites the code, transforming syntax constructs into older ones. But as for new built-in functions, we need to implement them. JavaScript is a highly dynamic language, scripts may add/modify any functions, so that they behave according to the modern standard. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d Polifyll yang sering digunakan: diff --git a/1-js/04-object-basics/03-garbage-collection/article.md b/1-js/04-object-basics/03-garbage-collection/article.md index e7527179c..5083374bb 100644 --- a/1-js/04-object-basics/03-garbage-collection/article.md +++ b/1-js/04-object-basics/03-garbage-collection/article.md @@ -23,7 +23,11 @@ Sederhananya, sebuah nilai yang "terjangkau" adalah mereka yang masih dapat diak 2. Nilai lainnya dianggap terjangkau jika dapat dijangkau dari sebuah _root_ melalui sebuah rujukkan atau rantai rujukkan. +<<<<<<< HEAD Contoh, jika terdapat sebuah objek didalam global variabel, dan objek tersebut memiliki sebuah properti yang mereferensi objek lain, objek itu dianggap dapat dijangkau. Dan referensinya juga bisa dijangkau. Contoh lengkap dibawah ini. +======= + For instance, if there's an object in a global variable, and that object has a property referencing another object, *that* object is considered reachable. And those that it references are also reachable. Detailed examples to follow. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d Ada sebuah _background process_ di _engine_ JavaScript yang disebut [_garbage collector_](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)). Ia mengamati seluruh objek dan menyingkirkan semua yang sudah tak terjangkau. diff --git a/1-js/04-object-basics/07-optional-chaining/article.md b/1-js/04-object-basics/07-optional-chaining/article.md index 847543afd..cc0e5b3f3 100644 --- a/1-js/04-object-basics/07-optional-chaining/article.md +++ b/1-js/04-object-basics/07-optional-chaining/article.md @@ -14,6 +14,7 @@ The optional chaining `?.` is a safe way to access nested object properties, eve Jika kamu baru saja membaca tutorial dan belajar Javascript, mungkin masalahnya belum ketemu, tapi itu sudah biasa. +<<<<<<< HEAD <<<<<<< HEAD Contoh, beberapa dari pengguna kita punya alamat, tapi beberapa tidak memberikannya. Lalu kita tidak bisa dengan mudah menggunakan `user.address.street`: @@ -21,8 +22,13 @@ Contoh, beberapa dari pengguna kita punya alamat, tapi beberapa tidak memberikan let user = {}; // penggunanya tidak memiliki alamat ======= As an example, consider objects for user data. Most of our users have addresses in `user.address` property, with the street `user.address.street`, but some did not provide them. +======= +As an example, let's say we have `user` objects that hold the information about our users. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d + +Most of our users have addresses in `user.address` property, with the street `user.address.street`, but some did not provide them. -In such case, when we attempt to get `user.address.street`, we may get an error: +In such case, when we attempt to get `user.address.street`, and the user happens to be without an address, we get an error: ```js run let user = {}; // a user without "address" property @@ -31,6 +37,7 @@ let user = {}; // a user without "address" property alert(user.address.street); // Error! ``` +<<<<<<< HEAD <<<<<<< HEAD Atau, didalam pengembangan, kita ingin untuk mendapatkan informasi tentang sebuah elemen didalam halaman, tapi elemennya tidak ada: @@ -44,19 +51,24 @@ Sebelum `?.` muncul, operator `&&` digunakan untuk berurusan dengan hal itu. Contoh: ======= That's the expected result, JavaScript works like this. As `user.address` is `undefined`, the attempt to get `user.address.street` fails with an error. Although, in many practical cases we'd prefer to get `undefined` instead of an error here (meaning "no street"). +======= +That's the expected result. JavaScript works like this. As `user.address` is `undefined`, an attempt to get `user.address.street` fails with an error. + +In many practical cases we'd prefer to get `undefined` instead of an error here (meaning "no street"). +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d -...And another example. In the web development, we may need the information about an element on the page. The element is returned by `document.querySelector('.elem')`, and the catch is again - that it sometimes doesn't exist: +...And another example. In the web development, we can get an object that corresponds to a web page element using a special method call, such as `document.querySelector('.elem')`, and it returns `null` when there's no such element. ```js run -// the result of the call document.querySelector('.elem') may be an object or null +// document.querySelector('.elem') is null if there's no element let html = document.querySelector('.elem').innerHTML; // error if it's null ``` -Once again, we may want to avoid the error in such case. +Once again, if the element doesn't exist, we'll get an error accessing `.innerHTML` of `null`. And in some cases, when the absence of the element is normal, we'd like to avoid the error and just accept `html = null` as the result. How can we do this? -The obvious solution would be to check the value using `if` or the conditional operator `?`, before accessing it, like this: +The obvious solution would be to check the value using `if` or the conditional operator `?`, before accessing its property, like this: ```js let user = {}; @@ -64,7 +76,7 @@ let user = {}; alert(user.address ? user.address.street : undefined); ``` -...But that's quite inelegant. As you can see, the `user.address` is duplicated in the code. For more deeply nested properties, that becomes a problem. +It works, there's no error... But it's quite inelegant. As you can see, the `"user.address"` appears twice in the code. For more deeply nested properties, that becomes a problem as more repetitions are required. E.g. let's try getting `user.address.street.name`. @@ -76,10 +88,14 @@ let user = {}; // user has no address alert(user.address ? user.address.street ? user.address.street.name : null : null); ``` -That looks awful. +That's just awful, one may even have problems understanding such code. +<<<<<<< HEAD Before the optional chaining `?.` was added to the language, people used the `&&` operator for such cases: >>>>>>> d6e88647b42992f204f57401160ebae92b358c0d +======= +Don't even care to, as there's a better way to write it, using the `&&` operator: +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d ```js run let user = {}; // pengguna tidak memiliki alamat @@ -92,20 +108,35 @@ Dan juga selutuh path ke propertinya memastikan seluruh komponen ada, tapi terla ======= AND'ing the whole path to the property ensures that all components exist (if not, the evaluation stops), but also isn't ideal. -As you can see, the property names are still duplicated in the code. E.g. in the code above, `user.address` appears three times. +As you can see, property names are still duplicated in the code. E.g. in the code above, `user.address` appears three times. +<<<<<<< HEAD And now, finally, the optional chaining comes to the rescue! >>>>>>> d6e88647b42992f204f57401160ebae92b358c0d +======= +That's why the optional chaining `?.` was added to the language. To solve this problem once and for all! +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d ## Rantai opsional +<<<<<<< HEAD Rantai opsional `?.` menghentikan evaluasi dan mengembalikan `undefined` jika bagian sebelum `?.` adalah `undefined` atau `null`. +======= +The optional chaining `?.` stops the evaluation if the part before `?.` is `undefined` or `null` and returns that part. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d **Selanjutnya di artikel ini, untuk meringkas, kita akan bilang bahwa sesuatu "ada" jika itu bukan `null` dan bukan `undefined`.** +<<<<<<< HEAD <<<<<<< HEAD Ini ada cara teraman untuk mengakses `user.address.street`: ======= +======= +In other words, `value?.prop`: +- is the same as `value.prop` if `value` exists, +- otherwise (when `value` is `undefined/null`) it returns that `value`. + +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d Here's the safe way to access `user.address.street` using `?.`: >>>>>>> d6e88647b42992f204f57401160ebae92b358c0d @@ -132,6 +163,7 @@ alert( user?.address.street ); // undefined Perhatikan: sintaks `?.` membuat nilai opsional sebelumnya, tapi tidak setelahnya. +<<<<<<< HEAD <<<<<<< HEAD Didalam contoh diatas, `user?.` membolehkan hanya `user` untuk `null/undefined`. ======= @@ -142,6 +174,9 @@ Disisi lain, jika `user` ada, lalu itu harus memiliki properti `user.address`, s ```warn header="Jangan terlalu berlebihan menggunakan rantai opsional" Kita harus menggunakan `?.` hanya dimana sesuatu itu tidak apa-apa bila tidak ada. +======= +E.g. in `user?.address.street.name` the `?.` allows `user` to be `null/undefined`, but it's all it does. Further properties are accessed in a regular way. If we want some of them to be optional, then we'll need to replace more `.` with `?.`. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d <<<<<<< HEAD Contoh, jika berdasarkan logika koding kita objek `user` harus ada, tapi `address` bersifat opsional, lalu `user.address?.street` akan lebih baik. @@ -210,17 +245,20 @@ Contoh, `?.()` digunakan untuk memanggil fungsi yang mungkin saja tidak ada. Di kode dibawah, beberapa user mungkin memiliki method `admin`, dan beberapa tidak: ```js run -let user1 = { +let userAdmin = { admin() { alert("I am admin"); } -} +}; + +let userGuest = {}; -let user2 = {}; +*!* +userAdmin.admin?.(); // I am admin +*/!* *!* -user1.admin?.(); // I am admin -user2.admin?.(); +userGuest.admin?.(); // nothing (no such method) */!* ``` diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md index 4d3cfe491..906d7672f 100644 --- a/1-js/05-data-types/02-number/article.md +++ b/1-js/05-data-types/02-number/article.md @@ -406,7 +406,11 @@ Beberapa contoh: alert( Math.pow(2, 10) ); // 2 in power 10 = 1024 ``` +<<<<<<< HEAD Ada lebih banyak fungsi dan konstanta dalam objek `Math`, termasuk trigonometri, yang dapat Anda temukan di [docs untuk objek Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math). +======= +There are more functions and constants in `Math` object, including trigonometry, which you can find in the [docs for the Math object](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math). +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d ## Kesimpulan diff --git a/1-js/05-data-types/08-weakmap-weakset/article.md b/1-js/05-data-types/08-weakmap-weakset/article.md index 0b1406054..55e6c2626 100644 --- a/1-js/05-data-types/08-weakmap-weakset/article.md +++ b/1-js/05-data-types/08-weakmap-weakset/article.md @@ -30,8 +30,14 @@ let array = [ john ]; john = null; // tulis ulang referensinya *!* +<<<<<<< HEAD // john disimpan didalam array, jadi itu tidak dibuang // kita bisa mendapatkannya sebagai array[0] +======= +// the object previously referenced by john is stored inside the array +// therefore it won't be garbage-collected +// we can get it as array[0] +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d */!* ``` diff --git a/1-js/06-advanced-functions/04-var/article.md b/1-js/06-advanced-functions/04-var/article.md index 4f5c6d50d..c8045395f 100644 --- a/1-js/06-advanced-functions/04-var/article.md +++ b/1-js/06-advanced-functions/04-var/article.md @@ -78,7 +78,11 @@ function sayHi() { } sayHi(); +<<<<<<< HEAD alert(phrase); // Error: frasa tidak terdefinisi (periksa Developer Console) +======= +alert(phrase); // Error: phrase is not defined +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d ``` Seperti yang bisa kita lihat `var` menembus `if`, `for` atau blok kode lainnya. Itu karena sejak dahulu di blok Javascript tidak memiliki Lingkungan Leksikal. dan `var` adalah sisanya. @@ -267,8 +271,13 @@ Dalam semua kasus diatas kami mendeklarasikan sebuah Ekspresi fungsi dan menjala Ada dua perbedaan utama dari `var` dibandingkan dengan `let/const`; +<<<<<<< HEAD 1. `var` variabel tidak memiliki ruang lingkup blok, mereka terlihat minimum pada tingkat fungsi. 2. Deklarasi `var` diproses saat fungsi dimulai (skrip dimulai untuk global). +======= +1. `var` variables have no block scope, their visibility is scoped to current function, or global, if declared outside function. +2. `var` declarations are processed at function start (script start for globals). +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d Ada satu perbedaan kecil terkait objek global, yang akan kita bahas pada bab selanjutnya. diff --git a/1-js/06-advanced-functions/05-global-object/article.md b/1-js/06-advanced-functions/05-global-object/article.md index 7492e46c5..d4c41dcb9 100644 --- a/1-js/06-advanced-functions/05-global-object/article.md +++ b/1-js/06-advanced-functions/05-global-object/article.md @@ -5,11 +5,15 @@ Objek global menyediakan variabel dan fungsi yang bisa didapatkan dimana saja. S Di dalam browser ia dinamakan `window`, untuk Node.js `global`, untuk lingkungan lainnya ia mungkin mempunyai nama lain. +<<<<<<< HEAD <<<<<<< HEAD Akhir-akhir ini, `globalThis` ditambahkan ke bahasanya, sebagai nama standar untuk objek global, yang harus di dukung di semua lingkungan. Di browser tertentu, ya itu non-Chromium Edge, `globalThis` belum didukung, tapi bisa dengan mudah dipolyfill. ======= Recently, `globalThis` was added to the language, as a standardized name for a global object, that should be supported across all environments. It's supported in all major browsers. >>>>>>> f830bc5d9454d85829e011d914f215eb5896579a +======= +Recently, `globalThis` was added to the language, as a standardized name for a global object, that should be supported across all environments. It's supported in all major browsers. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d Kita akan memakai `window` disini, dengan anggapan bahwa lingkungan kita adalah browser. Jika script kamu mungkin digunakan di lingkungan lain, lebih baik menggunakan `globalThis`. @@ -29,7 +33,13 @@ var gVar = 5; alert(window.gVar); // 5 (menjadi properti objek global) ``` +<<<<<<< HEAD Mohon jangan bergantung dengan itu! Perilaku ini ada untuk alasan kompatibilitas. Script modern menggunakan [JavaScript modules](info:modules) dimana hal-hal tersebut tidak terjadi. +======= +The same effect have function declarations (statements with `function` keyword in the main code flow, not function expressions). + +Please don't rely on that! This behavior exists for compatibility reasons. Modern scripts use [JavaScript modules](info:modules) where such thing doesn't happen. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d Jika kita menggunakan `let`, hal tersebut tidak akan terjadi: diff --git a/1-js/06-advanced-functions/06-function-object/article.md b/1-js/06-advanced-functions/06-function-object/article.md index d41f83c4d..19e56dab5 100644 --- a/1-js/06-advanced-functions/06-function-object/article.md +++ b/1-js/06-advanced-functions/06-function-object/article.md @@ -347,7 +347,11 @@ Jika fungsinya di deklarasikan sebagai ekspresi fungsi (tidak didalam alur kode Juga, fungsi mungkin memiliki properti tambahan. Beberapa librari Javascript yang cukup terkenal banyak menggunakan fitur ini. +<<<<<<< HEAD Mereka membuat sebuah fungsi "utama" dan mengkaitkannya dengan fungsi "pembantu". Contoh librari [jQuery](https://jquery.com) menciptakan fungsi bernama `$`. Librari The [lodash](https://lodash.com) membuat sebuah fungsi `_` dan lalu menambahkan `_.clone`, `_.keyBy`dan properti lainnya kedalamnya (lihat [dokumentasinya](https://lodash.com/docs) ketika kamu mau tau lebih dalam). Sebenarnya, mereka melakukannya untuk mengurangi penggunaan dari ruang global, jadi librari tunggal itu hanya menggunakan satu variabel global. Itu mengurangi kemungkinan dari konflik penamaan variabel. +======= +They create a "main" function and attach many other "helper" functions to it. For instance, the [jQuery](https://jquery.com) library creates a function named `$`. The [lodash](https://lodash.com) library creates a function `_`, and then adds `_.clone`, `_.keyBy` and other properties to it (see the [docs](https://lodash.com/docs) when you want to learn more about them). Actually, they do it to lessen their pollution of the global space, so that a single library gives only one global variable. That reduces the possibility of naming conflicts. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d Jadi, sebuah fungsi bisa melakukan hal-hal yang berguna dengan dirinya-sendiri dan juga membawa setumpuk fungsionalitas didalam propertinya sendiri. \ No newline at end of file diff --git a/1-js/06-advanced-functions/07-new-function/article.md b/1-js/06-advanced-functions/07-new-function/article.md index aa07d101f..2573ab53c 100644 --- a/1-js/06-advanced-functions/07-new-function/article.md +++ b/1-js/06-advanced-functions/07-new-function/article.md @@ -92,7 +92,11 @@ Bagaimana jika itu bisa mengakses variabel luar? Masalahnya adalah saat Javascript belum dipublikasikan untuk produksi, itu akan dikompresi menggunakan *minifier* -- sebuah program spesial yang mengecilkan ukuran kode dengan menghapus komentar-komentar, spasi dan -- yang paling penting, menamai variabel lokal menjadi lebih pendek. +<<<<<<< HEAD Contoh, jika sebuah fungsi mempunyai `let userName`, minifier akan mengganti itu dengan `let a` (atau huruf lainnya jika tidak hurufnya tidak tersedia), dan melakukannya dimanapun. Sebenarnya itu adalah yang yang aman untuk dilakukan, karena variabelnya lokal, tidak ada sesuatu dari luar fungsinya yang bisa mengaksesnya. Dan didalam fungsinya, minifier mengganti seluruh penamaan variabelnya. Minifier cukup pintar, mereka menganalisa struktur kodenya, jadi mereka tidak akan merusak apapun. Minifier bukanlah hal bodoh yang hanya akan mencari-dan-mengganti. +======= +For instance, if a function has `let userName`, minifier replaces it with `let a` (or another letter if this one is occupied), and does it everywhere. That's usually a safe thing to do, because the variable is local, nothing outside the function can access it. And inside the function, minifier replaces every mention of it. Minifiers are smart, they analyze the code structure, so they don't break anything. They're not just a dumb find-and-replace. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d Jadi jika `new Function` mempunyai akses ke variabel luar, itu tidak akan bisa menemukan `userName` yang telah dinamai ulang. diff --git a/1-js/06-advanced-functions/08-settimeout-setinterval/article.md b/1-js/06-advanced-functions/08-settimeout-setinterval/article.md index cc0650309..7a6884a54 100644 --- a/1-js/06-advanced-functions/08-settimeout-setinterval/article.md +++ b/1-js/06-advanced-functions/08-settimeout-setinterval/article.md @@ -129,7 +129,11 @@ setTimeout(() => { clearInterval(timerId); alert('stop'); }, 5000); ```smart header="Waktu terus berjalan sementara `alert` ditampilkan" Di kebanyakan peramban, termasuk Chrome dan Firefox penghitung waktu internal berlanjut "berdetik" selagi menampilkan `alert/confirm/prompt`. +<<<<<<< HEAD Jadi jika kamu menjalankan kode diatas dan tidak menyingkirkan jendela `alert` untuk beberapa saat, maka `alert` selanjutnya akan langsung muncul. Interval sebenarnya diantara alert lebih pendek dari 2 detik. +======= +So if you run the code above and don't dismiss the `alert` window for some time, then the next `alert` will be shown immediately as you do it. The actual interval between alerts will be shorter than 2 seconds. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d ``` ## setTimeout bercabang @@ -282,16 +286,28 @@ Hal yang sama akan terjadi jika kita menggunakan `setInterval` daripada `setTime Batasan itu sudah ada sejak lama dan beberapa skrip mengandalkan hal itu, jadi itu ada untuk beberapa alasan. +<<<<<<< HEAD Untuk Javascript dibagian server, batasan itu tidaklah ada, dan disana terdapat cara lain untuk menjadwalkan sebuah pekerjaan yang asinkronus, seperti [setImmediate](https://nodejs.org/api/timers.html) untuk Node.js. Jadi hal ini merupakan hal yang berada pada peramban. +======= +For server-side JavaScript, that limitation does not exist, and there exist other ways to schedule an immediate asynchronous job, like [setImmediate](https://nodejs.org/api/timers.html#timers_setimmediate_callback_args) for Node.js. So this note is browser-specific. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d ```` ## Ringkasan +<<<<<<< HEAD - Metode `setTimeout(func,delay, ...args)` dan `setInterval(func, delay, ...args)` mengijinkan kita untuk menjalankan fungsinya sekali atau terus menerus setelah `delay` milidetik. - Untuk membatalkan eksekusinya, kita harus memanggil `clearTimeout/clearInterval` dengan nilai yang dikembalikan oleh `setTimeout/setInterval`. - Pemanggilan `setTimeout` bercabang adalah alternatif yang lebih fleksibel dari `setInterval`, mengijinkan kita untuk menyetel waktu *diantara* eksekusinya dengan lebih presisi. - Penjadwalan dengan delay 0 dengan `setTimeout(func, 0)` (sama seperti `setTimeout(func)`) digunakan untuk menjadwalkan pemanggilan "secepat mungkin, tapi setelah skrip yang sedang berjalan selesai". - Peramban membatasi delay dengan minimal 5 atau lebih pada pemanggilan bercabang dari `setTimeout` atau dari `setInterval` (setelah pemanggilan kelima) menjadi 4ms. Hanyalah untuk alasan-alasan yang sudah lama. +======= +- Methods `setTimeout(func, delay, ...args)` and `setInterval(func, delay, ...args)` allow us to run the `func` once/regularly after `delay` milliseconds. +- To cancel the execution, we should call `clearTimeout/clearInterval` with the value returned by `setTimeout/setInterval`. +- Nested `setTimeout` calls are a more flexible alternative to `setInterval`, allowing us to set the time *between* executions more precisely. +- Zero delay scheduling with `setTimeout(func, 0)` (the same as `setTimeout(func)`) is used to schedule the call "as soon as possible, but after the current script is complete". +- The browser limits the minimal delay for five or more nested calls of `setTimeout` or for `setInterval` (after 5th call) to 4ms. That's for historical reasons. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d Perhatikan bahwa seluruh metode penjadwalan tidak *menjamin* delay yang tepat. diff --git a/1-js/08-prototypes/01-prototype-inheritance/article.md b/1-js/08-prototypes/01-prototype-inheritance/article.md index e57808051..cd4b94d32 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/article.md +++ b/1-js/08-prototypes/01-prototype-inheritance/article.md @@ -12,7 +12,7 @@ In JavaScript, objects have a special hidden property `[[Prototype]]` (as named ![prototype](object-prototype-empty.svg) -The prototype is a little bit "magical". When we want to read a property from `object`, and it's missing, JavaScript automatically takes it from the prototype. In programming, such thing is called "prototypal inheritance". Many cool language features and programming techniques are based on it. +When we read a property from `object`, and it's missing, JavaScript automatically takes it from the prototype. In programming, such thing is called "prototypal inheritance". And soon we'll study many examples of such inheritance, as well as cooler language features built upon it. The property `[[Prototype]]` is internal and hidden, but there are many ways to set it. @@ -27,19 +27,11 @@ let rabbit = { }; *!* -rabbit.__proto__ = animal; +rabbit.__proto__ = animal; // sets rabbit.[[Prototype]] = animal */!* ``` -```smart header="`__proto__` is a historical getter/setter for `[[Prototype]]`" -Please note that `__proto__` is *not the same* as `[[Prototype]]`. It's a getter/setter for it. - -It exists for historical reasons. In modern language it is replaced with functions `Object.getPrototypeOf/Object.setPrototypeOf` that also get/set the prototype. We'll study the reasons for that and these functions later. - -By the specification, `__proto__` must only be supported by browsers, but in fact all environments including server-side support it. For now, as `__proto__` notation is a little bit more intuitively obvious, we'll use it in the examples. -``` - -If we look for a property in `rabbit`, and it's missing, JavaScript automatically takes it from `animal`. +Now if we read a property from `rabbit`, and it's missing, JavaScript will automatically take it from `animal`. For instance: @@ -130,6 +122,8 @@ alert(longEar.jumps); // true (from rabbit) ![](proto-animal-rabbit-chain.svg) +Now if we read something from `longEar`, and it's missing, JavaScript will look for it in `rabbit`, and then in `animal`. + There are only two limitations: 1. The references can't go in circles. JavaScript will throw an error if we try to assign `__proto__` in a circle. @@ -137,6 +131,19 @@ There are only two limitations: Also it may be obvious, but still: there can be only one `[[Prototype]]`. An object may not inherit from two others. + +```smart header="`__proto__` is a historical getter/setter for `[[Prototype]]`" +It's a common mistake of novice developers not to know the difference between these two. + +Please note that `__proto__` is *not the same* as the internal `[[Prototype]]` property. It's a getter/setter for `[[Prototype]]`. Later we'll see situations where it matters, for now let's just keep it in mind, as we build our understanding of JavaScript language. + +The `__proto__` property is a bit outdated. It exists for historical reasons, modern JavaScript suggests that we should use `Object.getPrototypeOf/Object.setPrototypeOf` functions instead that get/set the prototype. We'll also cover these functions later. + +By the specification, `__proto__` must only be supported by browsers. In fact though, all environments including server-side support `__proto__`, so we're quite safe using it. + +As the `__proto__` notation is a bit more intuitively obvious, we use it in the examples. +``` + ## Writing doesn't use prototype The prototype is only used for reading properties. @@ -198,8 +205,8 @@ alert(admin.fullName); // John Smith (*) // setter triggers! admin.fullName = "Alice Cooper"; // (**) -alert(admin.fullName); // Alice Cooper , state of admin modified -alert(user.fullName); // John Smith , state of user protected +alert(admin.fullName); // Alice Cooper, state of admin modified +alert(user.fullName); // John Smith, state of user protected ``` Here in the line `(*)` the property `admin.fullName` has a getter in the prototype `user`, so it is called. And in the line `(**)` the property has a setter in the prototype, so it is called. diff --git a/1-js/08-prototypes/04-prototype-methods/article.md b/1-js/08-prototypes/04-prototype-methods/article.md index e460ef016..a4ce2646c 100644 --- a/1-js/08-prototypes/04-prototype-methods/article.md +++ b/1-js/08-prototypes/04-prototype-methods/article.md @@ -176,8 +176,8 @@ alert(Object.keys(chineseDictionary)); // hello,bye Modern methods to set up and directly access the prototype are: - [Object.create(proto, [descriptors])](mdn:js/Object/create) -- creates an empty object with a given `proto` as `[[Prototype]]` (can be `null`) and optional property descriptors. -- [Object.getPrototypeOf(obj)](mdn:js/Object.getPrototypeOf) -- returns the `[[Prototype]]` of `obj` (same as `__proto__` getter). -- [Object.setPrototypeOf(obj, proto)](mdn:js/Object.setPrototypeOf) -- sets the `[[Prototype]]` of `obj` to `proto` (same as `__proto__` setter). +- [Object.getPrototypeOf(obj)](mdn:js/Object/getPrototypeOf) -- returns the `[[Prototype]]` of `obj` (same as `__proto__` getter). +- [Object.setPrototypeOf(obj, proto)](mdn:js/Object/setPrototypeOf) -- sets the `[[Prototype]]` of `obj` to `proto` (same as `__proto__` setter). The built-in `__proto__` getter/setter is unsafe if we'd want to put user-generated keys into an object. Just because a user may enter `"__proto__"` as the key, and there'll be an error, with hopefully light, but generally unpredictable consequences. diff --git a/1-js/09-classes/01-class/1-rewrite-to-class/task.md b/1-js/09-classes/01-class/1-rewrite-to-class/task.md index 328d8af8e..982095005 100644 --- a/1-js/09-classes/01-class/1-rewrite-to-class/task.md +++ b/1-js/09-classes/01-class/1-rewrite-to-class/task.md @@ -4,6 +4,10 @@ importance: 5 # Menulis ulang ke class +<<<<<<< HEAD Class `Clock` ditulis dalam gaya fungsional. Tulis ulang dengan menggunakan sintaks "class". +======= +The `Clock` class (see the sandbox) is written in functional style. Rewrite it in the "class" syntax. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d P.S Class Clock berdetak pada console, buka untuk melihatnya. \ No newline at end of file diff --git a/1-js/09-classes/01-class/article.md b/1-js/09-classes/01-class/article.md index 65db0a16d..a55072a79 100644 --- a/1-js/09-classes/01-class/article.md +++ b/1-js/09-classes/01-class/article.md @@ -217,7 +217,7 @@ function makeClass(phrase) { return class { sayHi() { alert(phrase); - }; + } }; } diff --git a/1-js/09-classes/02-class-inheritance/article.md b/1-js/09-classes/02-class-inheritance/article.md index f76b15275..f9957fc5c 100644 --- a/1-js/09-classes/02-class-inheritance/article.md +++ b/1-js/09-classes/02-class-inheritance/article.md @@ -75,8 +75,8 @@ Misalnya, panggilan fungsi yang menghasilkan kelas induk: ```js run function f(phrase) { return class { - sayHi() { alert(phrase) } - } + sayHi() { alert(phrase); } + }; } *!* @@ -298,7 +298,7 @@ Pertimbangkan contoh ini: ```js run class Animal { - name = 'animal' + name = 'animal'; constructor() { alert(this.name); // (*) diff --git a/1-js/09-classes/06-instanceof/article.md b/1-js/09-classes/06-instanceof/article.md index 8bbd94b09..dd1ba7ed2 100644 --- a/1-js/09-classes/06-instanceof/article.md +++ b/1-js/09-classes/06-instanceof/article.md @@ -2,7 +2,11 @@ Operator `instanceof` memungkinkan kita untuk memeriksa apakah suatu _object_ milik _class_ tertentu. `instanceof` juga memperhatikan _inheritance_. +<<<<<<< HEAD Pengecekan seperti itu mungkin diperlukan dalam beberapa kasus. Di sini kita akan menggunakannya untuk membangun fungsi *polymorphic*, yang memperlakukan argumen secara berbeda bergantung pada tipenya. +======= +Such a check may be necessary in many cases. For example, it can be used for building a *polymorphic* function, the one that treats arguments differently depending on their type. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d ## Operator instanceof [#ref-instanceof] diff --git a/1-js/11-async/06-promisify/article.md b/1-js/11-async/06-promisify/article.md index d70d582cc..beb06f272 100644 --- a/1-js/11-async/06-promisify/article.md +++ b/1-js/11-async/06-promisify/article.md @@ -4,7 +4,13 @@ Promisifikasi -- adalah kata yang panjang untuk transformasi sederhana. Ini adal Transformasi seperti itu sering kali dibutuhkan dalam kehidupan nyata sebanyak function dan pustaka berbasis callback. Tetapi promise lebih nyaman. Jadi masuk akal untuk melakukan promisify ini. +<<<<<<< HEAD Sebagai contoh, kita memiliki `loadScript(src, callback)` dari bab . +======= +For better understanding, let's see an example. + +For instance, we have `loadScript(src, callback)` from the chapter . +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d ```js run function loadScript(src, callback) { @@ -21,8 +27,19 @@ function loadScript(src, callback) { // loadScript('path/script.js', (err, script) => {...}) ``` +<<<<<<< HEAD Mari lakukan promisify. function `loadScriptPromise(src)` yang baru akan melakukan hal sama, tetapi hanya menerima `src` (tidak ada `callback`) dan mengembalikan promise. +======= +The function loads a script with the given `src`, and then calls `callback(err)` in case of an error, or `callback(null, script)` in case of successful loading. That's a widespread agreement for using callbacks, we saw it before. + +Let's promisify it. + +We'll make a new function `loadScriptPromise(src)`, that does the same (loads the script), but returns a promise instead of using callbacks. + +In other words, we pass it only `src` (no `callback`) and get a promise in return, that resolves with `script` when the load is successful, and rejects with the error otherwise. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d +Here it is: ```js let loadScriptPromise = function (src) { return new Promise((resolve, reject) => { @@ -37,6 +54,7 @@ let loadScriptPromise = function (src) { // loadScriptPromise('path/script.js').then(...) ``` +<<<<<<< HEAD Sekarang `loadScriptPromise` cocok dengan kode berbasis promise. Seperti yang kita lihat, function tersebut mendelegasikan semua pekerjaan ke `loadScript` asli, menyediakan callbacknya sendiri yang diterjemahkan menjadi promise `resolve/reject`. @@ -54,6 +72,21 @@ function promisify(f) { return function (...args) { // mengembalikan function wrapper return new Promise((resolve, reject) => { function callback(err, result) { // callback khusus kita untuk f +======= +As we can see, the new function is a wrapper around the original `loadScript` function. It calls it providing its own callback that translates to promise `resolve/reject`. + +Now `loadScriptPromise` fits well in promise-based code. If we like promises more than callbacks (and soon we'll see more reasons for that), then we will use it instead. + +In practice we may need to promisify more than one function, so it makes sense to use a helper. + +We'll call it `promisify(f)`: it accepts a to-promisify function `f` and returns a wrapper function. + +```js +function promisify(f) { + return function (...args) { // return a wrapper-function (*) + return new Promise((resolve, reject) => { + function callback(err, result) { // our custom callback for f (**) +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d if (err) { reject(err); } else { @@ -73,11 +106,26 @@ let loadScriptPromise = promisify(loadScript); loadScriptPromise(...).then(...); ``` +<<<<<<< HEAD Di sini kita asumsikan bahwa function asli mengharapkan callback dengan dua argumen `(err, result)`. Itulah yang paling sering kita temui. Kemudian callback khusus kita benar-benar dalam format yang tepat, dan `promisify` bekerja dengan baik untuk kasus seperti itu. +======= +The code may look a bit complex, but it's essentially the same that we wrote above, while promisifying `loadScript` function. + +A call to `promisify(f)` returns a wrapper around `f` `(*)`. That wrapper returns a promise and forwards the call to the original `f`, tracking the result in the custom callback `(**)`. + +Here, `promisiefy` assumes that the original function expects a callback with exactly two arguments `(err, result)`. That's what we encounter most often. Then our custom callback is in exactly the right format, and `promisify` works great for such a case. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d Tetapi bagaimana jika `f` asli mengharapkan callback dengan lebih banyak argumen `callback(err, res1, res2, ...)`? +<<<<<<< HEAD Ini versi yang lebih canggih dari `promisify`: jika dipanggil sebagai `promisify(f, true)`, hasil dari promise akan berupa array dari hasil callback `[res1, res2, ...]`: +======= +We can improve our helper. Let's make a more advanced version of `promisify`. + +- When called as `promisify(f)` it should work similar to the version above. +- When called as `promisify(f, true)`, it should return the promise that resolves with the array of callback results. That's exactly for callbacks with many arguments. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d ```js // promisify(f, true) dapatkan array dari hasil @@ -105,6 +153,12 @@ f = promisify(f, true); f(...).then(arrayOfResults => ..., err => ...) ``` +<<<<<<< HEAD +======= +As you can see it's essentially the same as above, but `resolve` is called with only one or all arguments depending on whether `manyArgs` is truthy. + +For more exotic callback formats, like those without `err` at all: `callback(result)`, we can promisify such functions manually without using the helper. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d Untuk format callback yang lebih eksotis, seperti yang tidak memiliki `err` sama sekali: `callback(result)`, kita bisa melakukan promisify function tersebut tanpa menggunakan helper, secara manual. diff --git a/1-js/11-async/08-async-await/03-async-from-regular/task.md b/1-js/11-async/08-async-await/03-async-from-regular/task.md index 11ac1d869..ee2e256cc 100644 --- a/1-js/11-async/08-async-await/03-async-from-regular/task.md +++ b/1-js/11-async/08-async-await/03-async-from-regular/task.md @@ -1,6 +1,12 @@ # Panggil async dari non-async +<<<<<<< HEAD Kita punya function "reguler". Bagaimana memanggil `async`dari function tersebut dan menggunakan hasilnya? +======= +# Call async from non-async + +We have a "regular" function called `f`. How can you call the `async` function `wait()` and use its result inside of `f`? +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d ```js async function wait() { @@ -10,9 +16,15 @@ async function wait() { } function f() { +<<<<<<< HEAD // ...apa yang ditulis di sini? // kita harus memanggil async wait() dan tunggu sampai mendapatkan 10 // ingat, kita tidak bisa menggunakan "await" +======= + // ...what should you write here? + // we need to call async wait() and wait to get 10 + // remember, we can't use "await" +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d } ``` diff --git a/1-js/13-modules/02-import-export/article.md b/1-js/13-modules/02-import-export/article.md index f68eebf49..72abe7157 100644 --- a/1-js/13-modules/02-import-export/article.md +++ b/1-js/13-modules/02-import-export/article.md @@ -327,7 +327,11 @@ Kenapa hal tersebut diperlukan? mari lihat praktik penggunaannya. Bayangkan kita menulis sebuah "paket": sebuah direktori dengan banyak modul, dengan beberapa fungsi yang diekpor ke luar (perkakas seperti NPM memungkinkan kita untuk menerbitkan dan mendistribusikan paket seperti itu), dan kebanyakan modul hanyalah "pembantu" untuk penggunaan internal di paket modul lainnya. +<<<<<<< HEAD Struktur berkas bisa seperti ini: +======= +Imagine, we're writing a "package": a folder with a lot of modules, with some of the functionality exported outside (tools like NPM allow us to publish and distribute such packages, but we don't have to use them), and many modules are just "helpers", for internal use in other package modules. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d ``` auth/ @@ -383,7 +387,11 @@ export {default as User} from './user.js'; Ekspor bawaan memerlukan penanganan terpisah ketika melakukan ekspor ulang. +<<<<<<< HEAD Misalnya kita memiliki `user.js` dan kita ingin melakukan ekspor ulang kelas `User` tersebut: +======= +Let's say we have `user.js` with the `export default class User` and would like to re-export it: +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d ```js // 📁 user.js @@ -392,7 +400,13 @@ export default class User { } ``` +<<<<<<< HEAD 1. `export User form './user.js'` tidak dapat digunakan. Apa yang salah?... Ini adalah kesalahan sintaks! +======= +We can come across two problems with it: + +1. `export User from './user.js'` won't work. That would lead to a syntax error. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d Untuk melakukan ekspor ulang ekspor bawaan, kita harus menuliskan `export { default as User }` seperti contoh diatas. @@ -405,9 +419,13 @@ export default class User { export { default } from './user.js'; // ekspor ulang ekspor bawaan ``` +<<<<<<< HEAD Keanehan dari proses mengekspor ulang ekspor bawaan adalah salah satu alasan mengapa beberapa pengembang tidak menyukainya. ## Ringkasan +======= +Such oddities of re-exporting a default export are one of the reasons why some developers don't like default exports and prefer named ones. +>>>>>>> dccca58f268ad6d5a6f2160613a8ea3c5cd53a2d Berikut merupakan semua jenis `export` yang kita bahas di artikel ini dan sebelumnya. diff --git a/2-ui/2-events/02-bubbling-and-capturing/article.md b/2-ui/2-events/02-bubbling-and-capturing/article.md index e203a4eb4..5d854a59f 100644 --- a/2-ui/2-events/02-bubbling-and-capturing/article.md +++ b/2-ui/2-events/02-bubbling-and-capturing/article.md @@ -206,7 +206,7 @@ When an event happens -- the most nested element where it happens gets labeled a - Then the event moves down from the document root to `event.target`, calling handlers assigned with `addEventListener(..., true)` on the way (`true` is a shorthand for `{capture: true}`). - Then handlers are called on the target element itself. -- Then the event bubbles up from `event.target` to the root, calling handlers assigned using `on` and `addEventListener` without the 3rd argument or with the 3rd argument `false/{capture:false}`. +- Then the event bubbles up from `event.target` to the root, calling handlers assigned using `on`, HTML attributes and `addEventListener` without the 3rd argument or with the 3rd argument `false/{capture:false}`. Each handler can access `event` object properties: diff --git a/2-ui/2-events/03-event-delegation/article.md b/2-ui/2-events/03-event-delegation/article.md index df086f24b..41df9f079 100644 --- a/2-ui/2-events/03-event-delegation/article.md +++ b/2-ui/2-events/03-event-delegation/article.md @@ -5,7 +5,7 @@ Capturing and bubbling allow us to implement one of most powerful event handling The idea is that if we have a lot of elements handled in a similar way, then instead of assigning a handler to each of them -- we put a single handler on their common ancestor. -In the handler we get `event.target`, see where the event actually happened and handle it. +In the handler we get `event.target` to see where the event actually happened and handle it. Let's see an example -- the [Ba-Gua diagram](http://en.wikipedia.org/wiki/Ba_gua) reflecting the ancient Chinese philosophy. diff --git a/2-ui/5-loading/02-script-async-defer/article.md b/2-ui/5-loading/02-script-async-defer/article.md index 24af956dc..45f507d79 100644 --- a/2-ui/5-loading/02-script-async-defer/article.md +++ b/2-ui/5-loading/02-script-async-defer/article.md @@ -83,7 +83,7 @@ Let's say, we have two deferred scripts: the `long.js` and then `small.js`: Browsers scan the page for scripts and download them in parallel, to improve performance. So in the example above both scripts download in parallel. The `small.js` probably finishes first. -...But the `defer` atribute, besides telling the browser "not to block", ensures that the relative order is kept. So even though `small.js` loads first, it still waits and runs after `long.js` executes. +...But the `defer` attribute, besides telling the browser "not to block", ensures that the relative order is kept. So even though `small.js` loads first, it still waits and runs after `long.js` executes. That may be important for cases when we need to load a JavaScript library and then a script that depends on it. diff --git a/9-regular-expressions/17-regexp-methods/article.md b/9-regular-expressions/17-regexp-methods/article.md index e4044361f..a7847c0f6 100644 --- a/9-regular-expressions/17-regexp-methods/article.md +++ b/9-regular-expressions/17-regexp-methods/article.md @@ -20,7 +20,7 @@ It has 3 modes: alert( result.length ); // 2 // Additional information: - alert( result.index ); // 0 (match position) + alert( result.index ); // 7 (match position) alert( result.input ); // I love JavaScript (source string) ```