ES6 , New OOP features beside classes

Dokumentasi Exploring ES6 sub `New OOP features beside classes`
Published di Javascript, 3 days ago

/**
* Bab 15 New OOP features beside classes
*/

/**
* 15.1 Overview
* 15.1.1 New Object literal features
*/

// method definition
// let obj = {
// myMethod1(param1, param2) {},
// };

// // Property value shorthand
// let first = "Jane";
// let last = "Doe";
// let obj2 = { first, last }; // same as let obj2 = { first:first, last:last }

// // computed property keys
// let propKey = "foo";
// let obj3 = {
// [propKey]: true,
// ["b" + "ar"]: 123,
// };

// // computed property keys, also be used for method definitions
// let obj4 = {
// ["h" + "ello"]() {
// return "hi";
// },
// };
// console.log(obj4);
// console.log(obj4.hello());

// THE MAIN USE CASE FOR COMPUTED PROPERTY KEYS IS TO MAKE IT EASY TO USE SYMBOLS AS PROPERTY KEYS

/**
* 15.1.2 New methods in `Object`
* The most important new method of `Object` is `assign()`.
* `Object.assign()` only considers `own (non-inherited)` properties
*/

// let obj = { foo: 123 };
// Object.assign(obj, { bar: true });
// console.log(JSON.stringify(obj));

/**
* 15.2 New features of object literals
* Getters and setters
*
* get foo() dan set bar(value) adalah getter dan setter:
* get foo() artinya ketika kamu mengakses obj.foo, maka fungsi ini akan dipanggil secara otomatis (tanpa tanda ()).
* set bar(value) artinya ketika kamu menetapkan obj.bar = ..., maka fungsi ini dipanggil dengan parameter value.
*
| Akses | Fungsi yang dipanggil | Bentuk syntax | Output / Catatan |
| ---------------- | --------------------- | ------------------- | ---------------------------------------- |
| `obj.foo` | `get foo()` | Tanpa `()` | Dipanggil otomatis, return-nya digunakan |
| `obj.foo()` | ‚ùå Error (undefined) | Getter bukan fungsi | Akan error karena `foo` bukan method |
| `obj.bar = true` | `set bar(value)` | Assignment | Setter dipanggil, return-nya diabaikan |
*
* Tips Tambahan:
* Getter dan setter ini berguna saat kamu ingin:
* - Mengontrol akses baca-tulis properti
* - Menyimpan log perubahan
* - Mengemas properti privat agar lebih aman
*/

// let obj = {
// get foo() {
// console.log(`GET foo`);
// return 123;
// },

// set bar(value) {
// console.log(`Set bar to ${value}`);
// // return value is ignored
// },
// };

// Pertanyaan: kenapa tidak dipanggil dengan syntax `obj.foo()` ?

// JS akan mengenali bahwa foo adalah getter, dan otomatis menjalankan get foo().
// console.log(obj.foo); // output: `GET FOO` dan `123`, ini bukan memanggil fungsi secara eksplisit.

// Ini memanggil setter set bar(value) secara otomatis, Argumen value = true, Tapi setter tidak bisa mengembalikan nilai (return value akan diabaikan)
// Statement ini tetap mengembalikan true karena itu nilai yang sedang di-assign
// console.log((obj.bar = true)); // output: `Set bar to true` dan `true`

/**
* 15.2.3 Computed property keys
* Remember that there are two ways of specifying a key when you set a property
*
* 1. Via a fixed name: `obj.foo = true`
* 2. Via an expression `obj['b' + 'ar'] = 123`
*/
// let propKey = "foo";
// let obj = {
// [propKey]: true,
// ["b" + "ar"]: 123,
// ["he" + "llo"]() {
// return "Hi";
// },
// };
// console.log(obj.bar); // 123
// console.log(obj.hello()); // hi

/**
* The main user for computed property keys are symbols.
* You can define a `public symbol` and use it as a special propperty key that is always unique.
* One prominent example is the `symbol` stored in `Symbol.iterator`.
* If on object has a method with that key, it becomes `iterable`: The method must return an `iterator`,
* which is used by constructors such as the `for loop` to iterate over the object.
*
* ✳️ Apa Itu * dan yield?
* *[Symbol.iterator]() artinya: ini adalah generator function.
* Tanda * berarti fungsi ini bisa ditunda (lazy) dan digunakan untuk membuat iterator.
* yield artinya "kembalikan satu nilai dulu, tapi nanti bisa lanjut lagi."
*/

// let obj = {
// // (A)
// *[Symbol.iterator]() {
// yield "Hello", yield "World";
// },
// };

// for (const x of obj) {
// console.log(x);
// }

/**
* 15.3 New methods of `Object`
*/

/**
* 15.3.1 Object.assign(target, source_1, source_2, ...)
* This method merges the sources into the target: It modifies `target`, first copies all enumerable own
* properties of `source_1` into it, then all own properties of `source_2`,etc.
*
* How `Object.assign()` works.
* 1. Both kinds of property keys: `Object.assign()` supports both strings and `symbols` as property keys
* 2. Only enumerable own properties: `Object.assign()` ignores inherited properties and properties that are enumerable
* 3. Copying via assignment. Properties in the target object are created via assignment (internal operation[[Put]]).
* That means that `IF` target has `own or inerited` setters, those will be invoked during `copying`.
* An alternative would have been to `define` new properties, an operation which always creates new own peroperties
* and never invokes setters. There originally was a proposal for a variant of `Object.assign` that use definition
* instead if assignment. That proposal has been rejected for ES6, but may reconsidered for later editions.
* 4. You can't move that uses `super`; Such a method has an interbal property [[Home-Object]] that ties it to the object
* it was created in. If you move it via `Object.assign`, it will continue to refer to the super-properties of
* the original object.
*
| No | Fitur / Catatan | Penjelasan Singkat |
| -- | --------------------------------------------- | --------------------------------------------------- |
| 1 | Mendukung `string` dan `symbol` keys | ‚úÖ selama enumerable |
| 2 | Hanya properti `own` dan `enumerable` | ‚ùå Tidak menyalin inherited atau non-enumerable |
| 3 | Menyalin via `assignment`, bukan `definition` | ⚠️ Men-trigger setter kalau ada |
| 4 | Tidak bisa menyalin method yang pakai `super` | ‚ùå Karena `[[HomeObject]]` tetap menunjuk objek asal |
*/

// let obj = { foo: 123 };
// Object.assign(obj, { bar: true });
// console.log(obj);
// console.log(JSON.stringify(obj));

/**
* 15.3.1.1 Use cases for `Object.assign()`
*/

/**
* 15.3.1.1.1 Adding properties to `this`, you can use `Object.assign()` to add properties to `this` in a constructor
*/
class Point {
constuctor(x, y) {
Object.assign(this, { x, y });
}
}

/**
* 15.3.1.1.2 Providing default values for object properties.
* `Object.assign`, is also useful for filling in defaults for missing properties.
* In the following example, we have an object `DEFAULTS` with default values for properties and an object options with data.
*/

// const DEFAULTS = {
// logLevel: 0,
// outputFormat: "html",
// };

// function processContent(options) {
// // (A), we created a fresh object,
// // copied the defaults into it,
// // and then copied options into it,
// // overriding the default values
// options = Object.assign({}, DEFAULTS, options); // (A)
// console.log(options);
// }

// let newProcessContent = new processContent({ logLevel: 1 });

/**
* 15.3.1.1.3 Adding methods to objects
*/

// class SomeClass {}
// Object.assign(SomeClass.prototype, {
// someMethod(argument1, argument2) {
// console.log(`Some method ${argument1} ${argument2}`);
// },
// anotherMethod() {
// console.log("Another method");
// },
// });
// let aSomeClass = new SomeClass();
// aSomeClass.someMethod("Merindu", "Lagi");
// Bisa juga SomeClass.property.someMethod = function(argument1, argument2) { ...}

/**
* 15.3.1.1.4 Cloning objects
* One last use case for `Object.assign()` is a quick way of cloning objects.
* But, if you use this way, you will get `somewhat dirty`.
* Because it does not preserve the property attributes of orig. You must use `property descriptors`
*/
// function clone(orig) {
// //return Object.assign({}, orig); // cloning objects
// let origProto = Object.getPrototypeOf(orig);
// return Object.assign(Object.create(origProto), orig); // The clone to have the same prototype as the original
// }

/**
* 15.3.2 Object.getOwnPropertySymbols(obj)
* => retrieve all own symboled-value property keys of `obj`.
* It complements `Object.getOwnPropertyNames()` which retrieve all `string-valued` own property keys.
*
*/

/**
* 15.3.3 Object.is(value1, value2)
* The strict equals operator (===) treats two values differently that one might expect
*/

// console.log(NaN === NaN); // false
// console.log([0, NaN, 2].indexOf(NaN)); // -1 alias ga ketemu
// console.log([0, NaN, 2].findIndex(Number.isNaN)); // 1,ketemu

// Javascript has two zeros, but strict equals treats them as if they were the same value:
//console.log(-0 === +0);

// console.log(Object.is(NaN, NaN));
// console.log(Object.is(-0, +0));

/**
* 15.3.3.1 Using `Object.is()` to find Array elements
* If we combine `Object.is()` with the ES6 Array method `findIndex()`, we can find `NaN` in Arrays.
*/

// function myIndexOf(arr, elem) {
// return arr.findIndex((x) => Object.is(x, elem));
// }
// console.log(myIndexOf([0, NaN, 2], NaN));
// console.log([0, NaN, 2].indexOf(NaN));

/**
* 15.3.4 `Object.setPrototypeOf(obj, proto)`
* This method sets the prototype of `obj` to `proto`. The non standard way of doing in ES5, that is supported by many engines,
* is via assigning to the special property `__proto__`. The recommended way of setting the prototype remains the same as in ES5;
* During the creation of object, via `Object.create()`. That will always be faster than first creating an object and then setting
* its prototype. Obviously, it does not work if you want to change the prototype of an existing object.
*
* üí° Analoginya
* Object.create(proto) seperti melahirkan anak dengan warisan genetik langsung dari orang tua.
* Object.setPrototypeOf(obj, proto) seperti mengubah orang tua anak setelah dia lahir, yang biologisnya sudah telanjur beda.
*
*
| Metode | Contoh | Status | Catatan |
| ----------------------------------- | ----------------------------------- | ------------- | ------------------------------ |
| `Object.setPrototypeOf(obj, proto)` | `Object.setPrototypeOf(obj, proto)` | ‚úÖ standar ES6 | Tapi **lambat** untuk performa |
| `__proto__` | `obj.__proto__ = proto` | ⚠️ deprecated | Non-standard, hindari |
| `Object.create(proto)` | `Object.create(proto)` | ‚úÖ recommended | Paling efisien dan bersih |

*/

/**
* 15.4 Iterating over property keys in ES6
* - Object.keys(obj): Array <string>
* - Object.getOwnPropertyNames(obj): Array <string>
* - Object.getOwnPropertySymbols(obj) : Array <symbol>
* - Reflect.ownKeys(obj) : Array <string | symbol>
* - Reflect.enumerate(obj) : Iterator
*/

/**
* 15.4.1 Iteration order of property keys
* All methods that iterate over property keys do so in the same order:
*
* - First all Array indices, sorted numerically
* - Then all string keys (that are not indices), in the order in which they were created.
* - Then all symbols, in the order in which they were created
*
| Jenis Key | Contoh | Urutan |
| ------------------ | ------------ | ---------------- |
| Array Index | `'0'`, `'1'` | Numerik naik |
| String (non-index) | `'name'` | Urutan deklarasi |
| Symbol | `Symbol()` | Urutan deklarasi |
*/

console.log(
Reflect.ownKeys({
[Symbol()]: 0,
b: 0,
10: 0,
2: 0,
a: 0,
})
); // [ '2', '10', 'b', 'a', Symbol() ]

/**
*
* Why does the spec standardize in which order property keys are returned?
*
| Pertimbangan | Alasan |
| ------------------------------------------------------- | ----------------------------------------------------------------- |
| Banyak kode lama tergantung pada urutan properti object | Jadi urutan yang lazim (de facto) dijadikan standar |
| Browser harus konsisten agar web tetap bekerja | Maka dijadikan **requirement dalam spesifikasi ECMAScript** |
| Alternatif: urutan acak pada Map/Set | Terlalu mahal, susah, dan tidak bermanfaat praktis |
| Ordered structure useful (Python’s OrderedDict) | Maka dipilih model **creation-order yang stabil dan prediktabel** |


| Bagian | Fungsi | Dampak pada Iterasi |
| ------------------------- | ------------------------------------------------------------------- | ------------------------------------------- |
| **Array exotic object** | Menjelaskan **apa itu array index** (misalnya `"0"`, `"1"`) | Index diurutkan numerik dulu |
| **`[[OwnPropertyKeys]]`** | Metode internal standar ECMAScript | Menentukan **urutan properti** saat iterasi |
| Digunakan oleh | `Object.keys`, `Object.getOwnPropertyNames`, `Reflect.ownKeys`, dll | Semua iterasi key mengikuti aturan ini |


*/


const obj = {
b: 1,
100: 2,
a: 3,
2: 4,
[Symbol("x")]: 5,
};

console.log(Reflect.ownKeys(obj));
// ['2', '100', 'b', 'a', Symbol(x)]




Dukung Saya supaya tetap menulis artikel-artikel yang baik, membayar sewa domain, dan server untuk blog ini. Caranya dengan donasi cendol via Trakteer.id.


No image

Fadly Dzil Jalal

PHP, Yii2 Framework, Laravel, Java, Java Swing, Hibernate, Javascript, Angular, React, MySQL, MongoDB


Dapatkan USD 200 untuk develop aplikasimu di DigitalOcean DigitalOcean Referral Badge