[JS] 06. 자료형과 객체

블랑·2023년 3월 10일
0

원시 타입 자료형(primitive type)

자료형 : 숫자

실수형 자료형만 존재 + 리터럴

  1. JS 숫자 자료형의 가장 큰 특징은 숫자를 정수와 실수로 구분하지 않는 것이다.
    = 모든 숫자를 8Byte의 실수 형태로 처리한다(정수형이 존재하지 않는다.)
    = 숫자형 데이터는 number 타입으로 분류된다.

  2. 하지만 편의성을 위해 정수 리터럴과 실수 리터럴을 제공한다.

  3. 기본 연산 기호는 일반 프로그래밍 언어와 같다.

  4. 언더플로우, 오버플로우, 0으로 나누는 연산에 예외처리를 하지 않는다.

  5. JS에 존재하는 숫자와 관련된 특별한 상수 :

  • Infinity : 무한대 상수
  • NaN : 계산식의 결과가 숫자가 아닐 때 나타내는 상수

    자료형 : 문자

    문자열은 16비트의 Unicode 문자를 사용한다.
    또한 char의 존재가 없다. (= 모든 것을 문자열로 표현한다!)

  1. 작은 따옴표('), 큰 따옴표(") 모두 사용 가능하며 혼용 불가하다.
  2. (\)이스케이프 시퀀스 역시 사용 가능하다.

자료형 : boolean, null과 undefined

JAVA와 유사하다. 다만 undefined는 null과 다르니 유의하자.
null : 값이 없거나 비어 있음
undefined : 값이 초기화되지 않음(정의되지 않았다).

java에서 int a;를 선언한 뒤 a 변수를 사용할 때 발생하는 것과 유사한 개념이다.

자료형 동적 변환 :

JS에서는 형변환을 느슨하게 적용한다.

어떤 자료형도 변환 가능하고, 다른 자료형도 연산 가능하다는 뜻이다.
이로 인해 혼란을 야기하게 된다. 이를 해결하고자 let, const 등의 개념이 탄생하였다.
이 부분은 아래의 호이스팅과 상수 자료형에 조금 더 자세히 서술하도록 한다.

변수 호이스팅(Variable Hoisting)

var 선언, function 선언 등 모든 선언문이 해당 Scope의 처음으로 옮겨진 것처럼 동작하는 특성

var 키워드를 사용한 변수는 중복해서 선언이 가능하다.
JAVA의 경우 이렇게 중복 선언을 하면 에러가 나지만, JS의 경우 호이스팅으로 모든 선언문을 끌어올리기 때문에 계속해서 재정의가 가능하다.

  자바스크립트에서 var 키워드로 변수를 선언하면, 
  해당 변수는 함수 스코프(function scope) 또는 전역 스코프(global scope)에서 유효하다.
  변수가 선언되면, 해당 변수는 선언하기 이전에도 참조할 수 있는 것이다. 
  이것이 "hoisting(호이스팅)"의 개념이다.

  Q. 예를 들어, 아래와 같은 코드를 실행하면?
  
  	console.log(a);
	var a = 1;
	console.log(a);
	var a = 2;
	console.log(a);
  
  ------------------ [결과]
  	undefined
	1
	2
  
  
  /*설명
  1. 위 코드에서 변수 a는 처음에 선언되기 전에 console.log(a)를 호출한다. 
  하지만 호이스팅에 의해 var a = 1 이전에 a 변수가 이미 생성되어 있는 상태이다. 
  그래서 첫 번째 console.log(a)에서는 undefined가 출력된다.

  2. 이후 a 변수에 1을 대입하고, 다시 console.log(a)를 호출하면 1이 출력된다. 
  그리고 a 변수에 2를 대입하고, 다시 console.log(a)를 호출하면 2가 출력된다.

  3. 따라서 var 키워드로 선언된 변수는 호이스팅이 발생하므로, 변수 선언 위치와 상관없이 언제든지 참조가능하다.
  따라서 var 키워드를 여러번 사용해 같은 변수를 재정의해도, 호이스팅에 의해 변수가 이미 생성되었기에 문제가 없다.
  
  */
  

호이스팅 예제 2

<script>
      /*
      호이스팅 : 위쪽으로 끌어올린다.

      2단계로 실행을 나눈다.
      1단계 : 변수 또는 함수의 선언을 위쪽으로 끌어올린다.
      2단계 : 값의 대입 등을 처리, 문장 실행

      */
      fn1(); //호이스팅이 되어 에러 발생하지 않음.
      fn2(); //에러 발생 : 선언되지 않음
      function fn1() {
          console.log('fn1');
      } //선언식
      let fn2 = function() { //값의 대입이기에, 선언이 아니다! : 호이스팅은 선언만 끌어올린다.
          console.log('fn2');
      }; //표현식

      fn1(); 
      fn2();
  </script>

예제 3

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        function fn() {
            console.log(i);  //undefined 에러 발생. var i;가 끌어올려지나, 값은 지정되지 않았다.
            for (var i = 0; 1 < 9; i++) {
                console.log(i);  //제대로 출력된다.
            }
            console.log(i);  

            var j = 10;
            if (j >= 10) {
                var msg = '조건 실행';
            }
            console.log(msg);
        }
        fn();
    </script>
</body>
</html>

자료형 : 상수

ES6부터 추가된 개념으로 변수의 값을 변경하면 안 되는 상수와 일반 변수를 구분하고자 규칙을 다르게 하여 사용한다.

상수의 표기법은 모든 문자를 대문자로 사용하고 단어 사이는 '_'로 표기한다.

이 부분에서 letconst의 개념이 추가되었다.

const와 let은 모두 변수를 선언하는 키워드이지만, 사용 방법과 특징이 다르다.

1. const [상수]
const는 상수를 선언할 때 사용되며, 선언과 동시에 값을 할당하고 이후에 값의 변경이 불가능하다. 
예를 들어, const PI = 3.14;와 같이 선언된 상수는 이후에 PI = 3.14159;와 같이 재할당이 불가능하다.

2. let [변수]
let은 변수를 선언할 때 사용되며, 선언과 동시에 값을 할당하지 않아도 된다. 이후 변수의 값은 변경 가능하다. 
예를 들어, let x;와 같이 선언된 변수는 이후에 x = 10;와 같이 값을 할당할 수 있다.

3. 스코프 차이
또한, const와 let은 변수의 스코프(scope)가 다르다. 
const는 블록 레벨 스코프(block-level scope)를 가지고 있으며, 
let은 블록 레벨 스코프와 함수 레벨 스코프(function-level scope)를 가지고 있다.

이는 let으로 선언된 변수는 '해당 블록에서만 유효'하고, 
const로 선언된 상수는 '해당 블록 내부에서도 값을 변경할 수 없다'는 것을 의미한다.

4. 결론?
따라서, 변수의 값을 변경할 일이 없다면 const를 사용하고, 
값이 변경될 가능성이 있다면 let을 사용하는 것이 좋다.
  • 더해서 'let'과 'var'의 차이는 다음과 같다.
    둘 다 변수를 선언하는 자료형이라서 헷갈리기 쉬웠으니 유의하자.
    1. 스코프 차이
      let은 블록 스코프(해당 변수가 선언된 중괄호({}) 내에서만 유효),
      var은 함수 스코프(변수가 선언된 함수 내에서만 유효 -> 변수가 선언된 함수 외부에서도 접근 가능. 이는 전역 변수(global variable)와 유사한 특징이다.)
    1. 호이스팅 여부
      let은 호이스팅 불가능, var은 호이스팅이 발생(undifined로 초기화)
    1. 재선언
      let은 불가능, var은 가능
    1. 전역 객체 연관성
      var로 선언한 변수는 전역 객체의 프로퍼티가 되며, window 객체에서도 접근할 수 있다.
      반면에 let으로 선언한 변수는 전역 객체의 프로퍼티가 불가능

      연산자

      JS의 연산자는 대부분의 언어와 동일하다. 다만 비교 연산자 '==='를 유의하도록 하자.
      해당 연산자는 값과 데이터 타입을 둘 다 비교한다.

객체(Object)

정의

객체는 이름과 값으로 구성된 프로퍼티의 집합이다.

프로퍼티(property) : 객체(object)의 속성(attribute)을 나타내는 이름과 값으로 구성된 쌍(pair). = 내부 요소
객체는 여러 개의 프로퍼티를 가지고 있으며, 이들은 객체 내에서 유일한 이름으로 식별된다.

앞서 정의했던 기본 자료형(문자열, 숫자, boolean, null, undefined)을 제외한 모든 값은 객체이다.

특성 : 프로퍼티

또한, 전역 객체를 제외한 JS객체는 프로퍼티를 동적으로 추가하거나 삭제할 수 있다!

그리고 함수 역시도 객체이므로 값으로 사용할 수 있다. 이는 어떠한 함수가 다른 객체의 프로퍼티의 값으로 쓰일 수 있다는 이야기이다.
즉, JavaScript에서 함수는 객체이기 때문에 다른 객체처럼 객체 속성으로 사용될 수 있다. 이것은 함수를 다른 함수의 인자로 전달하거나 객체에 메소드로 포함시키는 것을 가능하게 한다.

const myObj = {
name: "John",
sayHello: function() {
  console.log("Hello!");
}
};

myObj.sayHello(); // "Hello!" 출력

설명 :
sayHello 함수는 myObj 객체의 속성 값으로 사용되었다. 
따라서 myObj.sayHello()를 호출하면 "Hello!"라는 문자열이 출력된다.

객체의 생성 방법

JavaScript에서 객체는 중괄호({})를 사용하여 생성된다.

객체는 이름과 값을 가지는 속성으로 구성된다.
객체를 생성하는 방법은 1. 객체 리터럴, 2. new 연산자와 Object 생성자 함수, 3. 생성자 함수, 4. Object.create() 메서드가 존재한다.

  1. 객체 리터럴
    가장 일반적인 방법으로, 중괄호 내에 속성을 정의한다.
const myObj = {
  name: "John",
  age: 30,
  hobbies: ["reading", "running"]
};
  1. new 연산자와 Object 생성자 함수
    new 연산자를 사용하여 Object 생성자 함수를 호출한다.
const myObj = new Object();
myObj.name = "John";
myObj.age = 30;
myObj.hobbies = ["reading", "running"]; 
  1. 생성자 함수
    생성자 함수를 사용하여 객체를 생성한다.
function Person(name, age) {
  this.name = name;
  this.age = age;
}

const john = new Person("John", 30);
  1. Object.create 메소드
    Object.create() 메소드를 사용하여 객체를 생성할 수 있다.
    이 메소드는 새로운 객체를 생성하고 지정된 프로토타입 객체를 상속한다.
const personProto = {
  introduce: function() {
    console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
  }
};

const john = Object.create(personProto);
john.name = "John";
john.age = 30;

객체 속성 값 CRUD

속성 값 조회는 기존 JAVA와 유사하다. 하지만, dot(.)을 사용하여 속성 값에 접근하는 것과 달리, 대괄호를 사용하여 속성 값에 접근할 수도 있다. (object["property"])

문자열 타입은 점 표기법으로 접근할 수 없다. 다음과 같은 예시를 살펴보자.

const person = {
name: "John",
age: 30,
"phone number": "010-1234-5678"
};

-------- 접근(조회)

//점 표기법 접근
console.log(person.name); // "John"
console.log(person.age); // 30

//문자열 타입은 대괄호를 사용하여 조회해야 한다.
console.log(person["phone number"]); // "010-1234-5678"

//다음과 같이 속성 이름이 변수에 저장되어 있을 때, 대괄호를 사용하여 조회하는 방법이 유용하다.
const propertyName = "age";
console.log(person[propertyName]); // 30

--------- (변경, 추가, 제거)

person.age = 25; //25로 변경
person['age'] = 25;

//없는 개념일 경우 자동으로 추가된다.
person.newProp = '없는 개념 추가';

//제거는 delete 연산자를 사용한다.
delete person.newProp;

함수 선언

<script type="text/javascript">
    var result = plus(5, 7);
    console.log(result); // 12

	//함수의 선언식
    function plus(num1, num2) {
      return num1 + num2; //만약 리턴이 없다면 'undefined' 값이 리턴됨.
    }

	//함수의 선언식 표현 : 이름이 없는 객체로 생성.
	var plus2 = function (num1, num2) {
    return num1 + num2;
    };
	// number, boolean, string, null, undfined, symbol(ES6부터 적용) <- 기본형
	// object : 함수는 객체 타입에 속한다.
  </script>
<script>
      fn1(); //2. fn1은 호출된다
      fn2(); //fn2은 에러가 발생한다. (선언된 이후에 호출이 가능하다.)
		====> 이 게시글 위에 봤던 호이스팅 탭을 참조하면 도움이 될 것이다.
      function fn1() {
          console.log('fn1');
      } //선언식
      let fn2 = function() {
          console.log('fn2');
      }; //표현식

      fn1(); //1. 잘 선언된다.
      fn2();
  </script>
profile
안녕하세요.

0개의 댓글