변수란? 변할 수 있는 데이터(숫자, 문자열, 객체, 배열 )이다. 변수란 결국 변경가능한 데이터가 담길 수 있는 공간 또는 그릇이라 생각하면 된다.
03. 변수 선언과 데이터 할당
var a;
a='abc'
var a= 'abc';
변수를 선언하고 데이터를 할당하면 해당위치에 값('abc')을 직접 저장하지 않는다.
데이터를 저장하기 위한 별도의 메모리 공간을 확보해서 값을 저장하고 그 주소를 변수영역에 저장하는 식으로 이루어 진다.
변수영역에 값을 직접 대입하지 않는 이유는 데이터 변환을 자유롭게 할 수 있게 하고 , 메모리를 효율적으로 관리하기 위해서이다.
미리 확보한 공간 안에서만 데이터 변환을 할 수 있다면, 변환된 데이터를 위해 확보된 공간을 조정하는 작업이 필요하게 된다.
따라서 컴퓨터가 처리해야할 연산은 많아지게 되고, 효율적으로 문자열 데이터의 변환을 처리하게하기 위해 변수와 데이터를 별도의 저장공간에 나누어 저장하는 것이다.
04. 기본형 데이터와 참조형 데이터
변수와 상수를 구분짓는 기준은 무엇인가?
흔히 바꿀 수 있다면 변수, 바꿀 수 없다면 상수로 생각하기 쉽다.
변수와 상수를 구분 짓는 변경 가능성의 대상은 변수 영역 메모리이다.
한 번 할당이 이루어진 변수 공간에 다른데이터를 재할당 할 수 있는지가 관건이라는 의미이다.
반면 불변성 여부를 구분할 때의 변경 가능성의 대상은 데이터 영역 메모리이다.
var a = b;
위의 설명이 잘 이해가 가지 않아 스터디원들과 논의를 하고 이해한 방식을 설명해본다.
위 코드에서 var a는 변수영역 메모리 부분, b는 데이터 영역 메모리 부분이다.
"var a라는 변수영역 메모리에 다른 데이터를 재할당할 수 있는가?" 에 대한 응답으로 변수와 상수를 구분짓게 된다.
또한 "b가 변경이 가능한가"에 대한 응답에 따라 불변성 여부가 결정된다.
기본형 데이터는 모두 불변값이다.
var b = 5;
var c = 5;
b = 7;
변수 b에 숫자 5을 할당하고자 컴퓨터는 데이터 영역에서 5를 찾고 없다면 데이터 공간을 하나 만들어 저장하게된다.
c는 이미 만들어 놓은 값이 있으니 이를 재활용하였다.
변수 b의 값을 7로 바꾸고자 하였다. 이는 5가 저장된 데이터 공간에 값을 바꾸는 것이아니라, 기존에 저장했던 7을 찾고 없다면 새로 만들어서 b에 저장하는 것이다.
즉, 변경은 새로만드는 동작을 통해서만 이루어진다(가비지 컬렉팅을 당하지 않는 한 영원히 변하지 않는다. )
참조형데이터는 모두 가변값인가?
기본적인 성질은 가변값인 경우가 많지만 불변값을 활용가능하다.
참조형 데이터가 가변값이라고 설명할 때의 '가변'은 참조형 데이터 자체를 변경할 경우가 아니라 그 내부의 프로퍼티를 변경할 때만 성립한다.
기본형 데이터와 참조형 데이터의 차이는 참조형 데이터는 객체의 변수 영역이 별도로 존재한다는 점이다.
기본형은 값을 복사하고 참조형은 주솟값을 복사한다.
하지만 기본형은 주솟값을 복사하는 과정이 한 번만 이루어지고, 참조형은 한 단계를 더 거치게 된다.
(기본형도 결국 주소값을 복사한다 !!!! - 어려움 ㅠ)
05.불변객체
불변객체가 필요한 경우
정보가 바뀐 시점에 알림을 보내야 할 때
바뀌기 전 정보와 바뀐 후의 정보의 차이를 가시적으로 보여줘야하는 경우
얕은 복사와 깊은 복사
얕은복사 : 바로 아래 단계의 값만 복사하는 방법이다. 이말은 중첩된 객체(객체 안에 객체가 있는경우)에서 참조형 데이터가 저장된 프로퍼티를 복사할 때 그 주솟값만 복사한다. (이렇게 되면 원본과 사본은 모두 동일한 참조형 데이터의 주소를 가르키게 되고 그에따라 원본 바꾸면 사본도 바뀜..)
깊은 복사 : 내부의 모든 값들을 하나하나 찾아서 전부 복사한다.
var user = {
name : 'suzin',
urls: {
portfolio: 'http:// ~,
blog: 'http://blog.com'
}
var user2 = copyObject(user);
user2.name = 'jang';
console.log(user.name === user2.name); // false
user2.urls.protfolio = 'http://protfolio.com';
console.log(user.urls.protfolio === user2.urls.protfolio); //true
위 예제에서 user2의 name을 바꾸어도 user의 name 프로퍼티는 바뀌지 않았다.
즉, user 객체에 직접 속한 프로퍼티에 대해서는 복사해서 완전히 새로운 데이터가 만들어진 반면, 중첩객체인 url의 내부 프로퍼티들은 기존데이터를 그대로 참조한다 !!
때문에 user.urls 프로퍼티에 대해서도 불변객체로 만들어야한다.
요약하자면, 객체의 프로퍼티 중에서 그 값이 기본형 데이터일 경우에는 그대로 복사해도 된다. 하지만 참조형데이터는 다시 그 내부의 프로퍼티들을 복사해야한다.
*깊은 복사를 처리할 수 있는 쉬운방법*
var copyObjectViaJSON = function (target) {
return JSON.parse(JSON.stringify(target))
};
객체를 json 문법으로 표현된 문자열로 전환했다가 다시 json객체로 바꾸는 것 !
06. undefind 와 null
자바스크립트 엔진은 사용자가 어떤값을 지정할 것이라고 예상되는 상황임에도 실제 그렇게 하지 않았을때 undefind를 반환한다.
혼란을 줄이려면 직접 undefined를 할당하지 않으면 된다.
--> (왜냐하면 자바스크립트엔진이 반환해주니까 !)
비어있음을 나타내고 싶을 때는 undefined보다 null을 사용하자. (주의 . typeof null 은 object임)