Til Home

2020-07-30-TIL

Fact

  • 4일차!!

Feeling

  • 오늘도 힘든 하루였다.

Finding

  • dictionary는 다른 용도로 사용할 수 있는 데이터 유형이다. dictionary는 하나의 키와 하나의 값을 함께 제공한다. 자바스크립트 프로그래밍 언어는 dictionary 데이터 구조를 기본적으로 제공하지 않는다. 그러나 JavaScript Object type의 도움을 받아 dictionary 데이터 구조를 구현할 수 있다.
const dict = {};

혹은

const dict = {

   name: "gibong",

   email: "gibong@gmail.com",

   4: 1,

   "aar": "bbb",

   10: "val",

};

dictionary 쉽게 추가 하기

dict["email"] = "gibong@gmail.com";

dict[30]= "This ";

dict.FirstName="gibong";

console.log(dict)// { "email" : "gibong@gmail.com" , 30: "This ", FirstName: "gibong"}

삭제하기

delete dict.email;
delete dict[30];

console.log(dict)// { FirstName: "gibong"}

탐색

dict.FirstName // "gibong"
dict["FirstName"]; // "gibong"

수정

dict.FirstName = "a";
dict.FirstName // "a"
dict["FirstName"] = "b";
dict["FirstName"] // "b"

모든 키/값 뽑기

dict.FirstName = "a";
dict.SecondName = "b";
dict.LastName = "c"
Object.keys(dict) //["FirstName", "SecondName", "LastName"]

Object.values(dict) // ["a", "b", "c"]

배열로 키/값 다 뽑기

dict.FirstName = "a";
dict.SecondName = "b";
dict.LastName = "c"
Object.entries(a)//[[ 'FirstName', 'a' ], ['SecondName', 'b' ], [ 'LastName', 'c' ]]

출처

  • Object 클래스는 JavaScript의 데이터 유형 중 하나를 나타낸다. 다양한 키 컬렉션과 더 복잡한 엔터티를 저장하는 데 사용된다.
  • JavaScript의 거의 모든 객체는 객체의 인스턴스(instance)이며, 일반적인 객체는 Object.prototype에서 속성(methods 포함)을 상속한다.
  • Map 개체는 키 값 쌍을 보유하며 키의 원래 삽입 순서를 기억한다. 모든 값(개체와 원시 값 모두)은 키 또는 값으로 사용할 수 있다.
Map Object
의도치 않은 키 Map은 명시적으로 제공한 키 외에는 어떤 키도 가지지 않습니다. Object는 프로토타입을 가지므로 기본 키가 존재할 수 있습니다. 주의하지 않으면 직접 제공한 키와 충돌할 수도 있습니다.
키 자료형 Map의 키는 함수, 객체 등을 포함한 모든 값이 가능합니다. Object의 키는 반드시 String 또는 Symbol이어야 합니다.
키 순서 Map의 키는 정렬됩니다. 따라서 Map의 순회는 삽입순으로 이뤄집니다. Object의 키는 정렬되지 않습니다.
크기 Map의 항목 수는 size 속성을 통해 쉽게 알아낼 수 있습니다. Object의 항목 수는 직접 알아내야 합니다.
순회 Map은 순회 가능하므로, 바로 순회할 수 있습니다. Object를 순회하려면 먼저 모든 키를 알아낸 후, 그 키의 배열을 순회해야 합니다.
성능 잦은 키-값 쌍의 추가와 제거에서 더 좋은 성능을 보입니다. 잦은 키-값 쌍의 추가와 제거를 위한 최적화가 없습니다.
> const map = new Map
undefined

> map
Map {}

> map.set("asd", 1)
Map { 'asd' => 1 }

> map.set({}, 2)
Map { 'asd' => 1, {} => 2 }

> map.set(a => 5)
Map { 'asd' => 1, {} => 2, [Function] => undefined }

> map.set(a, 5)
Map {
  'asd' => 1,
  {} => 2,
  [Function] => undefined,
  { FirstName: 'name', SecondName: 'name2', LastName: 'name3' } => 5
}

> map.size
4

> map.get(a)
5

> map.get({ FirstName: 'name', SecondName: 'name2', LastName: 'name3' })
undefined

java object vs js object

const user = {
    "name": "Ray",
    "age": "20",
    "email": "randomemail@gmail.com"

}

js 에서는 {} 를 써서 쉽게 객체를 생성할 수 있다. new Object도 가능하긴 하다.

public class User {
  String name = "Ray";
  int age = 20;
  String email = "randomemail@gmail.com"

  public static void main(String[] args) {
     User user = new User();
   }
}

java 에서는 class를 선언 하고 그 class 를 써서 new 를 써서 만들어야 한다.

자바스크립트에서 this 키워드가 가리키는 객체는 런타임에 함수를 호출하는 방법에 따라 결정될 수 있다. 자바에서 this 키워드는 클래스에 의해 정의된 객체의 현재 인스턴스를 가리킨다.

js 에선 this 를 써서 global variable를 참조를 할 수 있다

var a = 1;
var getValue = function() {
  return this.a;
}
console.log(getValue()); //1;
function bike() {
   console.log(this.name);
}
var name = "one";
var obj1 = { name: "Pulsar", bike: bike };
var obj2 = { name: "Gixxer", bike: bike };
bike();           // "one"
obj1.bike();      // "Pulsar"
obj2.bike();      // "Gixxer"
public class truck {
  String color = "black";
  int speed = 30;

  //method for changing speed
  public void speedUp(int speed) {
    this.speed += speed;
  }
  //create object
  truck truck = new truck();
  //change speed
  truck.speedUp(30); //60
}

위의 예에서 speedUp 메서드가 호출되면 이 키워드는 우리의 새로운 truck 객체를 가리킨다. 그 결과 자바가truck 클래스를 전체적으로 컴파일하면 truck 클래스에서 상속받은 속도가 30씩 증가한다.

일반 Map과 hashMap 차이

맵은 해시맵이 구현하는 인터페이스다.

해시 함수 종류

해시는 가변 길이의 데이터를 해시 함수를 사용해 고정 길이의 해시 값을 만들어 내는 방법이다

MD5
MD5 는 128비트의 해시 값을 생성하는 해시 함수이다 MD5 함수는 매우 취약한 함수로 분류되어 해시테이블의 인덱스로 사용하거나 파일의 Checksum 생성 등의 한정된 용도를 제외한 사용자 암호 보존 용도의 사용을 권하지 않고 있다.

Salt
암호학에서 salt은 데이터, 암호 또는 암호를 해시하는 단방향 함수의 추가 입력으로 사용되는 임의의 데이터다. 염분은 저장소의 비밀번호를 보호하기 위해 사용된다. 역사적으로 비밀번호는 시스템의 일반 텍스트에 저장되었지만, 시간이 지남에 따라 사용자 비밀번호가 시스템에서 읽히지 않도록 보호하기 위해 추가적인 안전장치가 개발되었다. salt은 그런 방법들 중 하나이다.

Username password Salt value String to be hashed Hashed value = SHA256 (Password + Salt value)
user1 password123 E1F53135E559C253 password123E1F53135E559C253 72AE25495A7981C40622D49F9A52E4F1565C90F048F59027BD9C8C8900D5C3D8

SHA-256
SHA(Secure Hash Algorithm) 알고리즘의 한 종류로서 256비트의 해시 값을 생성하는 해시 함수이다

hashmap

array: 해시 함수를 사용하여 키를 어레이 인덱스 값에 매핑 최악: O(n), 평균: O(1) 이진 검색 트리: 자체 균형 이진 검색 트리를 사용하여 값 검색 최악: O(log n), 평균: O(log n)

ss 각각의 키는 해시 코드로 번역된다. 배열 크기가 제한적이기 때문에(예: 10), 계량함수를 사용하여 사용 가능한 버킷을 반복해야 한다. 우리는 버킷에 키/값 쌍을 저장하고, 만약 둘 이상이 있다면, 우리는 그것들을 보관하기 위해 컬렉션을 사용한다.

이상적인 해싱 알고리즘은 일정한 시간 액세스/조회를 가진다. 하지만, 해싱 기능을 실제로 완벽하게 달성하기는 어렵다. 동일한 인덱스에서 서로 다른 두 개의 키가 생성되는 경우가 있을 수 있다. 이것을 충돌이라고 한다.

어레이와 같은 기본 데이터 구조를 사용할 경우 해시맵의 충돌이 불가피하다. 이 충돌을 해결 하기 위해서 배열이나 linkedlist를 쓰는 방법이 있지만 이런거 쓰게 되면 결국엔 O(n)으로 갈 수 있다는 점.

이것을 피하기 위해서 할 수 있는점은 버켓 크기를 크게 만들던가, 해시 함수를 잘 구현하던가.

엄청난 양의 메모리를 할당하는 것은 비현실적이다. 그래서 우리가 할 수 있는 것은 해시 맵이 자동으로 load factor을 기준으로 크기를 조정하도록 하는 것이다. 이 작전은 Rehash라고 불린다.

load factor는 해시 맵이 얼마나 가득 찬지 측정하는 것이다. 우리는 버킷 사이즈로 항목 수를 나누면 load factor을 얻을 수 있다.

class HashMap {
  constructor(initialCapacity = 16, loadFactor = 0.75) {
    this.buckets = new Array(initialCapacity);
    this.loadFactor = loadFactor;
    this.size = 0;
    this.collisions = 0;
    this.keys = [];
  }
...
 set(key, value) {
   ...
    // check if a rehash is due
    if(this.loadFactor > 0 && this.getLoadFactor() > this.loadFactor) {
      this.rehash(this.buckets.length * 2);
    }

    return this;
  }
...
  rehash(newCapacity) {
    const newMap = new HashMap(newCapacity);

    this.keys.forEach(key => {
      if(key) {
        newMap.set(key.content, this.get(key.content));
      }
    });

    // update bucket
    this.buckets = newMap.buckets;
    this.collisions = newMap.collisions;
    // Optional: both `keys` has the same content except that the new one doesn't have empty spaces from deletions
    this.keys = newMap.keys;
  }

  getLoadFactor() {
    return this.size / this.buckets.length;
  }

출처

단위 테스트

“테스트는 배포하는 것보다 중요합니다. 테스트 없이 배포한다는 것은 당신이 짜놓은 코드가 언제든 오작동해도 이상하지 않다는 얘기와 같습니다.” - clean-code-javascript

모든 함수에 단위 테스트를 붙이는게 좋다. 거기에 통합 테스트도 붙이면 굿.

명확한 입출력이 있는 구조가 테스트 하기 쉽다.

Future Action

  • 구현 하다가 자잘자잘한것들을 너무 잘 빼먹는다. 다음에는 todo 를 체크리스트를 먼저 작성 하고 해보는것도 괜찮을것 같다.