코어 자바스크립트 (데이터 타입)

L·2022년 10월 26일
0

코어자바스크립트

목록 보기
1/6

데이터 타입

1.데이터 타입 종류

기본형

숫자(Number), 문자열(String), Boolean, null, undefined, Symbol(ES6 추가)

참조형(객체)

객체(Object), 배열(Array), 함수(Function), 날짜(Date), 정규식(RegExp), Map(ES6 추가), Set(ES6 추가), WeakMap(ES6 추가), WeakSet(ES6 추가)

차이점

  • 일반적으로 기본형과 참조형의 차이는 할당시 값이 복제되느냐 또는 주소값이 복제 되느냐의 차이가 있는것으로 알고있지만, 사실은 둘다 복제를 하고있음. 다만 기본형은 값이 담긴 주소값을 복제하는 한편, 참조형은 주소값들이 묶음을 가리키는 주소값을 복제한다는 점이 다름.

2. 데이터 타입 배경지식

  • 식별자는 데이터를 식별하는데 사용 하는 이름(=변수명)
  • 변수는 변할수 있는 무언가(=데이터)
  • 즉 변수는 변경 가능한 데이터를 담을수 있는 공간으로 정의 할수 있음.

3. 변수 선언과 데이터 할당

1. 변수 선언

기본적인 변수 선언 (=식별자 age 라는 이름을 가진 변할 수 있는 데이터를 만든다)
컴퓨터가 메모리에서 비어 있는 공간을 할당 하여, 1002번이라는 임의의 공간에 age라는 식별자 이름을 가진 변수를 지정함.

var age;
주소100110021003
데이터이름:age,값:''

2.데이터 할당

  • 데이터를 저장하기 위해 별도의 메모리공간을 확보하여 할당한 값을 저장하고 그 주소값을 변수 영역에 저장하는 방식으로 이루어짐.

    var age = 30;
    • 주소영역

      주소...10021003
      데이터이름:age,값:'@5003'
    • 데이터영역

      주소50025003
      데이터30

데이터 할당 과정
1.변수 영역에 빈공간을 확보(@1002)
2.확보된 공간(@1002)에 식별자 age로 지정.
3.데이터 영역의 빈공간(@5003)에 숫자 30을 지정.
4.변수 영역에서 age식별자를 검색.(@1002).
5.앞서 저장한 숫자의 주소(@5003)를 @1002의 공간에 대입.

  • 변수 변경의 과정

    var age = 30;
    age = 100;
  • 주소영역

    주소...10021003
    데이터이름:age,값:'@5002 -> @5003'
  • 데이터 영역

    주소50025003
    데이터30100

    데이터 변경 과정

    1. 데이터 영역에 빈공간 확보(@5004)
    2. @5004 공간에 숫자 100을 저장.(이때, 문자열을 변경한다고하면, 문자열의 값을제거해도 무조건 새공간에 데이터를 저장함)
    3. @5004 영역은 age 식별자를 가진 변수 영역을 탐색.
    4. 변수영역에서 해당 식별자를 찾았다면, 주솟 값을 @5003에서 @5004로 변경.

4.기본형 데이터와 참조형 데이터

4-1. 불변값

  • 변수와 상수의 구분하는 것은 변경 가능성.(대상은 변수 영역에 메모리이며, 한번 할당된 변수공간에 다른 데이터를 재할당 할 수 있는지 여부.)

    불변값 ≠ 상수 는 다른 개념. 불변성 여부를 구별할떄 변경 가능성의 대상은 데이터 영역 메모리.

  • 위에 데이터 변경과정에서도 보듯, 한번 생성된 데이터 영역은 값을 아무리 변경하더라도, 기존에 저장된 데이터 영역은 변경되지않고, 기존 데이터 영역에 값이 있으면, 재활용하고 없으면, 새로운 영역에 만든다음, 식별자에서 주소값을 변경하는 식으로 저장을 한다고 이해.( 기본형 데이터 타입인 숫자, 문자열 ,boolean, null, undefined, symbol은 모두 불변값임. )

4-2. 가변값

1) 참조형의 데이터 할당

var jumin={
  name:'cheolsu',
  age: 30
}
  • 변수영역
주소...10021003
데이터이름:jumin,값:'@5002'

  • 데이터 영역
주소50025003
데이터@7103~'cheolsu'

  • 객체 @5002의 변수 영역
주소71037104
데이터이름:name, 값: @5003이름: age, 값: @5004

참조형 데이터 할당 과정
1. 변수영역에 빈 공간(@1002)을 확보.
2. 프로퍼티를 저장하기 위한 별도의 데이터 영역에 빈 공간(@5002)을 확보하여 그 영역의 주소(@7103~ ?)를 저장.
3. @7103 및 @7104에 각각 프로퍼티이름을 지정.
4. 데이터 영역에서 'cheolsu'값을 검색하여 임의로 @5003에 저장하여, 이 주소값을 @7103 영역의 값으로 저장. 값 30도 마찬가지로 검색하여 임의로 @5004로 저장한다음, 이 주소값을 @7104 영역의 값으로 저장.

2) 참조형 데이터의 프로퍼티 재할당

var jumin={
  name:'cheolsu',
  age: 30
}
jumin.age = 31;
  • 변수영역 (불변)
주소...10021003
데이터이름:jumin,값:'@5002'

  • 데이터 영역
주소5002500350045005
데이터@7103~'cheolsu'3031

  • 객체 @5002의 변수 영역
주소71037104
데이터이름:name, 값: @5003 -> @5005이름: age, 값: @5004

★ 변수영역에 주솟값은 불변.
데이터 영역에 31이라는 값이 있다면, 해당 영역 재활용 그렇지않으면 새로운 영역을할당하여 31을 넣고, 해당 주솟값을 @7105의 변수영역에 저장.

즉, 참조형은 변수안 프로퍼티의 값이 바뀌어도 변수영역에서 식별자 jumin의 주솟값은 변경이 되지않음.

3) 중첩된 참조형 데이터(객체)의 프로퍼티 할당( 객체안에 객체 )

var jumin={
  name:'cheolsu',
  age:31,
  address:'서울시 마포구',
  addressHistory:['서울시 용산구','서울시 성동구','서울시 마포구']
}
  • 변수영역
주소100110021003
데이터이름:jumin,값:'@5002'

  • 데이터 영역
주소5001500250035004500550065007
데이터@7103~'cheolsu'31'서울시 마포구'@8101~'서울시 용산구''서울시 성동구'

  • 객체 @5001의 변수 영역
주소7103710471057106
데이터이름:name, 값: @5002이름: age, 값: @5003이름:address, 값:@5004이름:addressHistory, 값:@5005

  • 객체 @5005의 변수 영역
주소810181028103
데이터이름:0, 값: @5007이름: 1, 값: @5008이름:2, 값: @5004

중첩된 참조형 데이터 할당 과정

  1. 변수영역에 빈 공간(@1001)을 확보.
  2. 프로퍼티를 저장하기 위한 별도의 데이터 영역에 빈 공간(@5001)을 확보하여 그 영역의 주소(@7103~ ?)를 저장.
  3. @7103, @7104, 7105에 각각 프로퍼티이름(name,age,addressHistory)을 지정.
  4. 데이터 영역에서 'cheolsu'값을 검색하여 임의로 @5002에 저장하여, 이 주소값을 @7103 영역의 값으로 저장. 값 31도 마찬가지로 검색하여 임의로 @5003로 저장한다음, 이 주소값을 @7104 영역의 값으로 저장. @7105에 이름 address를 저장하고 '서울시 마포구'를 검색하여 임의로 @5004로 저장한다음, 이 주소값을 @7105 영역의 값으로 저장.
  5. @7106의 addressHistory는 배열이 저장되기 떄문에, 이를 저장하기위한 별도의 변수영역을 추가.(@8101~)
  6. 배열의 길이만큼 변수 공간을 확보하고 이름에 인덱스 부여.
  7. 데이터 영역에 'cheolsu'를 검색하여 나온 주솟값(@5002)를 @7103에 저장.
  8. 데이터 영역에 'age'를 검색하여 나온 주솟값(@5003)를 @7104에 저장.
  9. 데이터 영역에서 '서울시 용산구'가 없으므로 @5006영역에 저장.
  10. 데이터 영역에서 '서울시 용산구' 값을 검색하여 @8101영역에 값 추가.
    11.데이터 영역에서 '서울시 성동구'가 없으므로 @5007영역의 @8101저장.
  11. 데이터 영역에서 '서울시 용산구' 값을 검색하여 @8102영역에 값 추가.
  12. 데이터 영역에서 '서울시 마포구' 값을 검색하여 @8103 영역에 추가.

4) 변수 복사

var a = 10;
var b = a; 

var obj1={
  c:'cccc',
  d:100
};
var obj2 = obj1;
  • 변수영역
주소1001100210031004
데이터이름:a,값:'@5001'이름:b,값:'@5001'이름:obj1,값:'@5002'이름:obj2,값:'@5002'

  • 데이터 영역
주소5001500250035004500550065007
데이터10@7101~cccc100

  • 객체 @5002의 변수 영역
주소7101710271037104
데이터이름:c, 값: @5003이름: d, 값:@5004

주소 복사 과정(기본형)
1. 식별자 a를 @1001에 지정. 값 10이 데이터 영역에 없기때문에 @5001에 지정. 식별자 a를 가진 변수영역을 찾아 해당 데이터영역 주소값을 넣음.
2. 식별자 b를 @1002에 저장. 값 10이 데이터 영역에 있기 때문에 해당 데이터영역 주소 값을(@5001) 저장.

주소 복사 과정(참조형)
1. 식별자 obj1을 @1003에 저장. 객체 안에 있는 값을 저장하기 위한 obj1프로퍼티 별도의 변수영역 주소값을 데이터 영역에 지정(@5002)
2. @7101~7102 영역에 프로퍼티명 지정. 해당 값이 없을때는 데이터 영역에 새로추가(@5003,5004). 각 프로퍼티명을 가진 객체의 변수영역을 찾아 해당 데이터영역 주소값을 넣음.
3.식별자 obj2을 @1004에 저장. 식별자 @obj1을 찾아 해당 변수영역 주소값을 넣음.

  • 기본형과 참조형의 복사과정은 동일하게 이루어 지나, 변수가 변경될때 과정에서 차이가 있음.

    var a = 10;
    var b = a; 
    var obj1={
    c:'cccc',
    d:100
    };
    var obj2 = obj1;
    b=100;
    obj2.d=50;
  • 변수영역

    주소1001100210031004
    데이터이름:a,값:'@5001'이름:b,값:'@5001 -> 5004'이름:obj1,값:'@5002'이름:obj2,값:'@5002'

  • 데이터 영역

    주소5001500250035004500550065007
    데이터10@7101~cccc100@8101~?50

  • 객체 @5002의 변수 영역

    주소7101710271037104
    데이터이름:c, 값: @5003이름: d, 값:@5004->5005

    기본형
    1.식별자 a를 @1001에 지정. 값 10이 데이터 영역에 없기때문에 @5001에 지정. 식별자 a를 가진 변수영역을 찾아 해당 데이터영역 주소값을 넣음.
    2.식별자 b를 @1002에 저장. 값 10이 데이터 영역에 있기 때문에 해당 데이터영역 주소 값을(@5001) 저장.
    3.데이터 100이 데이터 영역에 있으므로 변수영역에 있는 식별자 b의 주솟값을 해당 주솟값으로 변경.

    참조형
    1.식별자 obj1을 @1003에 저장. 객체 안에 있는 값을 저장하기 위한 obj1프로퍼티 별도의 변수영역 주소값을 데이터 영역에 지정(@5002)
    2.@7101~7102 영역에 프로퍼티명 지정. 해당 값이 없을때는 데이터 영역에 새로추가(@5003,5004). 각 프로퍼티명을 가진 객체의 변수영역을 찾아 해당 데이터영역 주소값을 넣음.
    3.식별자 obj2을 @1004에 저장. 식별자 @obj1을 찾아 해당 변수영역 주소값을 넣음.
    4.데이터 영역에 50값을 담기위한 영역 추가(5006)
    5.obj2의 변수영역에서 d가 변경되어 프로퍼티 d의 데이터 영역 주소값이 변경.

    • 해당 과정의 결과 기본형은 변수영역의 주소값이 서로 달라졌지만, 참조형 데이터는 프로퍼티의 영역을 담고있는 주소값이 변경되지않았기 때문에, obj2객체의 d 프로퍼티 값을 변경했어도, obj1객체의 d프로퍼티 값도 같이 변경이 됨. 즉, 이 결과를 아래와 같은 코드로 표현이 가능.
      a !== b
      obj1 === obj2
  • 객체 전체를 변경했을때

    var a = 10;
    var b = a; 
    var obj1={
      c:'cccc',
      d:100
    };
    var obj2 = obj1;
    b=100;
    obj2={ c:'dddd',d:50};
  • 변수영역

    주소1001100210031004
    데이터이름:a,값:'@5001'이름:b,값:'@5001 -> 5004'이름:obj1,값:'@5002'이름:obj2,값:'@5002->5005'

  • 데이터 영역

    주소5001500250035004500550065007
    데이터10@7101~cccc100@8101~?dddd50

  • 객체 @5002의 변수 영역

    주소7101710271037104
    데이터이름:c, 값: @5003이름: d, 값:@5004

  • 객체 @5005의 변수 영역

    주소8101810281038104
    데이터이름:c, 값: @5006이름: d, 값:@5007

    기본형
    1. 식별자 a를 @1001에 지정. 값 10이 데이터 영역에 없기때문에 @5001에 지정. 식별자 a를 가진 변수영역을 찾아 해당 데이터영역 주소값을 넣음.
    2.식별자 b를 @1002에 저장. 값 10이 데이터 영역에 있기 때문에 해당 데이터영역 주소 값을(@5001) 저장.
    3.데이터 100이 데이터 영역에 있으므로 변수영역에 있는 식별자 b의 주솟값을 해당 주솟값으로 변경.

    참조형
    1.식별자 obj1을 @1003에 저장. 객체 안에 있는 값을 저장하기 위한 obj1프로퍼티 별도의 변수영역 주소값을 데이터 영역에 지정(@5002)
    2.@7101~7102 영역에 프로퍼티명 지정. 해당 값이 없을때는 데이터 영역에 새로추가(@5003,5004). 각 프로퍼티명을 가진 객체의 변수영역을 찾아 해당 데이터영역 주소값을 넣음.
    3.식별자 obj2을 @1004에 저장. 식별자 @obj1을 찾아 해당 변수영역 주소값을 넣음.
    4.객체에 새로운값을 저장하기위한 obj2의 프로퍼티 별도 주소변수 영역값을 데이터에 지정(@5005)
    5.@8101~8102 영역에 프로퍼티명 지정. 해당 값이 없을때는 데이터 영역에 새로추가(@5006,5007). 각 프로퍼티명을 가진 객체의 변수영역을 찾아 해당 데이터영역 주소값을 넣음.
    6.식별자 obj2의 기존 주소값을 새로 할당한 변수영역의 주소값으로 변경.

참조형 데이터가 '가변값'인 경우는 데이터 자체(객체)변경이 아닌 객체 내부의 프로퍼티를 변경 할때만 성립.


5.불변 객체

1) 불변 객체를 만드는법

  • 불변 객체는 전달받은 객체를 변경하더라도, 원본객체는 변하지말아야함. 위에 4) 변수복사 에서 보듯이, 변경할객체를 선언하고 원본 객체 복사 후, 복사한 객체에 값을 변경하면, 가변성으로 인한, 원본객체 값도 같이 변함. 그래서 불변 객체를 리턴하고 싶다면, 아래 3가지 방법을 활용.

1.Object형 리턴
2.비구조화 할당
3.Object.assign 메소드 활용

var user1={
  name:'cheolsu',
  gender:'male'
};

var changeName = function(user,newName){
	return{
      name:newName,
      gender:user.gender
    };
  /**비구조화 할당을 통한 불변객체 리턴(객체안에 많은 내용이있을때)
  	return{
    ...user,
    name:newName
    }
  */
  /**1.Object.assign
  return Object.assign({},user,{name:newName})
  */
  	
}

var user2 = changeName(user1,'Lee');
if(user1 !== user2){
  console.log('유저 정보가 변경되었습니다.');
}
console.log(user.name,user2.name);//'cheolsu','Lee'
console.log(user1 === user2);//false

2) 얇은 복사 vs 깊은 복사

  • 얇은 복사는 아래 단계의 값만 복사. 만약에 중첩된 객체가 있다면, 중첩된 객체의 주소값은 동일한 주소값이 되기떄문에 참조형 변수의 가변성에 의해 원본이 변경되면, 복사본의 값도 변경이 됨.
function copyObject(target){
  var result={};
  for(var prop in target){
    result[prop]=target[prop];
  }
  return result; 
}
var user={
  name:'cheolsu',
  urls:{
    blog:'http://blog.naver.com'
  }
};
var user2=copyObject(user);

user2.name = 'Lee'
console.log(user2.name === user.name);//false

user2.urls.blog='https://velog.io';
console.log(user2.urls.blog === user.urls.blog);//true
  • url객체의 불변성을 보장하기 위해 url객체 자체를 복사해서 할당하는 소스 추가.(user2.url = copyObject(user.urls))

  • 깊은복사는 중첩된 객체까지 전부 찾아서 복사하는 방법.

var copyObject=function(target){
  var result={};
  if(typeof target === 'object' && target !== null){
  	for(var prop in target){
      result[prop]=copyObject(target[prop]);
    }
  }else{
    result = target;
  }
  
  return result; 
}
var user={
  name:'cheolsu',
  urls:{
    blog:'http://blog.naver.com'
  }
};
var user2=copyObject(user);

user2.name = 'Lee'
console.log(user2.name === user.name);//false

user2.urls.blog='https://velog.io';
console.log(user2.urls.blog === user.urls.blog);//false
  • ✓ JSON.stringify(object)를 통해 간단하게 깊은 복사 가능.

6.undefined와 null

  • 둘다 '없음'을 나타내는 값.
  • undefined
    • 값을 대입하지않은 변수.(변수영역에 식별자는 있으나 값에 데이터영역 주소값이 들어가지않은 상태)
    • 객체내부에서 존재하지않는 프로퍼티 접근시 리턴되는 값.
    • return값이 없거나 호출되지않는 함수 실행결과
    • 길이는 있지만 값은 비어있는 배열에서는 값이 [empty * 배열길이] 로 나오는 경우가 있는데, 이때 배열객체를 가진 변수는 undefined 그 자체가 아닌 비어있는 요소를 가진 객체로 보는게 맞음.
    • 값을 대입하지 않은 변수에 접근하고자 할때 자바스크립트 엔진이 반환해주는 값.
  • null
    • '비어있음'의 명시적 의미를 쓰고시다면 null을 사용.(케바케지만, 책에서는 표현을 위해서는 undefined를 지양하고있음)
    • typeof null 을 로그로 찍을떄 object가 나옴.(JS 자체 버그) 정확한 확인을 위해서는 ===(일치연산자)를 통한 비교를 해야함.

0개의 댓글