변수

자바스크립트 변수에 대해서 알아보자

데이터 타입

  • 숫자

    • 자바스크립트 에서는 정수와 실수값을 구분하지 않고 모두 64비트의 실수로 표현한다.

    • 배열 인덱싱과 비트 연산과 같은 특정연산은 32비트 정수로 수행한다.

    • 표현이 가능한 범위를 벗어난 숫자는 (+/-)Infinity 로 표현된다.

    • 또한 오버플로우, 언터플로우, 0 에 관한 별도의 에러를 발생시키지 않는다.

    • 0을 0으로 나누는 연산은 정의된 값으로 표현할 수가 없기에 'NaN' 이라는 키워드로 표현된다.

  • 문자

    • 딱히 정리할 필요는 없어 보인다.

    • '\' 를 활용하여 문자열 사이에 특별히 표한하고자 하는 문자를 삽입할 수 있다.

  • 정규표현식

    • RegExp() 생성자라는 것을 통해서 문자열을 검증할 수 있다.

    • 에초에 정규표현식은 가독성이 지나치게 떨어지기 떄문에 본인은 주로 정규표현식 검증 해당 사이트를 활용한다.

  • null : 값이 없다.

  • undefined : 초기화 되지 않은 변수나 기타요소에 접근하려 할때 발생되는 일종의 전역 프로퍼티

  • 묵시적, 명시적 타입의 형변환

    • 자바스크립트는 비교적 형변환에 대해서 유연하다.

    • 그러나 자바스크립트의 이와 같은 특성 때문에 골치를 썩었던 경험을 남기고자 한다.

    • 명시적으로 간단한 형변환을 취해 별도의 wrapper 객체를 활용하는 것보다

      간편하게 숫자형태로 형변환을 가미했으나, 앞서 말한 특정 연산자는 32비트 이내로

      표현이 가능하기 때문에 명시적인 형변환이라고 하더라도 안심해서는 안된다.

  • 객체

    • 복합적인 요소를 가지고 있는 값으로 생각하면된다.

    • 프로퍼티 혹은 명명되어 있는 값들의 집합을 의미한다.

    • 내부요소는 '.' 을 통하여 참조가 가능하다.

    • 문자열 리터럴은 객체가 아니지만 내부적으로 객체로 변환되기 때문에 해당 객체에 정의된 문자열과 관련된 요소를 참조할 수 있다.

           var s = "hello word";
           s.substring(3,4);
    • 숫자와, 불리언도 위와 비슷한 이유로 필요한 메서드를 별도의 선언없이 참조할 수 있다.

    • 위와 같은 기본 리터럴들의 객체를 wrapper 객체라고 한다.

    • wrapper 에는 참조만 가능하고, 할당은 불가하기에 유의한다.

    • 객체는 mutable 과 같은 특성을 가지고 있고 간단하게 이야기하여 자신의 값을 변경이 가능하다.

      • 값으로 비교되지 않으며 참조에 의하여 비교가 되므로 객체 내부의 특정 값과 비교하려면 '===' 과 같은 연산자, 혹은 비교 함수를 선언하여 비교한다.

    • 객체에서 원시타입 변환시 특이케이스 정리

      • 객체를 문자열로 변환시 흐름

        • 객체가 toString() 메서드를 통하여 반환하는 값이 원시 타입의 값이 아니라면, valueOf() 메서드의 호출과정으로 원시 타입값을 확인하려하고, 둘다 없는 경우 TypeError 을 발생시킨다.

      • 객체를 숫자로 변환시 흐름

        • 위의 문자열로 변환시 흐름과 반대로 valueOf() -> toString() -> TypeError 과정을 거친다.

        • 빈 배열을 이외 같은 경우 때문에 0 으로 반환되곤 한다. 배열은 기본적으로 valueOf() 를 상속한다.

          또한 배열의 숫자형태 변환은 toString() 메서드에 의존한다.

          • 배열은 때문에 다음과 같은 과정이 일어난다.

            • [] -> "" -> 0

            • [3] -> "3" -> 3

  • 전역 객체

    • 자바스크립트 전역에서 사용하도록 정의된 심벌이다.

    • 인터프리터가 기동될 떄, 새로운 웹페이지가 로딩될 때 여러 내부에 정의된 프로퍼티들을 초기화한다.

    • undefined, Infinity, Nan 등은 전역 객체 내부에 있고 엄밀히 이야기해서 예약어는 아니지만, 동일하게 취급된다.

  • 객체는 객체가 가진 고유한 프로퍼티를 유지하는 것 외에 프로토타입(Proto Type)이라 불리우는 최상위 Object의 프로퍼티를 상속받는다.

  • 또한 프로퍼티는 동적으로 추가 및 제거가 가능하다.

  • 여기서 말하는 프로퍼티는 key/value 형식에 존재하는 객체 내의 집합을 의미한다.

  • 프로퍼티 속성(property attribute)

    • ES5 부터는 사용자가 생성한 프로퍼티의 속성만을 변경이 가능하다.

    • writable : 프로퍼티의 값의 수정 여부를 결정

    • enumerable : 프로퍼티의 이름을 for/in 구문에서 읽을 수 있는지 결정

    • configurable : 프로퍼티의 삭제/변경 가능 여부

  • 오브젝트 속성(object attribute)

    • prototype : 상속받은 프로퍼티들에 대한 객체를 참조한다.

    • class : 객체의 자표형을 특정.

    • extensible : 새로운 프로퍼티를 추가할 수 있는지 여부

  • 오브젝트

    • 네이티브 오브젝트 : 이미 선언되어있는 객체들의 클래스 (배열, 정규표현식, 날짜 등등)

    • 호스트 오브젝트 : 브라우저 및 자바스크립트 인터프리터가 내장된 호스트의 환경에 정의된 객

    • 사용자정의 오브젝트 : 사용자가 작성한 코드에 의해 생성된 객체

  • 프로퍼티

    • 고유 프로퍼티 : 객체에 직접 정의된 프로퍼티

    • 상속된 프로퍼티 : 해당 객체의 프로토타입 객체가 정의한 프로퍼티를 의미

  • 객체의 생성방식

    • 객체 리터럴을 통한 방식

      var myObject = {};
      var myObject2 = {kbh : 32};
    • new 키워드 활용

      var myObjectCreateByConstructor = new Object();
      var myObjectCreateByConstructor = new RegExp("js");
    • Object.create()

      • 이해하기에 앞서 프로토타입이 무엇인가 잠시 훑어보고 넘어간다.

      • 대상이 되는 객체에 프로퍼티들을 제공해주는 객체를 의미한다.

      • 객체 리터럴 '{}' 로 선언된 모든 객체의 프로토타입은 같다.

      • 모든 프로토타입의 최상위는 Object 이며, 각 객체별로 프로토타입들이 연결된 구조를

        프로토 타입 체인이라고 정의한다.

      • 다음을 살펴본다. Object.create에 {1} 에 인자값으로 프로토타입을 주입하여

        넣는게 가능하며, {2}에 인자값으로 프로퍼티 속성을 주입할 수 있다.

        {1} 인자에 생략도 가능하지만, 이럴경우 최상의 Object에 선언된 기본적인 메서드 사용불가 및

        연산자 조차 사용이 불가능하다.

           var myObjectCreateByInjectPrototypeArgument 
              = Object.create({1},{2});
      • 특정한 프로토타입을 상속 받도록 메서드를 통해 금지 시킬 수 있으나, 내 개발 업무 내의 ES5 기준으로 이런 코드를 작성할 일이 없기 때문에, 생략한다.

      • Object의 프로퍼티에 접근하는 방법은 다음 두가지

          var myObject = {x : 1};
          console.log(myObject['x']);
          console.log(myObject.x);
        • 두 표현식은 동일하다. 위의 배열 형식으로 접근하기 위해 기술된 배열을 연관 배열(associate array) 이라 명명되기도 하고 hash, map, dictionary 라고도 한다. 모든 오브젝트는 연관 배열이다.

        • 타 언어는 정해진 수의 프로퍼티를 가져야 하고 반드시 프로퍼티의 이름을 미리 정의 해두어야하나 자바스크립트에서는 타입이 제약이 느슨하기 때문에 이런 규칙이 적용되지 않는다.

        • 프로퍼티의 이름을 반드시 식별자로 표현해야하며, 작성자가 직접 만든 이름이르모 자료형이 존재하지 않기에 프로그램 실행되는 도중에 변경이 불가하다.

        • 하지만 연관 배열을 사용해 객체의 프로퍼티에 접근시에는 식별자가 문자열이기 떄문에 프로그램 실행 도중 생성하고 접근이 가능하다. 무슨 소리이인지는 다음의 코드를 보면 알 수 있다.

          var addr = "";
          
          //가상의 customer 에 addr1, addr2 .... 등으로 이루어진 프로퍼티가 있다고 가정해보자
          
          for (i = 0; i < 4; i++){
            addr += customer["addr" + i] // 와 같은 형식으로 유동적인 접근이 가능하다.
          }
  • 프로퍼티 삭제

    • delete 키워드를 사용하면 되며, 이때 대상 객체의 고유한 프로퍼티가 아니라고 하면 삭제하지 않기 때문에 주의한다.

    • 대상 오브젝트의 프로퍼티 속성중 configurable 속성이 'false'인 경우 삭제 불가

      • nonextensible 객체에 속한 configurable 속성이 'true'인 경우 삭제가 가능

  • 프로퍼티 검사

    • in, hasOwnProperty(), propertyIsEnumerable(), 직접 접근하는 방식 등으로 검사가 가능하다.

    • propertyIsEnumerable() 의 경우에는 고유한 프로퍼티가 존재하고, Enumerable 속성이 true 인 경우에만 true 값을 반환한다.

  • 프로퍼티 열거하기

    • 객체의 모든 프로퍼티를 특정한 순회가 필요할 경우 사용 방법이 존재한다.

      • for/in 방식으로 순회하기

        • 고유 프로퍼티만 반환하는 것이 아니기 때문에 별도의 작업이 필요하다.

      • Object.keys() 함수를 사용하기

        • 열거가 가능한(Enumerable)한 프로퍼티의 이름을 배열형태로 반환한다.

      • Object.getOwnPropertyNames() 함수 사용하기

        • 해당 객체의 모든 고유 프로퍼티의 이름을 반환한다.

  • 프로퍼티 getter/ setter

    • 프로퍼티에 대한 접근자 프로퍼티(accessor property) 라고 할 수있다.

    • 타 프로퍼티와 다르게 키/값 형식으로 작성하지 않고 각각의 키워드와 함수가 같이 작성된다.

    • 솔직히 말해서 결론적으로는 안쓸거 같다.

    • getter()

      • 객체의 접근자 프로퍼티의 값에 접근 시, 자바스크립트 엔진은 getter()에 인자 값을 포함하지 않고 호출한다.

      • getter()의 반환 값이 프로퍼티 접근 표현식의 값이 된다.

      • writable 속성을 가진다.

    • setter()

      • 반대로 setter()는 프로퍼티의 값을 변경하고자 할때, 자바스크립트 엔진이 호출한다.

      • getter()와 다르게 아무런 속성을 가지지 않는다 반환값이 무시되기 떄문인듯 하다.

        정확히는 undefined 가 반환된다.

  • 프로퍼티 속성

    • ES5에서 js 라이브러리를 만드려고 할 시에 알아야할 API 들의 소개가 될 것이다.

    • 이 목차에서는 getter/setter 메서드를 프로퍼티가 가진 속성으로 간주하였고,

      이러한 방식으로 생각하면 데이터 프로퍼티의 값도 속성이라고 이야기한다.

    • 접근자 프로퍼티는 value, writable 속성이 없다. 그러나 writable 속성은 setter 메서드의 존재 여부에 따라서 결정이 된다. 그래서 위와 같은 서론을 통해서 아래와 같이 프로퍼티 속성의 종류를 정한다.

    • 데이터 프로퍼티 속성

      • value, writable, enumerable, configurable

    • 접근자 프로퍼티 속성

      • get, set, enumerable, configurable

      • 위를 표한하기 위하여 property descriptor 라는 특수한 객체를 사용한다.

        이 객체의 프로퍼티 이름은 표현하고자하는 대상의 속성의 이름과 같고 getOwnPropertyDescriptor()를 통해 얻을수 있다. 상속받은 프로퍼티의 속성에 대한 검증은 프로토타입 체인을 명기적으로 순회해야한다. 이 부분(getPrototypeOf)에 대해서는 별도의 스터디의 목차에서 다룬다.

    • getter/setter 를 제외하고 모두 boolean 값만 가지고있다.

    • 직접 프로퍼티의 속성을 정하고자 할때 Object.defineProperty() 를 이용하는 것도 하나의 방법이다.

      • 인자 값으로 프로퍼티 디스크립터 객체는 유동적으로 정의가 가능하다. (항상 풀세트로 정의하지 않아도 된다.)

      • 프로퍼티 디스크립터 객체에 속성이 지정되어 있지 않으면 그대로 유지된다.

      • 주의점은 상속받은 프로퍼티의 속성을 바꾸지 않으니 주의한다.

      • 여러 프로퍼티를 만들거나 수정이 필요한 경우, Object.defineProperties()를 활용한다.

      • 또한 nonextensible 속성을 가진 객체에 위 메서드로 프로퍼티의 변경을 가미시 TypeError 이 발생한다.

      • 이외도 주의 점이 참 많기때문에 '자바스크립트 완벽가이드 p166~167'을 참고한다.

    • 이외에도 기타 요소 속성들이 많다. '자바스크립트 완벽가이드 p167~172' 를 참고하자

  • 객체 직렬화 하기

    • JSON.stringfy()/ JSON.parse() 각각 객체 <--> 직렬화 역활을 담당한다.

    • 표현이 불가능한 값들은 null로 표기된다.

    • 인자값으로 가공하고자하는 프로퍼티의 목록을 지정할 수 있다.

    • 자세한건 '자바스크립트 완벽가이드 후반부 레퍼런스' 참고

  • 객체 메서드

    • 어느 객체에서나 사용이 가능하도록 한 메서드들 이며, Object.prototype 의 프로퍼티를 상속받는다.

    • toString() : 각 객체들이 정의한 고유한 결과 값을 반환한다. 특별히 없는 경우에는 [object Object]를 반환한다.

    • toLocaleString() : 지역화(localize) 된 정보를 반환하는 것이 목적, 특별히 이 메서드를 정의한 객체가 아니라면 toString과 동일하게 작동한다.

    • toJSON() : 다른 메서드들과 다르게 Object.protoType 에 정의 되있지 않으나, JSON.stringfy() 는 이 메서드가 있는 경우 원래 객체 대신 이 메서드의 결과 값을 직렬화 한다.

    • valueOf() : 원시타입으로 변환용도로 쓰이고, 원시타입이 활용되어야하는 문맥에서 호출 과정이 이루어 진다.

Last updated