[필기정리]Day52 - let, const, symbol 등

Web/javascript

2020. 9. 4. 13:03

# var vs let : 변수 선언

ex)

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="variable2.js"></script>
</head>
<body>
</body>
</html>
'use strict';           // ES5에서 추가

console.log(age);
age = 4;
console.log(age);
var age; // Hoisting되나 유지보수 어려워짐
 
// name = 4;
// let name; // 에크마스크립트 6에서 만들어짐, let으로 변수 선언 가능, 선언 전 초기화 시 에러 발생

{
    age = 4;
    var age; // 지역변수, 전역변수 개념이 없어 괄호 안에 쓰더라도 모두 적용된다.
}

console.log(age); // var로 선언하여 값이 출력된다.

let globalName = 'global name';
{
    let name = 'ellie'; // 지역변수
    console.log(name);
    name = 'hello';
    console.log(name);
    console.log(globalName);
}
console.log(name); // let으로 선언한 지역변수이므로 출력되지 않는다.
console.log(globalName);

co0nsole.clear(); // 위에서 한 선언이 모두 초기화된다.

const daysInWeek = 7; // constant, 상수 선언, 대문자로 선언하여 가독성을 높이는 것이 좋다.
const maxNumber = 5;

 

- 상수를 사용하는 이유

① security : 보안
② thread safety : 쓰레드의 안전성
③ reduce human mistakes : 사람의 실수를 줄이기 위함

    등의 이유로 상수를 많이 쓸수록 좋다.

 

# Variable types(변수 타입)
- primitive, single item: number, string, boolean, null, undefined, symbol(에크마6부터 추가)

let a = 12;
let b = 1.2;

const count = 17;   // integer 
const size = 17.1;      // decimal number
console.log(`value: ${count}, type: ${typeof count}`); // ${count} 변수값 자체를 그대로 출력 가능
console.log(`value: ${size}, type: ${typeof size}`);

console.clear();

// number - special numeric values: infinity, -infinity, NaN
const infinity = 1 / 0;
const negativeInfinity = -1 / 0; 
const nAn = 'not a number' / 2; 
console.log(infinity);
console.log(negativeInfinity);
console.log(nAn);      // NaN(Not a Number)로 출력

console.clear();

// 아직 지원하지 않는 브라우저가 많다.
const bigInt = 1234567890123456789012345678901234567890n;        // over (-2**53 ~ 2**53) // 어마어마하게 큰 숫자 사용 시 ~+n을 붙이면 사용 가능하나 지원하지 않는 브라우저가 많아 사용을 지양하는 것이 좋다.
console.log(`value: ${bigInt}, type: ${typeof bigInt}`);

// string
const char = 'c';
const brendan = 'brendan';
const greeting = 'hello ' + brendan; 
console.log(`value: ${greeting}, type: ${typeof greeting}`);
const helloBob = `hi ${brendan}!`;
console.log(`value: ${helloBob}, type: ${typeof helloBob}`); // 결과 : hi brendan 변수가 가진 값을 그대로 출력
console.log('value: ' + helloBob + ' type: ' + typeof helloBob);  

// boolean
// false: 0, null, undefined, NaN, ''(띄어쓰기 없는 것)
// true any other value

const canRead = true;
const test = 3 < 1;     // false
console.log(`value: ${canRead}, type: ${typeof canRead}`);
console.log(`value: ${test}, type: ${typeof test}`);

// null
let nothing = null;
console.log(`value: ${nothing}, type: ${typeof nothing}`);

// undefined
let x;      // let x = undefined;라는 값으로 초기화 되어 있음
console.log(`value: ${x}, type: ${typeof x}`); 

// symbol , create unique identifiers for objects 유니크한 값을 줄 필요가 있는 경우 사용
const symbol1 = Symbol('id');
const symbol2 = Symbol('id');
console.log(symbol1 === symbol2);       // false - 서로 다른 유니크한 값이기 때문

const gSymbol1 = Symbol.for('id');
const gSymbol2 = Symbol.for('id');
console.log(gSymbol1 === gSymbol2);     // true
// console.log(`value: ${symbol1}, type: ${typeof symbol1}`);           // Error
console.log(`value: ${symbol1.description}, type: ${typeof symbol1}`);

- Symbol() Symbol.for() 차이점

  Symbol() 은 고유한 심볼을 반환한다.

  하지만 Symbol.for() 는 전역으로 존재하는 global symbol table 의 목록을 참조한다.

  때문에 Symbol.for(token string) 으로 정의할 때,

  token string 으로 정의 된 심볼이 있다면 해당 심볼을 반환하게 된다.

 

- object , real-life object, data structure

const ellie = {name: 'ellie', age:20 }; // 오브젝트 생성
ellie.age = 21;

 

# Dynamic typing: dynamically typed language // 자바스크립트는 동적으로 데이터 타입이 정해짐

let text = 'hello'; // 자바 =  String text = "hello"
console.log(text.charAt(0));        // h - 0번째 출력한 것
console.log(`value: ${text}, type: ${typeof text}`);
text = 1; // 자바면 값을 넣을 수 없음. 자료형이 동적으로 결정되므로 가능한 것
console.log(`value: ${text}, type: ${typeof text}`);
text = '7' + 5;
console.log(`value: ${text}, type: ${typeof text}`);
text = '8' / '2';
console.log(`value: ${text}, type: ${typeof text}`);
// console.log(text.charAt(0));     // Error - 텍스트에 들어가 있는 자료형이 number이므로 에러 발생

 

# function

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="function2.js"></script>
</head>
<body>
</body>
</html>
function printHello(){
    console.log('Hello');
}
printHello();

function log(message){
    console.log(message);
}
log('Hello@'); // 결과 : Hello@
log(1234); 

 

# Parameters
premitive parameters: passwd by value
object parameters: passed by reference

function changeName(obj){
    obj.name = 'coder';
}
console.clear();

const ellie = {name: 'ellie'};
changeName(ellie);
console.log(ellie);

 

# Default parameters (added in ES6) : 디폴트 - 파라미터에 어떤 값을 주는 것을 의미

 function showMessage(message, from){  // 매개변수 2개이나
     console.log(`${message} by ${from}`); // 하나만 넘겼기 때문에 결과 : Hi! by undifined가 된다
 }
 showMessage('Hi!');
 function showMessage(message, from){ // (Hi, undifined)로 초기화
     if(from === undefined){ //from이 undifined이므로
         from = 'unknown'; // from에 unknown 값을 넣어주어 변경된다.
     }
     console.log(`${message} by ${from}`);
 }
 showMessage('Hi!');
function showMessage(message, from = 'unknown'){ // 에크마스크립트6 이후부터 디폴트값을 줄 수 있다
    console.log(`${message} by ${from}`); // 결과 : Hi by unknown
}
showMessage('Hi!');


 디폴트 값을 줄 때 규칙이 있다.
 매개변수가 여러 개 있으면 기본값은 오른쪽 값부터 초기화 해줘야 한다.

 

# Rest parameters (added in ES6)

function printAll(...args){ // 가변 - 매개변수의 갯수가 정해져 있지 않다. 매개변수 가변 가능
    for(let i = 0; i < args.length; i++){
        console.log(args[i]);
    }

    for(const arg of args){ // 위와 동일 내용, 다른 표현이다.
        console.log(arg);
    }

    args.forEach( (arg) => console.log(arg));
}

printAll('dream', 'coding', 'ellie');

 

# Local scope

let globalMessage = 'global';   // global variable, 전역변수
function printMessage(){
    let message = 'hello';
    console.log(message);       // local variable, 지역변수
    console.log(globalMessage);
    function printAnother(){
        console.log(message);
        let childMessage = 'hello';
    }
    // console.log(childMessage);       // Error - 지역변수이기 때문
    // return undefined;       // return 이 없는 함수는 이 것이 생략 되어있는 것이다. 동일 내용임
}

printMessage(); 

// console.log(message);        // Error - 지역변수이기 때문

 

# Return a value

function sum(a, b){
    return a + b;
}

const result = sum(1, 2);       // 3
console.log(`sum: ${sum(1, 2)}`); //결과 : sum3

 

# Early return, early exit 

ex) 안 좋은 예시

function upgradeUser(user){ 
     if(user.point > 10){
         // long upgrade logic ... // 굉장히 긴 로직
     }
 }

 

ex) 좋은 예시

function upgradeUser(user){
    if(user.point <= 10){
        return; // 필요없는 내용 앞에 리턴을 시켜 빠르게 빠져나갈 수 있게 해주는 것이 좋은 프로그래밍 습관이다.
    }
    // long upgrade logic ...
}

 

// Tip : First-class function(일급 함수의 조건) 
          functions are treated like any other variable(함수는 다른 변수처럼 취급된다) 
① can be assigned as a value to variable :  변수에 대한 값으로 지정될 수 있다.
② can be passed as an argument to other functions : 다른 함수에 인수로 넘길 수 있다.
③ can be returned by another function : 다른 함수로 리턴할 수 있다.

# Function expression(함수 표현식) 
- a function declarartion can be called earlier than it is defined. (hoisted)

  : function declarartion는 호이스팅 가능하기 때문에 더 빨리 호출이 가능하다.
- a function expression is created when the execution reaches it.

  : function expression은 호이스팅이 불가하기 때문에 실행 시 생성된다.

 

 print();             // Error;
const print = function print2() {      // named function
    console.log('print');
};
 const print = function() {      // anonymoius function 이름 없는 함수
     console.log('print');
 };
print();
const printAgain = print;
printAgain();
const sumAgain = sum;
console.log(sumAgain(1, 3)); // 결과 : 4

 

# Callback function using function expression

- 콜백(Callback) 함수(function) : 특정함수에 매개변수로 전달된 함수를 의미한다.
  이렇게 콜백함수를 전달 받은 함수 내에서 콜백함수가 실행이 된다.

  상황에 따라 어떤 작업이 끝났다는 것을 사용자에게 알려주거나,
  코드 내부에서 콜백함수를 받았을 경우에만 처리하는 로직을 짤 수 있다.

  예를 들어 DB에서 데이터를 다 가져오지도 않았는데 출력을 해버리면 결과 값이 나오지 않는다.
  하지만 콜백함수로 처리결과를 받은 후 출력을 한다면 데이터를 다 가져오고 출력을 하기 때문에 
  정상적인 결과 값이 출력되는 것이다.

 

ex) 콜백함수 예시

function randomQuiz(answer, printYes, printNO) {
    if(answer === 'love you'){
        printYes();
    } else {
        printNO();
    }
}
// anonymous function
const printYes = function(){
    console.log('yes!');
};

// named function
const printNo = function print() {
    console.log('no!');
};
randomQuiz('wrong', printYes, printNo);
randomQuiz('love you', printYes, printNo);

 

# Arrow function

 const simplePrint = function() {
     console.log('simplePrint!');
 };

const simplePrint = () => console.log('simplePrint!'); // 한 줄 시 return 키워드 생략 가능
const add = (a, b) => a + b;

 const add = function(a, b){
     return a + b;
 };

const simpleMultiply =  (a, b) => {
    // do something more
    return a * b;       // arrow function 에서 블록(여러줄)을 쓸려면 return 키워드를 생략하면 안된다.
};

 

# IIFE: Immediately Invoked Function Expression

(function hello(){  // 즉시실행함수
    console.log('IIFE'); 
})();


// function hello(){ // 위와 같은 내용
//     console.log('IIFE');
// }

// hello();

 

ex)

function calculate(command, a, b){ // 문자열, a, b
    switch(command){
        case 'add':
            return a + b;
        case 'substract':
            return a - b;
        case 'divide':
            return a / b;
        case 'multiply':
            return a * b;
        case 'remainder':
            return a % b;
        default:
            throw Error('unknown command');
    }
}
console.log(calculate('add', 2, 3)); // 결과 : 5

 

Q. 행맨 게임을 만드시오.

A.

<!DOCTYPE html>
<html>
<head>
    <title>행맨!</title>
</head>
<body>
    <h1>행맨!</h1>
    <script>
    // 단어 배열을 만든다.
    var words = [
      "javascript",
      "monkey",
      "amazing",
      "pancake"
    ];

    // 임의의 단어를 고른다.
    var word = words[Math.floor(Math.random() * words.length)];
    word = word.split(""); // 배열로 만들어짐

    // 정답 배열을 설정한다.
    var answerArray = [];
    for (var i = 0; i < word.length; i++) {
      answerArray[i] = "_"; // 각각의 단어 대신 단어 스펠링 갯수만큼 만듬
    }
    strAnswerArray = answerArray.toString(); // 문자열로 만들어줌

    // 게임 메인 반복문
    while ( strAnswerArray.indexOf("_") != -1 ) { // 맞출 때마다 _가 사라지기 때문에 _가 전부 사라질 때까지 반복하는 것
      // 플레이어에게 현재 상태를 알려준다.
      alert(answerArray.join(" "));

      // 플레이어가 입력한 글자를 저장한다.
      var guess = prompt("글자를 입력하세요. 취소를 누르면 게임을 멈춥니다.");
      if (guess === null) {
        // 게임 메인 반복문을 빠져나간다. (취소를 누른 경우)
        break;
      } else if (guess.length !== 1) { // 두 글자 이상 입력한 경우
        alert("한 글자만 입력해주세요.");
      } else {
        // 입력한 글자를 사용해 게임 상태 업데이트한다 (제대로 입력한 경우)
        for (var j = 0; j < word.length; j++) {
          if (word[j] === guess) {
            answerArray[j] = guess;
          }
        }
      }
       strAnswerArray = answerArray.toString();    
    // 게임 메인 반복문 끝
    }

    // 정답을 보여주고 플레이어를 축하한다
    alert(answerArray.join(" "));
    alert("잘하셨어요! 정답은 " + word + "입니다.");
    </script>
</body>
</html>

 

[참고자료] 드림코딩 by 엘리 유튜브

https://www.youtube.com/watch?v=e_lU39U-5bQ&list=PLv2d7VI9OotQ1F92Jp9Ce7ovHEsuRQB3Y&index=23&t=0s

728x90