일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 알고리즘
- 리트코드
- Async
- codestates
- 회고
- 코드스테이츠
- til
- 리액트
- js
- programmers
- 리덕스
- 손에 익히며 배우는 네트워크 첫걸음
- 2주 프로젝트
- SQL 고득점 Kit
- 프로그래머스
- 제로초
- 백준
- 정재남
- 타임어택
- python
- 자바스크립트
- 타입스크립트 올인원
- 토익
- javascript
- 코어 자바스크립트
- 렛츠기릿 자바스크립트
- 4주 프로젝트
- LeetCode
- 파이썬
- 타입스크립트
- Today
- Total
Jerry
자바스크립트 원시값? 본문
오늘은 자바스크립트 기본 개념 중 하나인 원시 값에 대해 알아보자!
MDN에서 자바스크립트 원시값에 대한 정의를 찾아보았다.
JavaScript에서 원시 값(primitive, 또는 원시 자료형)이란 객체가 아니면서 메서드도 가지지 않는 데이터입니다. 원시 값에는 6종류, string, number, bigint, boolean, undefined, symbol이 존재합니다. 겉보기엔 원시 값처럼 보이는 null도 있지만, 사실 모든 Object, 모든 구조화된 자료형은 프로토타입 체인에 따라 null의 자손입니다.
'자바스크립트에서 원시 값은 객체가 아니면서 메서드도 가지 않는 데이터'라고 하는데 무슨 말일까?
아마 객체가 아니라고 하는 것은 모든 원시 값은 불변성을 지니고 있기 때문일 것이다.
- 원시 값 성질자체가 변형이 허락되지 않기에 변형이 가능한 성질을 가진 객체({})가 아니어야 한다고 하는 것 같다.
- '메서드를 가지지 않는다는 데이터라는 말'도 메서드 자체가 객체 안에 있는 함수가 메서드이기 때문에 (참고: 여기) 안 된다고 하는 것 같다. (추가로 찾아보니, 함수도 객체의 일종이라 함)
아래의 문장은 보자.
당연한 이야기인 것 같지만 곱씹어볼만하다.
변수는 새로운 값을 다시 할당할 수 있지만, 이미 생성한 원시 값은 객체, 배열, 함수와는 달리 변형할 수 없습니다
간단하게 생각해보면, '새로운 값을 재할당이 가능하다면 원시 값이 아니다.'라고만 생각해도 원시 값을 구분하기 편해지지 않을까란 생각이 든다. 란 생각을 했지만.. 밑에 예시 정리해보면서 재할당과 변형은 차이가 있다는 걸 알 수 있었다.
불변함이란 개념과 가까워지기 위해 아래 코드를 살펴보자!
// Using a string method doesn't mutate the string
var bar = "baz";
console.log(bar); // baz
bar.toUpperCase();
console.log(bar); // baz
// Using an array method mutates the array
var foo = [];
console.log(foo); // []
foo.push("plugh");
console.log(foo); // ["plugh"]
// Assignment gives the primitive a new (not a mutated) value
bar = bar.toUpperCase(); // BAZ
toUpperCase() 메서드는 자바스크립트 string에서 제공하는 내장 객체 함수로 문자(열)를 대문자로 바꿔주는 기능을 가지고 있다. 위에서 결과를 보면 알듯이, 단순히 기능을 실행한다고 해서 본래 변수의 값 자체의 성질이 대문자로 되지 않는다.
반면에, 2번째 문단의 코드에서 보면 1번째와 다르게 새로운 값을 부여하거나 교체해주면 원래의 성질이 그대로 바뀌는 것을 볼 수 있다.
즉, 원시 값을 교체할 수는 있지만, 직접 변형이 안 된다는 걸 알 수 있다.
추가 예시를 가져와봤다!
// 원시 값
let foo = 5;
// 원시 값을 변경해야 하는 함수 정의
function addTwo(num) {
num += 2;
console.log("num: " + num); // #1
}
// 같은 작업을 시도하는 다른 함수
function addTwo_v2(foo) {
foo += 2;
console.log("foo: " + foo); // #2
}
// 원시 값을 인수로 전달해 첫 번째 함수를 호출
addTwo(foo);
// 현재 원시 값 반환
console.log(foo); // #3
// 두 번째 함수로 다시 시도
addTwo_v2(foo);
console.log(foo); // #4
#1, #2, #3, #4의 값을 뭐라고 예상하나요??
#1과 #2는 7을 반환하고 #3과 #4는 5를 반환합니다.
희한하죠?
왜 이런지는 보면, 먼저 코드를 실행하게 되면 JavaScript는 식별자 foofoo의 값을 찾습니다. 이는 인스턴스화 된 첫 번째 구문의 변수를 올바르게 찾습니다. 찾은 변수를 매개 변수로 전달 후 바로 대입이 되는 것이 아닙니다.
바로 그전에, 자바스크립트는 원래 전달된 인수인 원시 값을 복사해 로컬 복사본을 생성합니다. 이 로컬 복사본은 해당 함수 스코프 내에서만 존재를 합니다. 그래서 #1과 #2의 콘솔 값이 7로 찍히게 된 것이며 #3과 #4는 원리 값인 5가 찍히게 된 것입니다.
그렇다면, 위 예시 코드에서 foo를 불변성이 아닌 배열로 하면 어떻게 될까요?
함수 내에서 전역에서 한 번식 콘솔로 찍어보니 foo 자체 값도 변형이 된 것을 확인할 수 있습니다!
이렇게 된 이유는 자바스크립트의 lexical scoping (어휘적 유효 범위)와 결과 변수 섀도잉 때문이며 자세한 내용은 클로저를 참조하시면 됩니다. 이것이, 원시 값이 변하지 이유라고 할 수 있습니다.
출처: developer.mozilla.org/ko/docs/Glossary/Primitive
참고: ko.javascript.info/primitives-methods
'Front > JavaScript' 카테고리의 다른 글
이벤트 루프란? (in Javascript) (2) | 2021.04.16 |
---|---|
async 예외처리(의 까다로운점?) (0) | 2021.04.15 |
async await 이란? (0) | 2021.04.14 |
One Paper: Understanding Prototype (0) | 2020.11.07 |
One Paper: Inheritance Pattern (0) | 2020.11.07 |