May 08, 2020
33-js-concepts를 스터디하며 정리한 포스트 입니다.
자바스크립트에서 값 타입(Value Type)은 원시 타입(Primitive Type)과 비슷하다.
아래의 6가지 데이터 타입을 자바스크립트에서 값 타입(Value Type)이라고 한다.
Boolean
(true
, false
)null
undefinded
number
(1
, 1000
, 3.14
)string
("Primitive"
, 'Type'
)symbol
(Symbol()
, Symbol(42)
, Symbol('foo')
)모든 값 타입(Value Type)은 값을 표현하는 리터럴(literal) 형식이 존재한다.
리터럴(Literal)은 데이터 그 자체를 의미한다.
아래와 같이 변수에 저장하는 변하지 않는 데이터를 뜻한다.
var numberVar = 1
var stringVar = 'string'
var booleanVar = true
위의 코드에서 리터럴(Literal)은 1
과 "string"
, true
다.
자바스크립트에서 이러한 값 타입(Value Type)은 리터럴(Literal) 그대로 저장된다.
var lunch = 'pizza'
var dinner = lunch
console.log(lunch) // "pizza"
console.log(dinner) // "pizza"
위의 예제에서 lunch
변수는 "pizza"
라는 문자 리터럴을 가지고 있다.
lunch
가 가지고 있는 데이터를 대입연산자(=
)를 이용해 dinner
변수에 대입하였다.
그 결과 dinner
변수 또한 "pizza"
라는 문자 리터럴을 가지고 있게 되었다.
크롬 개발자 도구에서 메모리 할당 스냅샷을 찍어 확인해 보면 아래와 같다.
lunch
변수와 dinner
변수가 같은 문자열 데이터 메모리를 가지고 있다.
이 상황에서 lunch
에 저장된 값을 다른 값으로 변경시키면 어떻게 될까?
lunch = 'chicken'
console.log(lunch) // "chicken"
console.log(dinner) // "pizza"
위의 상황과 동일하게 크롬 개발자 도구의 메모리를 확인해보았다.
lunch
의 값을 chicken
이라는 값으로 변경했음에도 dinner
의 값은 변하지 않았다.
또한 launch
와 dinner
두 변수 모두 다른 메모리 주소를 가리키고 있다.
이 결과를 확인하면서 자바스크립트에서의 값 타입의 저장 방식을 확인할 수 있다.
값 타입은 메모리를 참조해 저장하는 것이 아니라 값을 그대로 저장한다.
참조 타입(Reference Type)은 값 타입이 아닌 모든 데이터 타입을 말한다.
대표적으로 아래의 4가지 데이터 타입이 참조 타입이다.
object
({foo: "bar"}
)array
([1, 2, 3, 4]
)function (object)
(function foo() { }
)class
(class foo { }
)참조 타입(Reference Type)을 정의하는 방법은 값 타입과 동일하다.
{}
(객체 리터럴)이나 []
(배열 리터럴)을 사용하거나 new
함수를 사용할 수 있다.
var objectVar = {}
var arrayVar = []
var funcVar = function() {}
var classVar = class {}
var usingNewOjbect = new Object()
var usingNewArray = new Array()
console.log(typeof objectVar) // object
console.log(typeof arrayVar) // object
console.log(typeof funcVar) // function
console.log(typeof classVar) // funcion
console.log(typeof usingNewOjbect) // object
console.log(typeof usingNewArray) // object
대입 연산자(=
)를 이용해 사용할 object
나 array
, function
을 대입하면 된다.
자바스크립트에서의 배열(array
)과 함수(function
)는 모두 객체(object
)다.
추후에 정리를 하겠지만 자세한 내용은 아래의 링크를 확인해보면 좋을 것이다.
자바스크립트 함수 (1) - 함수 객체, 함수 객체 생성
> JavaScript에서는 배열(Array)도 객체(Object)다
> [스터디_자바스크립트] 12. 함수도 객체이다!
사람의 정보를 갖는 객체 person
을 생성하고 newPerson
변수에 =
를 사용해 저장했다.
값 타입(Value Type)과 동일하게 두 개의 변수에는 같은 값이 들어가 있다.
var person = {
name: 'minsu',
age: 22,
job: 'Developer',
}
var newPerson = person
console.log(person) // {name: "minsu", age: 22, job: "Developer"}
console.log(newPerson) // {name: "minsu", age: 22, job: "Developer"}
동일하게 크롬 개발자 도구의 메모리 영역을 확인해보았다.
newPerson
과 person
의 메모리 주소가 @176907
로 같은 것을 확인할 수 있다.
여기까지는 이전의 값 타입과 별 다른 차이가 없다.
여기에서 person
변수의 job
을 변경시켜보았다.
person.job = 'Front-End Developer'
console.log(person) // {name: "minsu", age: 22, job: "Front-End Developer"}
console.log(newPerson) // {name: "minsu", age: 22, job: "Front-End Developer"}
분명 person
의 job
의 값만 변경시켰을 뿐인데 newPerson
의 값 또한 변경되었다.
참조 타입은 리터럴을 저장하는 것이 아니라 리터럴의 메모리 주소를 저장하고 있기 때문이다.
값이 어떻게 변하였는지 크롬 개발자 도구의 메모리 영역을 확인해보았다.
값 타입에서 값을 변경했을 때는 dinner
에 대입된 lunch
의 값을 변경시켰어도
기존의 dinner
가 가지고 있는 값과 메모리 주소는 변경되지 않았었다.
참조 타입에서 값의 변경되면 동일한 메모리 주소를 가지고 있는 모든 변수의 값이 변경된다.
참조 타입을 값 타입 처럼 대입하기 위해서는 Object.assign
과 같은 함수를 사용해야한다.
var person = {
name: 'minsu',
age: 22,
job: 'Developer',
}
var newPerson = Object.assign({}, person)
console.log(person) // {name: "minsu", age: 22, job: "Developer"}
console.log(newPerson) // {name: "minsu", age: 22, job: "Developer"}
Object.assign
함수를 사용한 코드의 메모리 주소를 확인해보았다.
person
과 newPerson
의 메모리 주소가 다른 것을 확인할 수 있다.
기존과 같이 person
의 값을 바꾸어도 그대로 newPerson
의 값이 유지되는지 확인해보았다.
person.job = 'Front-End Developer'
console.log(person) // {name: "minsu", age: 22, job: "Front-End Developer"}
console.log(newPerson) // {name: "minsu", age: 22, job: "Developer"}
person
의 값이 변경되었지만 newPerson
의 값은 변경되지 않은 것을 확인할 수 있다.
하지만 아래와 같이 참조 타입 내부에 참조 타입이 존재하는 경우 다른 결과를 얻을 수 도 있다.
var student = {
info: {
firstName: 'kim',
lastName: 'minsu',
},
department: 'Computer Software Engineering',
grade: 'senior',
graduated: false,
}
var newStudent = Object.assign({}, student)
console.log(student)
// {
// info: { firstName: "kim", lastName: "minsu" }
// department: "Computer Software Engineering"
// grade: "senior"
// graduated: false
// }
console.log(newStudent)
// {
// info: { firstName: "kim", lastName: "minsu" }
// department: "Computer Software Engineering"
// grade: "senior"
// graduated: false
// }
위의 코드는 Object.assign
함수를 이용해 객체를 할당했다.
하지만 student
와 newStudent
객체 내부에 있는 info
객체가 같은 메모리 주소를 가지고 있다.
student
객체의 info
의 firstName
의 값을 바꾸고 확인해보았다.
student.info.firstName = 'park'
console.log(student)
// {
// info: { firstName: "park", lastName: "minsu" }
// department: "Computer Software Engineering"
// grade: "senior"
// graduated: false
// }
console.log(newStudent)
// {
// info: { firstName: "park", lastName: "minsu" }
// department: "Computer Software Engineering"
// grade: "senior"
// graduated: false
// }
student
의 info
의 값이 변하면서 newStudent
의 info
객체 또한 변하는 것을 확인할 수 있다.
student
와 newStudent
객체 자체의 주소는 다르지만 내부의 info
객체의 주소가 동일하기 때문이다.
이와 같이 객체 내부에 객체가 있을 때 재귀 함수를 이용하거나 JSON
객체의 함수를 이용하면 된다.
var student = {
info: {
firstName: 'kim',
lastName: 'minsu',
},
department: 'Computer Software Engineering',
grade: 'senior',
graduated: false,
}
var newStudent = JSON.parse(JSON.stringify(student))
student.info.firstName = 'park'
console.log(student)
// {
// info: { firstName: "park", lastName: "minsu" }
// department: "Computer Software Engineering"
// grade: "senior"
// graduated: false
// }
console.log(newStudent)
// {
// info: { firstName: "kim", lastName: "minsu" }
// department: "Computer Software Engineering"
// grade: "senior"
// graduated: false
// }
JSON.stringify
를 이용해 문자열로 바꾼후 JSON.parse
로 다시 객체로 변환하면 된다.
위와 같이 student
와 newStudent
의 info
객체가 다른 주소를 갖는 것을 확인할 수 있다.