JavaScript - Getter, Setter, Class...
Tags: javascript, class, getter, setter
Published: 2021-12-09 20:49:39


# Property flags
Until now, a property was a simple **“key-value”** pair to us. <u>But an object property is actually a more flexible and powerful thing</u>.
Object properties, besides a value, have **three special attributes** (so-called “<u>flags</u>”)
- **`writable`** – if true, the value can be changed, otherwise it’s read-only.
- **`enumerable`** – if true, then listed in loops, otherwise not listed.
- **`configurable`** – if true, the property can be deleted and these attributes can be modified, otherwise not.

![property flags](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/idio0wgllhg6v2ihtjyt.png)
By using **`Object.getOwnPropertyDescriptor()`**, you can check property flags
```js
let user = {
    name: 'Lilly'
};

Object.defineProperty(user, "name", {
    writable: false
});

user.name = "Pete";

user.name; // it's not changed because we set writable: false previously.
// 'Lilly'
```
Find out about [property flags](https://javascript.info/property-descriptors)



# Prototype
Read this: [About Proto Type](https://javascript.info/prototypes)

# Getter
**`get`** syntax **binds an object property to a function** that <u>will be called when that property is looked up</u>
Use this to get values from object
```js
let user = {
    name: "John",
    surname: "Smith",
    
    get fullName() {
        return `${this.name} ${this.surname}`;
    }
};
console.log(user.fullName);
// John Smith
```
# Setter
**`set`** syntax **binds an object property to a function** to be <u>called when there is an attempt to set that property</u>.
Use this to set values to object
```js
let user = {
    name: "John",
    surname: "Smith",
    
    get fullName() {
        return `${this.name} ${this.surname}`;
    },

    set fullNameSet(value) {
        [this.name, this.surname] = value.split(" ");
    }
};

user.fullNameSet = "Hailey Ji";
console.log(user.name);
// Hailey
console.log(user.surname);
// Ji

// closure
const user = (function () {
  let name = "Hailey";
  let surname = "Ji";
  return {
    fullname: function() {
      return `${name} ${surname}`;
    }
  };
}());

user.fullname();
// 'Hailey Ji'
user.name;
// undefined
user.surname;
// undefined

```

# Class
Classes are a **_template for creating objects_**. They <u>encapsulate data with code to work on that data</u>. Classes in JS are built on prototypes but also have some syntax and semantics that are not shared with ES5 class-like semantics.
Classes are in fact "**_special functions_**",and just as you can define function expressions and function declarations, the class syntax has two components: class expressions and class declarations.

Class : is like a factory that make items.
Instance : is like a item that's produced from factory.
```js
class MyClass {
  // you can write different kind of methods
  constructor() { ... }; // don't use ,(comma) in class, use ;(semicolon)
  method1() { ... };
  method2() { ... };
  method3() { ... };
  ...
}

```

```js
class User {

  constructor(name) {
    this.name = name;
  }

  sayHi() {
    alert(this.name);
  }

}

// How to use:
let user = new User("John");
user.sayHi(); 
console.log(typeof User);
// ‘function’ 

class User {
  constructor(name) { this.name = name; }
  sayHi() { alert(this.name); }
}

console.log(typeof User); // class is type of function

// to be precise, it's more like function constructor 
console.log(User === User.prototype.constructor); // true

// method declared in class is saved in User.prototype
console.log(User.prototype.sayHi); // alert(this.name);

// currently there are two method in prototype, constructor and sayHi(what we created)
console.log(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi

```
** **code within the class body**'s syntactic boundary is **_always executed in strict mode_**.
More about [Class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)

```js

class Animal {

  constructor(name) {
    this.speed = 0;
    this.name = name;
  }

  run(speed) {
    this.speed = speed;
    alert(`${this.name}is running with speed of ${this.speed} speed.`);
  }

  stop() {
    this.speed = 0;
    alert(`${this.name} stopped.`);
  }

}

class Rabbit extends Animal {
  hide() {
    alert(`${this.name}is hidden!`);
  }

  stop() {
    super.stop(); // this calls 'sto'p of parent Class and stops.
    this.hide(); // it hides.
  }
}

let rabbit = new Rabbit("White Rabbit");

rabbit.run(5); // white Rabbit is running speed of 5
rabbit.stop(); // White Rabbit stooped. White Rabbit id hidden! 

```
```js
class Article {
  constructor(title, date) {
    this.title = title;
    this.date = date;
  }

  static compare(articleA, articleB) {
    return articleA.date - articleB.date;
  }
}

// how to use
let articles = [
  new Article("HTML", new Date(2019, 1, 1)),
  new Article("CSS", new Date(2019, 0, 1)),
  new Article("JavaScript", new Date(2019, 11, 1))
];

articles.sort(Article.compare);

alert( articles[0].title ); // CSS
```

# Private class features
Class fields are **public by default**, but <u>private class members can be created by using a hash # prefix</u>. The privacy encapsulation of these class features is enforced by JavaScript itself.


```js
class CoffeeMachine {
  #waterLimit = 200;

  #checkWater(value) {
    if (value < 0) throw new Error("value for water cannot be negative.");
    if (value > this.#waterLimit) throw new Error("water value goes over the water limit.");
  }

}

let coffeeMachine = new CoffeeMachine();

// cannot reach to private from outside.
coffeeMachine.#checkWater(); // Error
coffeeMachine.#waterLimit = 1000; // Error
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n2ch6453ee0ir0levw1i.png)

Class is to create specific objects and there are properties and methods inside Class.


### instanceof 
The **`instanceof`** operator tests to see if the prototype property of a constructor appears anywhere in the prototype chain of an object. The return value is a boolean value.
```js
class Rabbit {} 
let rabbit = new Rabbit();
 // is rabbit instance of Rabbit?

console.log(rabbit instanceof Rabbit); // true    

let arr = [1, 2, 3];
console.log(arr instanceof Array); // true
console.log(arr instanceof Object); // true

    class Animal {}
class Rabbit extends Animal {}

let rabbit = new Rabbit();
console.log(rabbit instanceof Animal); // true

// rabbit.__proto__ === Rabbit.prototype
// rabbit.__proto__.__proto__ === Animal.prototype
// true
```

# Polyfill
A **_polyfill_** is a piece of code (usually JavaScript on the Web) used to provide modern functionality on older browsers that do not natively support it.
for instance, Babel includes a polyfill that includes a custom regenerator runtime and core-js.

### JavaScript does not support overloading. JavaScript supports overriding.
**_What is overloading?_** In some programming languages, function overloading or method overloading **is the ability to create multiple functions of the same name with different implementations. **
```js
function sum(x, y) {
  return x + y;
}

function sum(x, y, z) {
  return x + y + z;
}

sum(1,2)
// NaN

sum(1,2,3)
// 6
```
In most languages, sum(1,2) and sum(1,2,3) both will work.
However, it doesn't work in JavaScript as you can see.
From above code only function available is sum(x,y,z)
Because the second sum function's overridden the first one.
Overloading works depending on the parameters that are passed.
And <u>in the languages that support overloading, you need to declare the types of variable and parameters</u>. **However, you don't do that in JavaScript so it doesn't support overloading**.

[overloading vs overriding in JavaScript](https://stackoverflow.com/questions/34336995/overloading-vs-overriding-in-javascript)

# underscore in variable name
In some places, it's used to mark variable/function as private. (so that you know you shouldn't touch those variables)