본문 바로가기
JS/바닐라JS

[인사이드 JS] 자바스크립트 데이터 타입과 연산자

by 실버dev 2019. 10. 31.

자바스크립트의 값들은 크게 기본타입과 참조타입으로 나뉜다.

 

기본타입 - 숫자, 문자열, 불린값, undefined, null

참조타입 - 객체(배열, 함수, 정규표현식)

 

 


1. 자바스크립트 기본타입.

 

자바스크립트는 느슨한 타입 체크 언어이다.

변수를 선언할 때 타입을 미리 정하지 않고, var라는 한 가지 키워드로만 변수를 선언한다.

선언된 변수에는 어떤 타입의 데이터라도 저장하는게 가능하다.

저장한 값에 따라 해당 변수의 타입이 정해진다.

 

 

1) 숫자

자바스크립트에서는 int, long, float과 같은 숫자타입의 구분이 없다.

모든 숫자를 64비트 부동 소수점 형태로 저장하는 단 하나의 숫자형만 존재한다.

자바스크립트에서는 정수형이 따로없고, 모든 숫자를 실수로 처리하기 때문에 C언어와 달리 나눗셈 연산시 소수부분을 버리지 않는다.

 

2) 문자열

문자열은 작은 따옴표나 큰 따옴표로 생성하며, 따옴표의 종류에 따른 문자열 타입의 차이는 없다.

문자열은 배열처럼 인덱스를 이용해 접근할 수 있으나, 수정은 불가능하다.

let text = 'test'
console.log(text[0], text[1], text[2], text[3])
//test로 출력

text[0] = 'T'
console.log(text[0], text[1], text[2], text[3])
//수정되지 않고 test로 출력됨

 

3) 불린값

true와 false를 가진다.

 

4) null과 undefined

둘다 값이 비어있음을 나타낸다.

undefined는 자바스크립트 환경 내에서 기본적으로 값이 할당되지 않았을때 부여된다.

null은 개발자가 명시적으로 값이 비어있을을 나타내는데 사용한다.

 

 


 

2. 자바스크립트 참조 타입(객체 타입)

 

자바스크립트에서 기본타입 외에는 모두 객체이다.

JS에서 객체는 단순히 키와 밸류를 저장하는 컨테이너로서, 해시 자료구조랑 유사하다.

객체는 여러개의 프로퍼티를 포함할 수 있으며, 이러한 객체의 프로퍼티는 기본 타입의 값을 포함하거나, 다른 객체를 가리킬 수도 있다.

 

 

1) 객체 생성

 

- Object() 생성자 함수 이용

const foo = new Object()

foo.name = 'foo'
foo.age = 30
foo.gender = 'male'

- 객체 리터럴 방식 사용

const foo = {
  name: 'foo',
  age: 30,
  gender: 'male'
}

 

2) 프로퍼티의 읽기/쓰기/갱신

 

-대괄호나 마침표로 접근한다.

console.log(foo.name) // 마침표로 접근
foo.name = 'boo' // 갱신
foo['major'] = 'computer science' // 동적 생성
console.log(foo['name']) // 대괄호 접근
console.log(foo.major)

대괄호 표기법은 프로퍼티가 예약어이거나 표현식을때 주로 사용함.

 

 

3) for in 문으로 객체 프로퍼티 출력

for (prop in foo) {
  console.log(prop, foo[prop])
}

prop = 키, foo[prop] = 밸류. 

for in 문은 객체의 키값을 순회한다.

 

 

4) 프로퍼티 삭제

delete foo.name

delete문 사용.

단 객체 자체는 삭제할 수 없다. 프로퍼티만 가능하다.

 

 

 

 


3. 참조타입의 특성.

 

1) 객체 비교

const a = {
  value : 100
}
const b = a

console.log(a===b) // true

a.value = 50
console.log(b.value) // 50

객체 a 를 만들고 b에 a를 할당했다.

이때 b는 a의 복사본을 가지는 것이 아니라 a의 주소를 참조하게 된다.

a의 프로퍼티인 value값을 변경하면 b도 a의 value를 참조하기 때문에 b.value는 50을 출력하게된다.

 

 

2) 참조에 의한 함수 호출 방식

 

기본타입은 call by value 방식으로 함수를 호출한다.

함수를 호출할 때 인자로 기본타입의 값을 넘기면 매개변수로 복사된 값이 전달된다.

따라서 함수에 인자로 기본타입의 변수를 넘겨줘도 변수의 값이 변경되지 않는다.

 

객체와 같은 참조타입은 Call by reference 방식으로 동작한다.

객체를 인자로 넘겨주면 매개변수로 복사되는 것이 아니라 객체의 참조값이 그대로 함수 내부로 전달된다.

때문에 함수 내부에서 참조값을 이용해 실제 객체의 값을 변경할수도 있다.

 

const func = (a, b) => {
  a = 200
  b.value = 200
}

let a = 100
let b = {
  value : 100
}

func(a, b)
console.log(a) //100
console.log(b.value) //200

기본타입인 a는 변경되지 않았고 객체 b의 프로퍼티는 값이 변경되었음.

 

 


4. 프로토타입

 

자바스크립트의 모든 객체는 자신의 부모 역할을 하는 객체와 연결되어 있다.

그리고 이것을 객체지향의 상속 개념과 같이 부모 객체의 프로퍼티를 마치 자신의 것처럼 사용할 수 있다.

부모객체를 프로토타입 객체라고 부른다.

 

const foo = {
  name: 'foo'
}

foo.toString()

다음 코드에서 foo 객체에는 toString이라는 프로퍼티가 없지만 코드가 동작한다.

자바스크립트에서 모든 객체는 자신의 프로토타입을 가리키는 [[Prototype]]이라는 숨겨진 프로퍼티를 갖는다.

크롬브라우저에서 __proto__가 바로 이것이다.

즉 foo 객체는 자신의 부모 객체를 __proto__라는 내부 프로퍼티로 연결하고 있는 것이다.

toString 메서드는 __proto__내에 존재했다.

 

객체를 생성할 때 결정된 프로토타입 객체는 임의의 다른 객체로 변경하는 것도 가능하다.

 


5. 배열

 

배열은 자바스크립트의 특별한 형태이다.

C언어처럼 배열의 크기를 지정할 필요가 없고, 어떤 타입의 데이터를 저장하더라도 에러가 발생하지 않는다.

 

1) 배열 리터럴

대괄호를 사용해 생성한다.

const arr = [0, 1, 2, 3]

배열 접근은 인덱스값을 이용한다.

 

2) 요소 생성

arr[5] = 10

인덱스로 접근해서 값을 할당하면 된다.

 

 

3) length 프로퍼티

 

 

length는 배열의 원소 개수를 나타내지만 실제 원소 개수와 일치하는 것은 아니다.

length의 값은 배열내에 가장 큰 인덱스 + 1으로, 중간에 비어있는 요소가 있어도 있는것으로 친다.

 

length프로퍼티로 배열의 길이를 변경할 수도 있다.

const arr = [0, 1, 2, 3]

arr.length = 2
console.log(arr) // [0, 1]
console.log(arr[2]) // undefined

length가 4인 배열 arr을 2로 명시적으로 값을 변경하니 앞의 두 값 외에는 삭제되었다.

 

자바스크립트는 배열에서 사용 가능한 표준메서드들을 제공하는데 이 메서드는 length 프로퍼티를 기반으로 동작한다.

예를들어 push() 메서드는 length프로퍼티를 참조해 그 위치에 값을 추가한다.

length를 명시적으로 100으로 수정하면 100번 인덱스 위치에 값을 추가한다.

 

 

4) 배열과 객체

 

배열과 객체 모두 typeof() 메서드로 타입검사를 하면 Object로 출력된다.

하지만 배열에서는 length프로퍼티나 push와 같은 배열 메서드를 사용할 수 있지만 객체는 불가능하다.

 

그 이유는 객체의 프로토타입은 Object.prototype이지만 배열의 프로토타입은 Array.prototype이다.

그리고 Array.prototype의 프로토타입 객체는 Object.prototype이다.

객체는 자신의 프로토타입이 가지는 모든 프로퍼티 및 메서드들을 상속받아 사용할 수 있으므로, 배열은 Array.prototype에 포함된 배열 표준 메서드와 Object.prototype의 표준메서드를 모두 사용할 수 있기 때문이다.

 

 

5) 배열의 프로퍼티 동적 생성

 

배열도 객체이기 때문에 배열 원소 이외의 객체와 같은 프로퍼티를 추가할 수 있다.

const arr = [0, 1, 2, 3]

arr.color = 'red'
console.dir(arr) // [ 0, 1, 2, 3, color: 'red' ]
console.log(arr.length) // 4

하지만 length는 배열 원소의 가장 큰 인덱스가 변했을 경우에만 변경되므로, 프로퍼티를 추가해도 값이 변하지 않는다.

 

 

6) 배열 프로퍼티 열거

 

배열은 객체와 같이 for in문을 사용해서 열거할 수 있지만, 출력이 불필요한 프로퍼티를 같이 출력할 수 있다.

ES6에서 생긴 for of 문을 사용하면 된다.

 

 

7) 배열 요소 삭제

 

배열도 객체이므로, 배열 요소나 프로퍼티를 삭제하는데 delete 연산자를 사용할 수 있다.

const arr = [0, 1, 2, 3]

delete arr[2]
console.log(arr) // [ 0, 1, undefined, 3 ]
console.log(arr.length) // 4

하지만 빈 요소가 생기고, length 프로퍼티도 변경되지 않는다.

 

자바스크립트에서 배열 요소를 삭제할 때 splice() 배열 메서드를 사용한다.

splice(시작위치, 삭제할 요소의 수, 삭제할 위치에 추가할 요소)

const arr = [0, 1, 2, 3]

arr.splice(2,1)
console.log(arr) // [ 0, 1, 3 ]
console.log(arr.length) // 3

 

8) Array() 생성자 함수

const foo = new Array(3)
console.log(foo) // [ <3 empty items> ]

const boo = new Array(1, 2, 3)
console.log(boo) // [1, 2, 3]

보통 리터럴로 배열을 생성하지만 생성자로 생성하는 방법도 있다.

 

 

9) 유사 배열 객체

 

length프로퍼티를 가진 일반 객체를 유사 배열 객체라고 부른다.

유사배열 객체의 특징은 객체임에도 불구하고, 표준 배열 메서드를 사용하는 것이 가능하다.

 

const foo = {
  name : 'foo',
  length : 1
}

//foo.push('baz') - 그냥은 안된다.
Array.prototype.push.apply(foo, ['baz'])
console.log(foo) // { '1': 'baz', name: 'foo', length: 2 }

apply() 메서드를 사용하면 객체지만 표준 배열 메서드를 활용하는 것이 가능하다.

 

궁금해서 length를 지우고 적용해봤다.

const foo = {
  name : 'foo',
}

Array.prototype.push.apply(foo, ['baz'])
console.log(foo) // { '0': 'baz', name: 'foo', length: 1 }

인덱스를 키값으로 baz가 추가되고, 자동적으로 length 프로퍼티도 생성되었다.

 

 

 


6. 기본 타입과 표준 메서드

 

자바스크립트는 기본타입에서도 타입별로 호출 가능한 메서드들을 정의하고 있다.

 

기본 타입은 객체가 아닌데 메서드를 호출 할 수 있는 이유는?

기본 값들은 메서드 처리 순간에 객체로 변환된 다음 각 타입별 표준 메서드를 호출하고, 메서드 호출이 끝나면 다시 기본값으로 복귀하는 것이다.

 

const num = 0.5
console.log(num.toExponential(1)) // 5.0e-1

 

 

 


7. 연산자

 

1) + 연산자.

 

숫자일땐 더하기연산, 문자일땐 문자열 연결 연산을 한다.

숫자 + 문자열일땐? 문자열 연결 연산을 한다.

 

 

2) typeof 연산자.

 

피연산자의 타입을 문자열 형태로 리턴한다.

단, null과 배열이 object로 출력되고 함수는 function으로 출력된다.

 

 

3) ==(동등), ===(일치)

 

== 연산자는 피연산자의 타입이 다를 경우에 타입 변환을 거친 후 비교한다.

=== 연산자는 피연산자의 타입이 다를 경우에 타입을 변경하지 않고 비교한다.

 

console.log(1 == '1') // true
console.log(1 === '1') // false

===이 더 엄격한 비교이다.

===를 사용하자.

 

 

4) !! 연산자.

 

!!의 역할은 피연산자를 불린 값으로 변경하는 것이다.

 

 

 


인사이드 자바스크립트 책의 3장 요약.