ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 타입, 값, 변수
    Javascript 2019. 12. 20. 21:43

    원시 타입

    숫자, 텍스트, 불리언, null, undefined

     

    객체 타입

    원시 타입이 아닌 것들은 모두 객체이다.

     

    객체

    이름과 값을 갖는 property의 집합이다. 일반적인 경우 순서가 없는 값들의 집합이며, 각 값에는 이름이 지정되어 있다. 배열, 함수도 객체라고 부를 수 있다.

     

    숫자

    자바스크립트는 정수 값과 실수 값을 구분하지 않는다. 모든 숫자를 실수로 표현한다. 64비트 실수 형태로 표현한다.

    하지만, 배열 인덱싱이나 비트 연산과 같은 특정한 연산은 32비트 정수로 수행한다.

     

    정수 리터럴

    프로그램 안에 있는 그래도 등장하는 숫자는 숫자 리터럴이라고 한다. 10진수 리터럴 외에도 16진수 값을 인식한다. 

     

    부동소수점 리터럴

    실수는 정수 부분과 소수점, 소수점 이하 부분으로 표현한다. 지수 표기법으로도 표현할 수 있다. 실수에 이어 문자 e가 따라나오고, 그 뒤에 선택적으로 덧셈 혹은 뺄셈 기호가 나타나고 마지막으로 정수 지수 값이 따라온다.

    [''digits''][.''digits''][(E|e)[(+|-)]''digits'']

     

    1
    2
    3
    4
    5
    3.14
    2345.789
    .333333333
    6.02e23 // 6.02 * 10^23
    1.4738223E-32 // 1.4738223 * 10^-32

     

    산술 연산

    자바스크립트는 기본적인 산술 연산뿐 아니라, 더 복잡한 수치 연산을 Math 객체를 통해 지원한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Math.pow(2,53)    // 2^53
    Math.round(.6)    // 1.0
    Math.ceil(.6)    // 1.0
    Math.abs(-5)    // 5
    Math.log(10)     // log10
    Math.exp(3)        // e^3

    자바스크립트의 산술 연산은 오버플로와 언더플로, divide by zero 에러를 발생시키지 않는다. 오버플로 대신 Infinity로 표현한다. 언더플로는 연산 결과가 표현할 수 있는 가장 작은 값보다 0에 가까울 때 발생한다. 이런 경우 그냥 0을 돌려준다. 0을 0으로 나누는 것은 정의되지 않은 값을 갖는다. 이러한 값은 NaN으로 출력한다. 자바스크립트는 양의 무한대와 숫자가 아닌 값을 표현하기 위해 전역 변수 Infinity, NaN을 미리 정의한다. 또한, NaN은 자신뿐만 아니라 다른 값과 같은지 비교할 수 없다. 변수 x가 NaN인지 판단하기 위해 x == NaN문을 작성할 수 없다.

     

    이진 부동소수점과 반올림 오류

    자바스크립트에서 사용하는 부동소수점 표현 방식은 1/2, 1/8, 1/1024 같은 분수를 정확하게 표현할 수 있는 이진 표현법이다. 그러나, 가장 많이 사용하는 10진수 분수로 1/10, 1/100 등 인데, 이진 표현법으로는 0.1과 같은 간단한 값도 정확하게 표현할 수 없다.

    1
    2
    3
    4
    5
    var x = .3 - .2;
    var y = .2 - .1;
    == y     // false
    == .1 // false
    == .1 // true

    위와 같은 오류는 이진 부동소수점 수샂를 사용하는 프로그래밍 언어의 공통적인 현상이다. 반올림 문제를 피하기 위해서는 민감한 금융 계산에는 환산된 정수 값을 이용해야 할 수도 있다.

     

    날짜와 시간

    코어 자바스크립트는 날짜와 시간을 표현하는 객체를 생성하는 Date() 생성자를 제공한다. Date 객체는 간단한 날짜 계산을 하는 메서드를 가지고 있다.

    1
    2
    3
    4
    5
    6
    var later = new Date(201001171030);
     
    later.getFullYear()
    later.getMonth()
    later.toString()
    later.toUTCString()

     

    텍스트

    문자열은 16비트 값들이 연속적으로 나열된 변경이 불가능한 값으로, 각 문자는 유니코드 문자로 표현된다. 문자열의 길이 값은 문자열에 들어있는 16비트 값의 개수이다. 배열과 문자열은 0 기반의 인덱싱을 이용한다.

     

    문자열 리터럴

    문자열 그대로를 포함하려면 따옴표(' 또는 ")로 둘러싸면 된다.

    1
    2
    3
    4
    ""
    'testing'
    "3.14"
    "O'Reily's book"

    ECMA Script5 에서는 줄 끝에 역슬래시를 놓으면 한 줄을 여러 줄로 작성할 수 있다. 역슬래시와 그 뒤에 오는 줄 종료자는 문자열 리터럴의 일부가 아니다.

     

    문자열 리터럴 내의 이스케이프 문자열 

    시퀀스 표현하는 문자
    \0 널 문자
    \b 역스페이스
    \t 수평 탭
    \n 줄바꿈 문자
    \v 수직 탭
    \f 폼 피드
    \r 캐리지 리턴
    \" 큰따옴표
    \' 작은따옴표 
    \\ 역슬래시
    \x 두 개의 16진수 숫자에 의해 지정되는 Latin-1
    \u 네 개의 16진수 숫자에 의해 지정되는 유니코드

     

    문자열 다루기

    여러 문자열을 + 연산자를 사용해서 이어붙이는 것이 가능하다. 또한, 길이를 알 수 있는 length 프로퍼티가 있으며 이 외에도 다양한 메서드가 존재한다.(문자의 위치 찾기, 문자 대체, 문자열 쪼개기 등)

    패턴 매칭

    자바스크립트는 문자 패턴을 나타내는 객체를 생성하기 위해 RegExp() 생성자를 정의한다. 이 패턴은 정규 표현식이라 부르며, 그 중에서도 펄의 구문을 따른다. 문자열과 RegExp 객체는 모두 패턴 매칭과 '검색 후 바꾸기' 기능을 수행하는 메서드를 가지고 있다.

     

    불리언

    참/거짓, on/off, yes/no를 표현한다. nudefined, null, 0, -0, NaN, ""은 모두 불리언 false 값으로 변한다. 

     

    null과 undefined

    null은 보통 아무 값도 갖지 않음을 가리킬 때 사용되며, 특별한 값을 평가하는 키워드이다. typeof 연산자를 null에 사용하면 문자열 "Object"를 반환한다. 그 결과로 볼 때, null은 객체가 없음을 뜻하는 특수한 객체 값으로 생각할 수 있다. undefined는 null 보다 더 심한 부재 상태를 나타낸다. 초기화되지 않은 변수나 존재하지 않는 객체 프로퍼티나 배열의 원소 값에 접근하려고 할 때 얻는 값이다. undefined는 반환값이 없는 함수의 반환값이다. 그리고 읽기 전용이다. 동치 연산자를 null과 undefined에 사용하면 두 값이 같다고 간주한다. 구분하기 위해서는 엄격한 연산인 ===을 사용하라.

     

    전역 객체

    전역 객체의 프로퍼티는 자바스크립트 프로그램 전역에서 사용할 수 있게 정의된 심볼이다. 자바스크립트 인터프리터가 시작할 때 새로운 전역 객체를 만들고 그 프로퍼티를 초기화한다.

    - undefined, Infinity, NaN 같은 전역 프로퍼티

    - isNaN(), parseInt(), eval() 같은 전역 함수들

    - Date(), RegExp(), String() 같은 생성자 함수들

    - Math, JSON 같은 전역 객체

    최상위 코드(함수의 일부가 아닌 코드)에서는 this 키워드를 통해 전역 객체를 참조할 수 있다.

    1
    var global = this;

     

    wrapper 객체

    자바스크립트 객체는 복합적인 값이다. 객체는 프로퍼티 또는 이름 있는 값들의 집합이며, . 표기법을 사용해 프로퍼티의 값을 참조할 수 있다. 프로퍼티의 값이 함수일 때, 우리는 그것을 메서드라고 부른다. 객체 o의 메서드 m을 호출하려면 o.m()이라고 적는다. 그런데 왜 문자열은 객체도 아닌데 프로퍼티를 가지고 있을까? 자바스크립트는 new String(s)를 호출하듯이 문자열 값을 객체로 변환하고 이 객체는 문자열 메서드를 상속한다. 숫자와 불리언 또한 같은 이유로 메서드를 가지고 있다. 임시 객체는 Number() 혹은 Boolean() 생성자를 통해 만들어지고, 메서드는 임시 객체를 통해 호출된다. 이렇게 문자열, 숫자, 불리언의 프로퍼티에 접근하려고 할 때 생성되는 임시 객체를 wrapper 객체라고 한다.

    1
    "hello".toUpperCase();    // result : "HELLO"

     원시 자료형인 "hello"를 마치 new String("hello")로 호출한 것 처럼 임시 객체로 변환해서 프로퍼티에 접근할 수 있는 것이다.

    1
    2
    3
    var a = "hello";
    a.someProperty = 111// new String(a).someProperty = 111
    a.someProperty; // undefined

    somePRoperty에 111을 대입했으나 이를 다시 사용하자 undefined가 출력되었다. 프로퍼티의 참조가 끝나면 곧바로 소멸되는 것을 알 수 있다.

     

    변경이 불가능한 원시 타입과 변경 가능 객체

    원시 타입은 값을 수정할 수 없다. 수의 값을 바꾸면, 그것은 다른 수가 되기 때문이다. 이는 문자열도 마찬가지이다.

    1
    2
    3
    var s = "hello"// "hello"
    s.toUpperCase(); // "HELLO"
    s                 // "hello"

    객체는 자신의 값을 변경할 수 있다.

    1
    2
    3
    4
    5
    6
    var o = { x:1 };
    o.x = 2;
    o.y = 3;
    var a = [1,2,3];
    a[0= 0;
    a[3= 4;

    두 객체는 같은 프로퍼티와 값을 갖고 있어도 같지 않다.

    1
    2
    var o = { x:1 }, p = { x:1 };
    === p // false

    객체는 참조 타입으로 불리는데, 이는 자바스크립트의 원시 타입과 구별하기 위해서다. 객체의 값은 참조다. 즉, 두 객체 값이 같은 객체를 참조한다면 같다고 할 수 있다.

    1
    2
    3
    4
    5
    var a = [];
    var b = a;
    b[0= 1;
    a[0];
    === b; // true

    위의 코드를 보면 알 수 있듯이, 객체를 변수에 할당하는 것은 단순히 참조를 할당하는 것이다. 즉, 객체의 새로운 복사본을 생성하지 않는다는 뜻이다.

     

    타입 변환

    자바스크립트는 타입에 대해 매우 유연하다. 

    1
    2
    3
    4
    10 + " objects" // "10 objects"
    "7" * "4" // 28
    var n = 1 - "x" // NaN
    + " objects" // "NaN objects"

     

    변환과 동치

    자바스크립트는 값의 타입을 유연하게 변환시킬 수 있다. 따라서, 동치 연산자 == 도 유연하게 동작한다. 예를 들어, 다음의 동등 비교 예제들은 모두 true이다.

    1
    2
    3
    4
    null == undefined
    "0" == 0
    0 == false
    "0" == false
     
     

    명시적 변환

    코드를 깔끔하게 유지하기 위해, 변환을 명시적으로 하는 것을 더 선호할 수도 있을 것이다. 가장 간단한 방법은 Boolean(), Number(), String(), Object() 함수를 사용하는 것이다.

    1
    2
    3
    4
    Number("3")     // 3
    String(false)     // "false"
    Boolean([ ])     // true
    Object(3)         // new Number(3)

    null, undefined를 제외한 모든 값은 toString() 메서드를 가지고 있으며, 이 메서드의 결과는 보통 string() 함수가 반환하는 값과 같다. null, undefined를 객체로 변환하려고 하면 TypeError가 발생한다. 이 외에는 예외를 발생시키지 않지만 대신 새로 생성된 빈 객체를 반환한다. 

    어떤 연산자는 암시적 타입 변환을 수행한다.

    1
    2
    3
    + "" // String(x)
    +// Number(x)
    !!// Boolean(x)

    toString() 메서드는 몇 진수로 할지를 정하는 선택적 인자를 받는다.

    1
    2
    3
    4
    var n = 17;
    binary_string = n.toString(2); // 10001
    octal_string = n.toString(8); // 021
    hex_string = n.toString(16); // 0x11

     toFixed() 메서드는 소수점 이하 자릿수 개수를 인자로 받는다.

    1
    2
    3
    var n = 123456.789;
    n.toFixed(0); // 123457
    n.toFixed(2); // 123456.79

    toExponential() 메서드는 지수 표기법으로 변환한다.

    1
    2
    3
    var n = 123456.789;
    n.toExponential(1); // 1.2e+5;
    n.toExponential(3); // 1.235e+5;

    parseInt() 메서드는 리터럴의 일부가 숫자가 아니라도 된다. 만약 문자열이 "0x" 나 "0X"로 시작하면 16진수 숫자로 인식한다.

    1
    2
    3
    parseInt("3 blind mice")     // 3
    parseInt("-12.34")            // -12
    parseInt("0xff")            // 255

     

    변수 선언

    자바스크립에서는 변수를 사용하기 전에 변수 선언을 해야 한다. 변수는 다음과 같이 var 키워드를 이용해 선언한다.

    1
    var i, sum;

    그리고 선언과 동시에 초기화를 할 수도 있다.

    1
    2
    var message = "hello";
    var i = 0, j = 0, k = 0

     초기 값을 지정하지 않는다면, undefined 값을 갖게된다.

     

    변수의 유효범위

    지역 변수를 선언할 때 var를 사용하지 않으면, 동일한 이름의 전역 변수가 지역 변수의 값으로 오염될 위험이 있다. 자바스크립트는 C언어와 같은 블록 유효범위가 아닌 함수 유효범위를 사용한다. 해당 변수가 정의된 함수 안에서 보일 뿐 아니라, 그 함수 안에 중첩된 함수 안에서도 보인다.

     

    Hoisting

    자바스크립트 함수는 parser가 실행되기 전에 함수 안에 필요한 변수값들을 모두 모아서 유효 범위의 최상단에 선언한다. 오직 var의 선언만 위로 올라간다. 

    예를 들어, 다음과 같은 코드가 있다.

    1
    2
    3
    console.log("hello");
    var myname = "HEEE";    // var 변수 
    let myname2 = "HEEE2";    // let 변수 

    JS parser의 호이스팅 결과는 다음과 같다.

    1
    2
    3
    4
    var myname;             // [Hoisting] "선언"
    console.log("hello");
    myname = "HEEE";         // "할당"
    let myname2 = "HEEE2";     // [Hoisting] 발생 X

    출처

    Javascript the definitive guide 6/E - David Flanagan

    https://includestdio.tistory.com/26

    https://gmlwjd9405.github.io/2019/04/22/javascript-hoisting.html

     

    'Javascript' 카테고리의 다른 글

    객체와 배열  (0) 2020.01.02
    문장  (0) 2020.01.02
    변수  (0) 2020.01.02
    표현식과 연산자  (0) 2019.12.22
    어휘 구조  (0) 2019.12.20
Designed by Tistory.