Pandaman Blog

[JS] Javascript의 타입 (Type) 본문

Front end/Javascript

[JS] Javascript의 타입 (Type)

oyg0420 2019. 12. 29. 16:31

자바스크립트의 타입은 기본형 타입 Boolean, Null, Undefined, Number, String, Symbol과 별도의 Object 있습니다.

1. 기본형 타입

자바스크립트의 오브젝트를 제외한 모든 값은 변경 불가능한 값 (immutable value)입니다.

Boolean

Boolean 타입은 논리적 요소로, true, false 두 가지 값을 가질 수 있습니다.

보통 boolean 조건은 어떤 코드 부문이 실행되어야 할지 if 문, for 문에서 주로 사용합니다.

if (false) {
  console.log('will pass');
}
if (true) {
  console.log('will show'); // 'will show'
}
for(var i=0; i<4; i++) {
    console.log(i);
} 
// 0 
// 1
// 2
// 3

Null

Null 타입은 null 값을 가질 수 있습니다. null의 어떤 값이 의도적으로 비어있는 것을 나타냅니다.

Undefined

값을 할당하지 않은 변수에 대해 undefined 값을 가집니다.

null값과 undefined값의 차이점이 있습니다. 예제를 통해 알아보겠습니다.

let willHaveUndefined;
willHaveUndefined; // undefined

const willHaveNull = null;
willHaveNull; // null

willHaveUndefined처럼 값을 할당받지 않는 변수는 undefined을 나타내는 것을 확인할 수 있습니다.
willHaveNull처럼 값을 의도적으로 null로 할당한다면 null값을 갖는 것을 확인할 수 있습니다.

Number

Number타입은 숫자를 나타내는 타입입니다. 국제 IEEE 754 표준을 따릅니다.
숫자의 범위를 넘는다면 +Infinity, -Infinity로 나타납니다.
숫자가 아니라면 NaN를 나타냅니다.
JavaScript는 integers, short, long, floating-point 등 과 같은 숫자의 다른 형식을 정의하지 않습니다.
가수부는 bits 0부터 bits 51, 지수부는 bits 52부터 62, 부호는 bit 63에 저장합니다.

var x = 999999999999999;   // 999999999999999
var y = 9999999999999999;  // 10000000000000000

은 숫자를 표현할 때 사용하는 정해진 비트 수가 있습니다.(부호 1, 지수부 11, 가수부 52). 가수부에 담길 수 있는 자릿수를 초과하면 반올림을 합니다.

999999999999999를 2진수로 변환하면 11100011010111111010100100110001100111111111111111 50자리, 9999999999999999를 2진수로 변환하면 100011100001101111001001101111110000010000000000000000 54자리로 가수부에 담길 수 있는 52 비트를 초과하여, 반올림하게 됩니다.
따라서 정수 15자리를 넘어가면 정확도 떨어지게 됩니다.

또 다른 예제입니다.

0.2 + 0.4 // 0.6000000000000001

예상은 0.6이라고 생각했지만, 결과는 0.6000000000000001입니다.

64 비트 IEEE 754 형식에 따라 0.6은 2진수로 변환하고 가수부에 담길 수 있는 자릿수를 초과하여, 반올림을 하게 됩니다.
반면에 0.2와 0.4는 각각 반올림을 하고 더한 값을 다시 반올림하게 되면서 결괏값은 0.6과 다르다는 것을 알 수 있습니다.

String

자바스크립트의 String 타입은 텍스트 데이터를 나타내는 데 사용합니다.
String의 각 요소는 String의 위치를 차지합니다. 첫 번째 글자는 0번째, 두 번째 글자는 1번째.. n번째 글자는 n-1의 요소입니다.

예제를 통해 알아보겠습니다

const str1 = '가나다라마바사';
str1[0] // '가'
str2[1] // '나'

첫 번째 인덱스의 값은 '가', 두 번째 인덱스의 값은 '나'를 나타내는 것을 확인할 수 있습니다.

자바스크립트의 문자열은 변경 불가능(immutable)합니다.

예제를 통해 알아보겠습니다.

let str1 = 'Hello';
str1 = 'Javascript';

str1 // 'Javascript'

첫 구문이 실행되면 'Hello' 문자열이 메모리에 생성됩니다. 그리고 str1 포인터에 'Hello' 문자열 주소를 할당하게 됩니다.
두 번째 구문이 실행되면서 'Javascript' 문자열이 메모리에 생성됩니다. 다시 str1 포인터에 'Javascript' 문자열 주소를 재할당하게 됩니다. 결론적으로 기존 문자열이 변경되지 않고 모두 메모리에 생성되었으며, str1의 포인터에 문자열 주소가 재 할당되는 것입니다.

let str = '테스트는 테스트다';
str.replace('테스트', '텍스트'); // '텍스트는 텍스트다'
str // '테스트는 테스트다'

위 예제에서는 str의 포인터에 '테스트는 테스트다' 문자열 주소를 할당하고, 이후 구문에서 재할당하지 않았기 때문에, str값은 변하지 않습니다.

2. Object

객체는 관련된 데이터와 함수의 집합입니다.
객체는 키와 값의 맵핑입니다. 키는 문자열이고 값은 어떤 값도 될 수 있습니다.

property와 method

예제를 통해 알아보겠습니다.

var yoongu = {
 age: 30,
 job: 'developer',
 greeting: function() {
   alert('Hi I\'m ' + this.age + 'years old'),
 } 
};

속성(property)은 기본적으로 이름과 값을 가지고 객체 정보를 담고 있습니다.
메서드(method)는 객체가 갖고 있는 동작입니다.
위의 객체에서는 age, jobyoongu객체의 속성이 되며, greeting이라는 함수는 yoongu객체의 메서드가 되는 것입니다.

해당 객체의 속성과 메서드에 접근하기 위해서는 접근 연산자 '.'를 사용하여 접근합니다. 추가적으로 속성과 메서드를 제거하기 위해서는 delete를 사용하여 제거합니다.

delete yoongu.greeting // true
yoongu // {age: 30, job: "developer"}

Object method

1) Object.assign()

열거할 수 있는 하나 이상의 원본 객체로부터 대상 객체로 속성을 복사할 때 사용합니다.
Object.assign(target,... sources)
target: 소스 객체를 적용할 객체, sources: 속성을 갖고 있는 적용할 객체

예제를 통해 알아보겠습니다.

const targetObject = { job: 'developer', age: 31 };
const sourceObject = { nickname: 'oyg0420' };
const newObject = Object.assign(targetObject, sourceObject);
newObject; // { job: 'developer', age: 31, nickname: 'oyg0420'}
targetObject // { job: 'developer', age: 31, nickname: 'oyg0420'}

예제와 같이 target객체의 속성은 동일한 key를 가진 source 객체의 속성으로 대체됩니다. 그리고
sourceObject 속성이 추가된 targetObject이 반환됩니다.

여기서, 주의할 점은 target객체(targetObject)도 변화하게 됩니다. 그 이유는 assing() 반환 값은 source객체와 병합된 target객체이기 때문입니다. 만약 assign() 메서드를 사용해도 객체 targetObject 값이 유지되길 원한다면 아래와 같이 사용할 수 있습니다.

const targetObject = { job: 'developer', age: 31 };
const sourceObject = { nickname: 'oyg0420' };
const newObject = Object.assign({}, targetObject, sourceObject);
targetObject; //  { job: 'developer', age: 31 }
newObject; // { job: 'developer', age: 31, nickname: 'oyg0420'}

targetObject를 매개변수 source객체 위치로 변경해 위에 선언된 객체 값을 유지할 수 있었습니다.

2) Object.defineProperty()

객체에 직접 새로운 속성을 정의하거나 이미 존재하는 속성을 수정한 후, 그 객체를 반환합니다.
defineProperty()를 통해서 속성을 상세하게 정의할 수 있습니다.
Object.defineProperty(obj, prop, descriptor)
obj: 정의할 객체, prop: 추가할 속성, descriptor: 속성에 대해 기술 및 설명

예제를 통해 알아보겠습니다.

const obj1= {};
Object.defineProperty(obj1, 'age', { value: 31, writable: true });

obj1에 새로운 속성 age를 할당하는 예제입니다. 값은 31(Number)을 할당했으며, writable: true로 할당 연산자(=)를 통해 값을 수정할 수 있도록 정의했습니다.
descriptor 대해 더 알고 싶다면 참고하세요.

3) Object.freeze()

freeze를 통해 사용하여 객체를 수정하지 못하게 합니다. 즉 불변함을 유지시켜줍니다.
freeze(obj)

예제를 통해 알아보겠습니다.

const freezeObject = { name: 'oyg0420', age: 30 };
Object.freeze(freezeObject);
freezeObject.age = 31;
freezeObject.age; // 30 
freezeObject.name = 'oyg0730';
freezeObject.name; // 'oyg0420;

freeze를 메서드를 통해 freezeObject의 속성 값은 변화되지 않는 것을 확인할 수 있습니다.

4) Object.seal()

seal() 메서드를 사용하면 객체의 새로운 속성을 추가하지 못하게 됩니다.
writable이 true인 속성의 값은 수정 가능합니다. 이것이 위의 freeze와 차이입니다.

예제를 통해 알아보겠습니다.

const sealObject = { name: 'oyg0420', age: 30 };
Object.seal(sealObject);
sealObject.age = 31; 
sealObject; // { name: 'oyg0420', age: 31 }
sealObject.nation = 'korea';
sealObject; // { name: 'oyg0420', age: 31 }

5) Object.is()

두 값이 같은지 확인하기 위한 메서드입니다.
반환 값은 boolean입니다.

예제를 통해 알아보겠습니다.

Object.is(1, 1); // true
Object.is('test', 'test') // true
Object.is(undefined, undefined) // true
Object.is(NaN, NaN) // true

위 예제에서 확인해야 할 것은 NaN, undefiend가 동일한지 확인할 때 true를 반환하는 것을 확인할 수 있습니다. 이것은 강제 비교 연산자(==), 엄격한 비교 연산자(===) 결과와 다르다는 것을 확인할 수 있습니다. 그리고 is() 메서드는 비교할 대상의 값의 타입을 강제로 변경하지 않습니다.

6) Object.keys()

객체의 속성 이름을 배열(string [])로 반환합니다.

예제를 통해 알아보겠습니다.

const object1 = { name: 'oyg0420', age: 31 };
Object.keys(object1); // ['name', 'age']

7) Object.values()

객체의 속성 값을 배열로 반환합니다.

예제를 통해 알아보겠습니다.

const object1 = { name: 'oyg0420', age: 31 };
Object.values(object1); // ['oyg0420', 31]

Object의 객체 생성 방법

javascript의 객체 생성 방법은 크게 3가지로 나눌 수 있습니다.

  1. 기본 객체 생성자 함수를 통한 객체 생성
  2. 객체 리터럴 사용
  3. 생성자 함수 이용
1) 기본 객체(Object)의 생성자 함수를 통한 객체 생성

Object의 생성자함수를 사용하여 객체를 생성할 수 있습니다.

예제를 통해 알아보겠습니다.

const newObject = new Object();
newObject.name = 'oyg0420';
newObject.age = 31;
newObject.job = 'developer';
newObject // { name: 'oyg0420', age: 31, job: 'developer' }

생성자 함수를 사용하여 기본 객체를 생성한 후 필요한 속성들을 추가하여, { name: 'oyg0420', age: 31, job: 'developer' }를 포함하는 newObject 객체를 생성했습니다.

2) 객체 리터럴을 사용한 객체 생성

간편하게 객체 생성을 하는 방법입니다.
객체를 직접 생성하는 방법으로 중괄호({})를 사용하고 그 내부에 속성 이름과 값을 정의하는 방법입니다.
객체 리터럴로 객체를 생성하는 방식은 내부적으로 Object생성자 함수를 사용하여 객체를 생성합니다.

예제를 통해 알아보겠습니다.

const newObject = {
    name: 'oyg0420',
      age: '31',
      job: 'developer',
};
newObject; // { name: 'oyg0420', age: 31, job: 'developer' }
newObject.nation = 'korea';
newObject; // { name: 'oyg0420', age: 31, job: 'developer', nation: 'korea' }
3) 생성자 함수를 이용한 객체 생성

생성한 함수에 new 키워드를 사용하여 객체를 생성할 수 있습니다.
Object 생성자 함수의 방식객체 리터럴 방식으로 객체를 생성하는 것은 속성 값이 다른 여러 개의 객체를 생성할 때 불편합니다. 동일 속성을 갖는 객체임에도 매번 같은 속성을 기술해야 하기 때문입니다.
생성자 함수를 이용해 객체를 생성하면, 속성이 동일한 여러 개의 객체를 간편하게 생성할 수 있습니다.

예제를 통해 알아보겠습니다.

const Developer = function(name, age) {
    this.name = name;
      this.age = age;
};

const itIsMe = new Developer('oyg0420', 31);
itIsMe; // { name: 'oyg0420', age: 31 } 
const itIsYou = new Developer('junior', 20);
itIsYou; // { name: 'junior', age: 20 } 

Wrapper Object

앞서 말했듯이 자바스크립트의 총 기본타입(원시타입)에는 총 6개의 타입(string, number, boolean, null, undefined, symbol)이 있습니다.
그에 상응하는 Wrapper object(String, Number, Boolean, Symbol)가 존재합니다.

String객체와 원시타입 string 에 차이점에 대해 살펴보겠습니다.

const str1 = New String('oyg0420');
const str2 = 'oyg0420';
str1 == str2; // false
typeof str1; // "object"
typeof str2; // "string"

wrapper object인 String객체는 말 그대로 객체입니다. 따라서 원시 타입 문자열 str2와 str1은 다르다고 할 수 있습니다.
str1은 아래와 같은 객체로 나타낼 수 있습니다.

str1 = {
 0: 'o',
 1: 'y',
 2: 'g',
 3: '0',
 4: '4',
 5: '2',
 6: '0',
 length: 7
}

문자열의 길이를 측정할때 length 속성을 사용합니다. 그리고 length는 String객체의 속성이라는 것도 알게 되었습니다. 그런데 우리는 어떻게 원시타입인 문자열을 사용하면서 속성을 사용하지?라는 생각이 들었습니다.
찾아보니, 원시타입에서 속성이나 메서드를 호출하려 할 때, 자바스크립트는 래퍼 오브젝트로 변경하고 속성이나 메서드에 접근한다고 합니다. 이것을 바로 오토 박싱(AutoBoxing)이라고 합니다.

const name = 'oyg0420'; 
name.length; // 7
name === 'oyg0420'; // true

name.length에서 length라는 속성에 접근하기 위해 자바스크립트는 name을 Wrapper Object를 만듭니다. 그리고 length에 접근 후에 값을 이용하고 다시 지워버립니다. 그래서 다시 엄격한 비교 연산자(===)를 사용했을 때 true가 됩니다.

number타입와 Number객체도 마찬가지로 행동합니다.

const num1 = new Number(100);
const num2 = 100;
typeof num1; // "object"
typeof num2; // "number"
num2 === num1; // false

Number객체로 생성된 num1의 타입은 object이고, 100이 할당된 변수 num2의 타입은 number입니다.

const num1 = 100;
num1.toString(); // '100'
num1.valueOf(); // 100
num1.length = 3;
num1.length // undefined

일시적으로 Number객체를 생성하여 toString() 메서드, valueOf() 메서드에 접근할 수 있도록 한 것입니다.
length라는 속성에 3이라는 값을 할당했습니다. 그리고 다시 num1.length 호출하면 undefined를 얻는 것을 확인할 수 있습니다. Number 객체가 즉시 파괴되었기 때문입니다.

위 예제를 진행하면서 Wrapper object 덕분에 원시타입(number, string, boolean)에서 속성과 메서드에 접근할 수 있다는 것을 알게 되었습니다.

 

파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음

Comments