본문 바로가기

Javascript

[JavaScript] 타입(typeof) : 배열, 문자열, 숫자, 값이 아닌 값

반응형

JavaScript 내장 타입


원시 타입, primitives

null falsy한 유일한 원시값이지만, 타입은 'object' 인 특별한 존재
undefined 값이 없는 변수 값이거나, 선언되지 않은 변수 값
- 값이 없은 undefined : 접근 가능한 스코프에 변수가 선언되었으나, 현재 아무런 값도 할당되지 않은 상태
- 선언되지 않으 undefined : 접근 가능한 스코프에 변수 자체가 선언조차 되지 않은 상태
boolean  
number  
string  
symbol ES6부터 추가

 

예시)

typeof undefined === "undefined" // true
typeof true === "boolean" // true
typeof 42 === "number" // true
typeof "42" === "string" // true
typeof {life : 42} === "object" // true
typeof Symbol() === "symbol" // true
typeof null === "object" // true

var a;
a; // undefined
b; // Uncaught ReferenceError

typeof a; // "undefined"
typeof b; // "undefined"

 

객체 타입, object

function object의 하위 타입, 호출 가능한 객체
length 프로퍼티 : 함수의 인자 개수
array object의 하위 타입, 숫자 인덱스를 가짐
length 프로퍼티 : 자동으로 관리

 


[네이티브(native)] chati.tistory.com/151

 

[JavaScript] 네이티브, native

다음은 가장 많이 쓰는 네이티브 들이고, 네이티브는 사실 내장 함수이다. - String() - Number() - Boolen() - Array() - Object() - Function() - RegExp() - Date() - Error() - Symbol() : ES6에서 추가됨 필..

chati.tistory.com

 


배열, array


문자열, 숫자, 객체 심지어 다른 배열이나 어떤 타입의 값이라도 담을 수 있는 그릇이다.

배열 크기는 미리 정하지 않고도 선언할 수 있으며, 원하는 값을 추가하면 된다.

 

배열의 인덱스는 숫자이나, 배열 자체도 하나의 객체여서 키/프로퍼티 문자열을 추가할 수 있다.

(단, 그러면 배열 length 가 증가하지 않는다.) 

 

var a = [];
a[0] = 1;
a["foo"] = 2;

a.length; // 1
a["foo"]; // 2
a.foo; // 2

 

일반적으로 배열에 문자열 타입의 /프로퍼티를 두는 추천하지 않는다.

그렇게 해야한다면 객체를 대용하고 배열 원소의 인덱스는 확실히 숫자만 쓰자.

 

유사 배열 값을 진짜 배열로 바꾸고 싶은때, 배열 유틸리티 함수(indexOf(), concat(), forEach()등)를 사용하여 해셜하는 것이 일반적이다.

혹은 함수에 인자가 없으면 기본 인자 값으로 구성된 배열을 복사한다. 이는 ES6부터는 기본 내장 함수 Array.from()이 이 일을 할 수 있다.

 

문자열, String


문자열은 불변 값이지만, 배열은 가변값이다.

즉, 배열에는 reverse()라는 가변 메서드가 준비되어 있지만, 문자열은 그렇지 않다.

 

문자열은 불변 값이므로 문자열 메서드는 그 내용을 바로 변경하지 않고, 항상 새로운 문자열을 생성한 후 반환한다.

But, 대부분의 배열 메서드는 그 자리에서 곧바로 원소를 수정한다.

 

'문자열' 자체에 어떤 작업을 빈번하게 수행하는 경우라면,

관점을 달리하여 문자열을 문자 단위로 저장하는 배열로 취급하는 것이 더 나을 수 있다.

 

숫자, Number


자바스크립트의 숫자 타입은 number가 유일하며, '정수(Integer)' 및 '부동 소수점 숫자(Fractional Decimal Number)'를 모두 아우른다.

따라서 자바스크립트의 정수는 부동 소수점 값이 없는 값이다. (예: 42.0은 '정수' 42와 같다.)

 

자바스크립트는 IEEE754 표준을 따르며, 그 중에서도 정확히는 'Double Percision' 표준 포맷(64비트 바이너리)을 사용한다.

상세 내용을 알고 싶다면 따로 확인을 해보자!

 

숫자 값은 Number 객체 래퍼로 박싱할수 있기 때문에 Number.prototype 메서드로 접근할 수도 있다.

예) toFixed() 메서드 : 지정한 소수점 이하 자릿수까지 숫자를 나타냄

이진 부동 소수점

다음은 널리 알려진 이진 부동 소수점 숫자의 부작용을 알아보자.

 

0.1 + 0.2 === 0.3; // false
0.1 + 0.2 // 0.30000000000000004

 

위와 같이 이진 부동 소수점으로 나낸 0.1과 0.2는 원래의 숫자와 일치하지 않는다. 

실제로는 0.30000000000000004 에 가깝지만, 가깝다고 해도 같은 것은 아니기 떄문이다.

 

이런 경우 어떻게 처리해야할까?

 

ES6부터는 이 값이 Number.EPSILON으로 미리 정의되어 있으므로 필요시 사용하면 되고,

ES6 이전 브라우저는 다음과 같이 사용하면 된다.

 

Number.EPSILON // 2.220446049250313e-16

// ES6 이전 브라우저
if (Number.EPSILON) {
    Number.EPSILON = Math.pow(2, -52)
}

 

이를 이용해 두 숫자(반올림 허용 오차 이내의)의 '동등함'을 비교할 수 있다.

 

function numbersEqual(n1, n2) {
    return Math.abs(n1 - n2) < Number.EPSILON;
}

var a = 0.1 + 0.2;
var b = 0.3;

numbersEqual(a, b); // true
numbersEqual(0.0000001, 0.000002); // false

정수

숫자 표현하는 방식이 이렇다 보니, 정수는 Number.MAX_VALUE 보다 훨씬 작은 수준에서 안전 값의 범위가 정해져 있다.

 

즉, '안전하게' 표현할 수 있는 정수는 최대 2^53 - 1 (9007199254740991) 으로, 얼추 9천조가 넘으며 이 값은 ES6 에서 Number.MAX_SAFE_INTEGER 으로 정의한다.

 

또한 데이터베이스 등에서 64비트 ID를 처리할때가 대부분인데,

이때 64비트 숫자는 숫자 타입으로 정확하게 표시할 수 없으므로 (보내고 받을 때) 자바스크립트 string 타입으로 저장해야한다.

 

ES6부터는 Number.isInteger()로 어떤 값의 정수 여부를 확인하고, 안전한 정수 여부는 Number.isSafeInteger()로 확인하며, 

ES6 이전 브라우저는 다음과 같이 사용하면 된다.

 

Number.isInteger(42); // true
Number.isInteger(42.3); // false

Number.isSafeInteger(Math.pow(2, 53)); // false
Number.isSafeInteger(Math.pow(2, 53) - 1); // true

//  ES6 이전 브라우저 정수 여부
if (!Number.isInteger) {
    Number.isInteger = function (num) {
      return typeof num == "number" && num % 1 == 0;
    };
}

 


실종된 값(값을 아직 가지지 않은 것), Undefined


느슨한 모드에서는 전역 스코프에서 undefined란 식별자에 값을 할당할 수 있으나, 이는 추천하지 않는다 !!

 

unction foo() {
    undefined = 2;
}

foo(); // undefined

function foo() {
    "use strict";
    undefined = 2;
}

foo(); // Uncaught TypeError

 

게다가 어떠한 모드에 상관없이 undefined란 이름을 가진 지역 변수는 생성할 수 있으나, 이 또한 추천하지 않는다 !!

 

function foo() {
    "use strict";
    undefined = 2;
    console.log(undefined);
}

// undefined

 

undefined는 내장 식별자로, 값은 undefined지만(위에처럼 재정의하지 않는다면), 이 값은 void 연산자로도 얻을 수 있다.

표현식 void 는 어떤 값이든 '무효로 만들어', 항상 결과 값을 undefined로 만든다. 

관례에 따라 void만으로 undefined 값을 나타내려면 void 0 이라고 쓴다.

 

var a = 42;

console.log( void a, a ); // undefined 42
a; // 42

void 0 === undefined // true

 

즉, void 연산자는 (어떤 표현식으로부터) 값이 존재하는 곳에서 그 값이 undefined가 되어야 좋을 경우에만 사용하자.

 

특수 숫자, NaN


 

NaN은 글자 그대로 '숫자 아님, Not a Number'이고, 자세히 말하자면 '유효하지 않은, Invalid' 혹은 '실패한, Failed' 숫자가 더 정확하다.

 

NaN은 경계 값의 일종으로 숫자(Number) 집합 내에서 특별한 종류의 에러 상황을 나타낸다.

즉, NaN의 typeof는 Number 이다 !!

 

var a = 2 / "test"; // NaN
typeof a === "number"; // true

a == NaN; // false
a === NaN; // false

 

게다가 어떠한 변수값이 특수한 실패 숫자(NaN)인지 여부를 확인할때는 isNaN()로 사용해야한다.

NaN의 값은 어떤 NaN과도 동등하지 않으며, 반사성이 없는 유일무이한 값이다.

NaN = "자기가 아닌 다른 어떤 값도 항상 자신과 동등한" 유일한 값

 

var a = 2 / "test"; // NaN
isNaN(a); // true

 

ES6부터는 Number.isNaN()을 사용하면 되고, ES6 이전 브라우저에서는 다음과 같이 사용하면 안전하게 NaN여부를 확인할 수 있다.

 

if (!Number.isNaN) {
    Number.isNaN = function (num) {
        return (
            typeof n === "number" && window.isNaN(num)
        );
    };
}

var a = 2 / "test";
var b = "test";

Number.isNaN(a); // true
Number.isNaN(b); // false

 

ES6부터 잡다한 예외를 걱정하지 않아도 두 값이 절대적으로 동등한지를 확인하는 새로운 유틸리티를 지원해 이는 바로 Object.is() 이다 !!

ES6 이전 브라우저에서는다음과 같이 사용하면 된다.

 

var a = 2 / "test";
var b = -3 * 0;

Object.is(a, NaN); // true
Object.is(b, -0); // true
Object.is(b, 0); // false

// ES6 이전 브라우저의 동등 비교
if (!Object.is) {
    Object.is = function(v1, v2) {
        // '-0' 테스트
        if (v1 === 0 && v2 === 0) {
            return 1 / v1 === 1 / v2;
        }

        // 'NaN' 테스트
        if (v1 !== v1) {
            return v2 !== v2;
        }

        // 기타
        return v1 === v2;
    };
}

 


[값(value), 레퍼런스(Reference)] chati.tistory.com/150

 

[JavaScript] 값(value), 레퍼런스(Reference)

값, Value 자바스크립트는 포인터라는 개념 자체가 없고, 참조하는 방법도 조금 다르다. 어떤 변수가 다른 변수를 참조할 수 없다. !! 포인터가 없다 !! 자바스크립트에서 레퍼런스는 공유된 값을

chati.tistory.com

 


[참고] You Don't Know JS 타입과 문법, 스코프와 클로저 - 카일 심슨

 

 

반응형

❥ CHATI Github