# 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