1. 문장(Statements) 과 표현식(Expressions)


문장(Statements)


Javascript 에서 문장은 어떤 동작이 일어나도록 작성된 최소한의 코드덩어리를 가리킨다.


let x;  // 선언문(문장)
x = 3;  // 할당문(문장)

// 문장
if (x < 5) {
	console.log('x는 5보다 작다');
} else {
	console.log('x는 5와 같거나 크다');
}

// 문장
for (let i = 0; i < 5; i++) {
	console.log(i);
}

표현식

표현식은 결과적으로 하나의 값이 되는 모든 코드를 가리킨다.


  • 어떤 하나의 값을 그대로 작성하는 것 → 표현식

    5  // 5
    'string'  // string

  • 연산자를 이용한 연산식 → 하나의 값 → 표현식

    5 + 7   // 12
    'I' + 'Love' + 'Adam'  // I Love Adam
    
    true || false  // true

  • 선언된 변수를 호출, 객체의 프로퍼티에 접근 → 하나의 값 → 표현식

    ⇒ 결국 길이와는 상관없이 결과적으로 하나의 값이 되는 코드를 모두 표현식이라 한다.

    // 할당 연산자는 값을 할당하는 동작도 하지만, 할당한 값을 그대로 가지는 표현식이다.
    const title = 'Javascript';
    const language = {
    	name: 'Python',
    };
    const numbers = [1, 2, 3];
    
    typeof language  // object
    title  // Javascript
    language.name  //Python
    numbers[3]  // undefined

  • 표현식이면서 문장, 문장이면서 표현식
    // 할당 연산자는 값을 할당하는 동작도 하지만, 할당한 값을 그대로 가지는 표현식이다.
    title = 'Python'; // Python
    
    // 함수 호출은 함수를 실행하는 동작도 하지만, 실행한 함수의 리턴 값을 가지는 표현식이다.
    sayHello(); // sayHello 함수의 리턴 값
    
    // console.log 메소드는 콘솔에 아규먼트를 출력하는 동작도 하지만, undefined 값을 가지는 표현식이다.
    console.log('Hi'); // undefined

표현식인 문장 Vs 표현식이 아닌 문장

결과적으로 문장은 다시 표현식인 문장과, 표현식이 아닌 문장으로 나눌 수 있고, 이 둘을 구분하는 가장 간단한 방법은 구분하고자 하는 문장을 변수에 할당하거나 어떤 함수의 아규먼트로 전달해보는 것이다.

console.log 메소드의 아규먼트로 if 문을 전달하거나 어떤 변수에 for 반복문을 할당하게 되면 Error 가 발생하게 된다. === 조건문이나 반복문은 값으로 평가되지 않고 오로지 문장으로만 평가되기 때문


💡 자바스크립트에서는 특별한 경우를 제외하면 일반적으로 표현식인 문장은 세미콜론(;) 으로, 표현식이 아닌 문장은 문장 자체의 코드블록(중괄호 {})로 그 문장의 범위가 구분된다.

3 + 4*2;
console.log('Hello');

for (let arg of arguments) {
	// 동작
}


2. 조건 연산자


삼항 연산자

  • 조건 ? 조건이 truthy 할 때 표현식 : 조건이 falsy 할 때 표현식;

    const con = false
    const name = con ? 'Adam' : 'Eve'
    console.log(name)  // Eve
  • Python

    con = False
    name = 'Adam' if con else 'Eve'
    print(name)


3. Spread 구문


여러개의 값을 묶은 하나의 배열을 각각의 개별 값으로 펼치는 문법


const numbers = [1, 2, 3]

console.log(...numbers)  //  1 2 3
console.log(1, 2, 3)     //  1 2 3

const numbers1 = [1, 2]
const numbers2 = [3, 4]

console.log([...numbers1, ...numbers2])   // [1, 2, 3, 4]

const members = ['adam', 'eve', 'noa'];
const newObj = {...members};

console.log(newObj)   // {0: 'adam', 1: 'eve', 2: 'noa'} -> index가 키값으로 담김

객체 Spread

const newObj = {
    name: 'adam',
    age: 30,
    sex: 'male',
    from: 'South of Korea'
}

const spreadObj = {
    sister: true,
		// 객체를 복사해서 spread 할 수 있다.
    ...newObj
}

console.log(spreadObj)  
// {sister: true, name: 'adam', age: 30, sex: 'male', from: 'South of Korea'}

주의 사항

  • Spread 구문을 사용해서 새로운 배열을 만든다거나 함수의 아규먼트로 사용할 수는 없다.

    객체 spread 할때는 반드시 객체를 표현하는 중괄호 안에서 활용해야 한다.

    const latte = {
      esspresso: '30ml',
      milk: '150ml'
    };
    
    const cafeMocha = {
      ...latte,
      chocolate: '20ml',
    }
    
    [...latte]; // Error
    
    (function (...args) {
      for (const arg of args) {
        console.log(arg);
      }
    })(...cafeMocha); // Error


모던한 프로퍼티 표기법


  • 키값이 변수이름 또는 함수이름과 같다면 생략이 가능하다.

    // 모던한 프로퍼티 표기법
    const firstName = 'Daehwi';
    const lastName = 'Kim';
    
    function getFullName(firstName, lastName) {
      return `${this.firstName} ${this.lastName}`
    }
    
    const user = {
      firstName: firstName,
      lastName: lastName,
      getFullName: getFullName,
    }

      ⬇️

    const user = {
      firstName,
      lastName,
      getFullName,
    }

  • 계산된 속성명 (computed property name)

    // 표현식의 값을 대괄호[]로 감싸주면 property name으로 사용할 수 있다. 
    const user = {
    	[표현식]:,
    }
    const propertyName = 'BirthDay'
    const getName = () => 'Name';
    
    const adam = {
      ['my' + 'age']: 30,
      [propertyName]: 1992,
      [getName()]: 'DaeHwi Kim'
    }
    
    console.log(adam)  // {myage: 30, BirthDay: 1992, Name: 'DaeHwi Kim'}

옵셔널 체이닝 (Optional Chaining)

일반적으로 객체의 프로퍼티는 점표기법을 통해서 접근하게되는데, ECMAScript2020에서 등장한 옵셔널 체이닝을 이용하여 간단하게 객체의 프로퍼티에 접근할 수 있다.

  • 옵셔널 체이닝 연산자( ? )

  • ? 연산자의 왼편의 프로퍼티 값이 null 혹은 undefined 값이 아니라면 그다음 프로퍼티 값을 리턴,

    그렇지 않다면 undefined 를 반환

  • 객체의 프로퍼티에 접근할 때 없는 객체를 접근할 때 Error 발생

    function printDogName(user) {
      console.log(user.dog.name);
    }
    
    const user1 = {
      name: 'Adam',
      dog: {
        name: 'Moon',
        sex: 'Female'
      }
    }
    
    const user2 = {
      name: 'Eve'
    }
    
    printDogName(user1)  // Moon
    printDogName(user2)  // TypeError: Cannot read properties of undefined (reading 'name')

  • 위의 에러를 옵셔널 체이닝(Optional Chaining) 방식과 null 병합 연산자를이용하여 에러 없이 접근

    function printDogName(user) {
      console.log(user.dog?.name ?? '반려견이 없습니다.');
    }
    
    const user1 = {
      name: 'Adam',
      dog: {
        name: 'Moon',
        sex: 'Female'
      }
    }
    
    const user2 = {
      name: 'Eve'
    }
    
    printDogName(user1)  // Moon
    printDogName(user2)  // 반려견이 없습니다.


5. 구조 분해 (Destructuring)


배열이나 객체를 분해하는 문법

1. 배열

  • 일반적인 배열을 변수에 할당하는 방법

    const ranking = ['유재석', '정준하', '정형돈', '하하', '노홍철'];
    
    const macbook = ranking[0];  // 유재석
    const iphone = ranking[1]  // 정준하
    const applewatch = ranking[2];  // 정형돈
    const airpods = ranking[3];  // 하하

  • Destructuring 문법을 이용해서 변수에 할당 (배열을 분해해서 할당)

    const ranking = ['유재석', '정준하', '정형돈', '하하', '노홍철'];
    
    const [macbook, iphone, applewatch, airpods] = ranking
    
    console.log(macbook) // 유재석
    console.log(iphone)  // 정준하
    console.log(applewatch)  // 정형돈
    console.log(airpods)  // 하하
    // 배열의 형식이 아니거나 아무것도 할당하지 않으면 Error가 난다.
    const [macbook, iphone, applewatch, airpods] = 123;  // SyntaxError
    const [macbook, iphone, applewatch, airpods];  // SyntaxError

  • 할당 방법

    const ranking = ['유재석', '정준하', '정형돈', '하하', '노홍철'];
    
    const [mac, iphone, ...others] = ranking
    
    console.log(mac)  // 유재석
    console.log(iphone)  // 정준하
    console.log(others) // ['정형돈', '하하', '노홍철']

  • undefined : 선언된 배열의 갯수가 할당하는 변수보다 적을 경우 할당되는 변수는 undefined 로 할당

    const ranking = ['유재석', '정준하'];
    
    const [mac, iphone, other] = ranking
    
    console.log(mac)  // 유재석
    console.log(iphone)  // 정준하
    console.log(other) // undefined

    기본 값을 정하여 할당할 수 있다.

    const ranking = ['유재석', '정준하'];
    
    const [mac, iphone, other = 'other'] = ranking
    
    console.log(mac)  // 유재석
    console.log(iphone)  // 정준하
    console.log(other) // other

  • 변수를 교환하여 할당할 수 있다.

    let mac = 'Adam';
    let win = 'Eve';
    
    console.log(mac);  // Adam
    console.log(win);  // Eve
    
    [mac, win] = [win, mac]
    
    console.log(mac);  // Eve
    console.log(win);  // Adam

2. 객체 분해

const win = {
  title: 'HP Desktop',
  price: 700000,
  memory: '16GB',
  storage: '1TB SSD'
}

// 객체의 프로퍼티에 따른 구조분해
const { title, price, display, mouse = 'Logitech' } = win

console.log(title)  // HP Desktop
console.log(price)  // 700000

console.log(display)  // 객체의 없는 프로퍼티는 undefined로 반환
console.log(mouse)  // Logitech -> 기본값으로 선언한 값

  • rest parameter 이용 : ...
  • 객체의 프로퍼티네임 지정하여 할당 : titleproduct
    
    const { title: product, ...rest } = win
    
    console.log(product)  // HP Desktop
    console.log(rest)  // {price: 700000, memory: '16GB', storage: '1TB SSD'} 

  • computed property name을 이용한 새로운 변수이름으로 할당

    const propertyName = 'title';
    const { [propertyName]: product } = win
    
    console.log(product)  // HP Desktop

3. 함수와 Destructuring

  • 함수의 파라미터가 배열일때 Destructuring

    function printRank([first, second, third, ...rest]) {
      console.log(first)
      console.log(second)
      console.log(third)
      console.log(rest)
    }
    
    const members = ['유재석', '하하', '정형돈', '정준하', '박명수']
    
    printRank(members)
    // 유재석
    // 하하
    // 정형돈
    // ['정준하', '박명수']

  • 함수의 파라미터가 객체일때 Destructuring

    const win = {
      title: 'HP Desktop',
      price: 700000,
      memory: '16GB',
      storage: '1TB SSD'
    }
    
    function printProduct({ title, price, memory }) {
      console.log('title: ', title)
      console.log('price: ', price)
      console.log('memory: ', memory)
    }
    
    printProduct(win)
    
    // title:  HP Desktop
    // price:  700000
    // memory:  16GB


6. 에러와 에러 객체


Javascript에서 에러는 에러의 name 과 message로 구분된다.

const error = new SyntaxError('문법 에러가 발생했습니다.')

console.log(error.name)  // SyntaxError
console.log(error.message)  // 문법 에러가 발생했습니다.

console.log('End');  // End

  • throw 키워를 이용한 Error 발생

    const error = new SyntaxError('문법 에러가 발생했습니다.')
    
    console.log(error.name)  // SyntaxError
    console.log(error.message)  // 문법 에러가 발생했습니다.
    
    throw error;  //  Uncaught SyntaxError: 문법 에러가 발생했습니다.
    
    // Error가 발생하여 console() 실행되지 않는다.
    console.log('End');

try catch 문

  • 사용법

    try {
      // 코드
    } catch (error) {
      // 에러가 발생했을 떄 동작할 코드
    }

  • 예시

    try {
      console.log('Before Error')
    
      const name = 'adam'
      console.log(name)
    
    	
      name = 'eve'  // 재할당으로인한 에러발생
      console.log(name)  // 위의 에러발생으로 실행되지 않는다.
    
    } catch (error) {
    	// 위의 에러 발생으로 실행되어짐
      console.log('After Error');
      console.error(error)  // 에러 발생
      console.log(error)   // Error객체 프린트
    }
    
    // Before Error
    // adam
    // After Error
    // TypeError: Assignment to constant variable. (ERROR)
    // TypeError: Assignment to constant variable.

Try Catch 문의 활용

Error가 발생하면 프로그램이 중단되지만 try catch문을 이용하여 프로그램의 중단 없이 에러를 다룰 수 있다.

  • 에러 발생으로 인한 프로그램 중단

    function printRank(members) {
      for (let member of members) {
        console.log(member)
      }
    }
    
    const membersA = ['혜정', '지혜', '조민']
    printRank(membersA)
    
    // 객체를 printRank함수에 아규먼트로 실행하여 Error 발생
    const membersB = { name: '하하' }
    printRank(membersB)
    
    // 위의 에러발생으로 실행되지 않음
    const membersC = ['길동', '철민', '조준']
    printRank(membersC)
    
    // 혜정
    // 지혜
    // 조민
    // Uncaught TypeError: members is not iterable

  • try catch 문을 이용하여 프로그램 중단 없이 Error Handling

    function printRank(members) {
      try {
        for (let member of members) {
          console.log(member)
        }
      } catch (error) {
        console.log(error.name)
        console.log(error.message)
      }
    
    }
    
    const membersA = ['혜정', '지혜', '조민']
    printRank(membersA)
    
    const membersB = { name: '하하' }
    printRank(membersB)
    
    const membersC = ['길동', '철민', '조준']
    printRank(membersC)
    
    // 혜정
    // 지혜
    // 조민
    // TypeError
    // members is not iterable
    // 길동
    // 철민
    // 조준

  • try catch 문은 중괄호 {} 안에서만 변수선언이 유효하기 때문에 변수 스코프를 잘 생각해야된다.

    try {
      const title = 'apple' // try 문에서만 title 변수가 유효
      title = 'af'
    } catch (error) {
      console.log(title)  // Uncaught ReferenceError: title is not defined
    }

  • try catch 문은 실행이가능한 코드에서만 작동한다.(SyntaxError는 실행이 되기전 에러가 발생되기 때문에 try catch 문은 작동되지 않는다)
  • 예외처리 (Exception Handling) : 실행 가능한 코드에서 예외처리하는 것

finally 문

finally문은 try문에서 에러가 발생해도 발생하지 않아도 항상 실행되는 구문이다.

try {
  // 실행할 코드
} catch (error) {
  // 에러가 발생했을 때 동작 코드
} finally {
  // 항상 실행할 코드
}

  • finally문에서 에러가 발생했을 시 에러 처리

    try {
      try {
        // 실행할 코드
      } catch (err) {
        // 에러가 발상했을 때 실행할 코드
      } finally {
        // 항상 실행할 코드
      }
    } catch (err) {
      // finall문에서 에러가 발생했을 때 실행할 코드
    }