Javascript Object

// Objects
// one of the JavaScript's data types.
// a collection of related data and/or functionality.
// Nearly all objects in JavaScript are instances of Object
// object = {key : value};

const name = 'dylan';
const age = 20;
function print(name,age) {
  console.log(name);
  console.log(age);
}

기본적으로 primitive 타입은 변수 하나당 값을 하나만 담을 수 있다. 이 경우에 만약 이름과 나이를 출력하고 싶은 함수를 만든다면, 이름과 나이를 파라미터로 전달해주어야 한다. 그리고 함수를 정의할때도 두 가지의 파라미터를 받아서 처리해주어야 한다. 조금 더 인자가 많아지면 각 파라미터당 추가해야할 것이 굉장히 많아지고, 그룹으로 묶어서 생각할 수가 없게된다.

이것을 개선하고자, 자바 스크립트에서는 Object를 사용한다.

function print(person){
  console.log(person.name);
  console.log(person.age);
}
const dylan = {name: 'dylan', age: 20};
print(dylan);

오브젝트를 만드는 방법

const obj1 = {}; //'object literal' syntax
const obj2 = new Object(); // 'object constructor' syntax (Object 클래스 내의 constructor 호출을 이용하여 만듬)

Dynamic type

자바스크립트는 동적으로 런타임때 타입이 결정된다. 그래서 이미 오브젝트에서 이름과 나이를 정의했음에도 불구하고, 뒤늦게 프로퍼티를 추가하거나 삭제 할 수 있다. 이 특징은 빠르게 제작하는데는 도움이 될지 모르겠지만, 나중에 유지보수나 디버깅 측면에서는 좋지 않다.

const dylan = {name: 'dylan', age: 20};
dylan.hasJob = true;
console.log(dylan.hasJob); // true
delete dylan.hasJob;
console.log(dylan.hasJob); //undefined;

Computed properties

//  key should be always string
const dylan = {name: 'dylan', age: 20};

console.log(dylan.name); //dylan
console.log(dylan['name']); //dylan (computed properties)

dylan['hasJob'] = true;
console.log(dylan.hasJob); //True

코딩하는 그 순간 키에 해당하는 값을 받아오고 싶을때는 dylan.name과 같이 사용하고, Dylan[‘hasJob’] (computed properties)를 사용하는 것은 키 값이 런타임에서 결정될때 computed properties를 사용한다. 예를 들어, 실시간으로 원하는 키 값을 받아오고 싶을때 사용한다.

실시간으로 원하는 키를 받아올땐 배열에서 받아오듯 dylan[‘name’] (computed properties)를 사용

const dylan = {name: 'dylan', age: 20};
// 다음 함수는 obj, key 파라미터를 받아와서 출력하는 함수인데, key는 사용자로부터 입력을 받는 인자로, 코딩하는 시점에서는 알 수 없음
function printValue(obj, key){
  console.log(obj.key); // undefined;
  console.log(obj[key]); //  정상 출력
}
printValue(dylan,'name');

// 보통의 경우, 그냥 obj.key 를 쓰는게 맞지만, 동적으로 키에 관련된 value를 받아와야할때 obj[key]로 사용

Property value shorthand

const person1 = {name : 'bob' ,  age: 2};
const person2 = {name: 'steve', age: 3};
const person3 = {name: 'dave', age: 4};
const person4 = makePerson('dylan',20); // 조금 더심플하게 만드는 방법

function makePerson(name, age) {
  return {
//    name: name,
//    age: age (생략 가능)
    name,
    age,
  }
}

오브젝트를 필요할 때 일일이 만들게 되면, 불가피하게 동일한 key와 value들을 반복해서 작성해야되는 문제점이 있다.
그래서 값만 전달해주면 오브젝트를 만들어주는 makePerson 이라는 함수를 만들었는데, 이것은 들여다보면 클래스와 비슷하다. 이전에 자바 스크립트에 클래스가 없었을 때는 이런 식으로 많이 작성이 되었다고 한다.

사실 Class 자체도 Object 를 상속받은 것이므로, 동일하다고 보면 될 거같다.

Constructor function

이렇게 보통 다른 계산을 하지 않고, 순수하게 오브젝트를 생성하는 함수들은 대문자로 시작하도록 함수를 만든다.
또 return은 생략하고 클래스 constructor와 같이 정의한다.

function Person(name,age){
  //this = {}; 생략
  this.name = name;
  this.age = age;
  //return this; 생략
}
const person4 = new Person('dylan',20);

In operator

// in operator: property existence check (key in obj)
console.log('name' in dylan); //True
console.log('age' in dylan); //True
console.log('random' in dylan); //False

For in , For of

// for(key in obj)
for (key in dylan){
  console.log(key); // 오브젝트내의 모든 키 출력
}

// for (value in obj)
for (key in dylan){
  console.log(dylan[key]);
}

// for (value of iterable)
const array = [1,2,4,5];
for(value of array) {
  console.log(value); // 배열내의 모든 값 출력
}

Fun cloning

//Object.assign(dest, [obj1, obj2, obj3 ...])
const user = {name: 'dylan', age: 20};
const user2 = user;
user2.name = 'coder';
console.log(user.name); //coder

변수 user에는 name: dylan, age: 20 이 할당되어 있는 메모리를 가리키고 있는 참조값 ref이 들어있는데 이것을 변수 user2에 그대로 할당했으므로 user2 변수 내에도 name:dylan, age:20을 가리키고 있는 ref가 그대로 들어간다. 그래서 user2.name을 바꾼다는 것은 곧 ref이 가리키고 있는 곳의 값을 바꾸는 것이 되고, user에도 영향을 미치게 된다.

참고 ) number, string, boolean, null, undfined 의 데이터 타입은 사이즈가 작기때문에 메모리에 그대로 올라가지만, object의 데이터들은 따로 다른 메모리에 올라가있고 그 주소(reference)를 가지고 있다.

배열, 함수 등도 전부 Object로 볼 수 있다.

이것을 방지하기 위해 오브젝트를 복사하는 방법을 사용한다.

// old way
const user3 = {};
for (key in user) {
  user3[key] = user[key];
}
console.log(user3); // name:"dylan", age: 20

//Object.assign 사용
//const user4 = {};
//Object.assign(user4,user);
const user4 = Object.assign({},user);
console.log(user4); // name:"dylan", age:20

//another example
const fruit1 = {color: 'red'};
const fruit2 = {color: 'blue', size: 'big'};
const mixed = Object.assign({}, fruit1, fruit2); // 뒤에 나오는 것을 덮어 씌움
console.log(mixed.color); // blue
console.log(mixed.size); // big