1주차
1995 - js 등장
2005 - ajax 등장 -> 요소 별 새로고침, ux 향상
2009 - node.js 등장
2015 - ES6 등장
*객체 지향 프로그래밍 지원
객체 지향 vs 절차 지향
절차 지향 - 순차적으로 처리
객체 지향 - 데이터와 함수를 객체로 묶어서 처리
*동적 타이핑 지원
-> 변수 선언 시 타입을 지정하지 않음, 런타임 시 변수에 할당된 값에 따라 자동으로 지정
변수 이름: 저장된 값의 고유 이름
변수 값: 변수에 저장된 값
변수 할당: 변수에 값을 저장하는 행위
변수 선언: 변수를 상요하기 위해 컴퓨터에 알리는 행위
변수 참조: 변수에 할당된 값을 읽어오는 것
변수를 선언할 수 있는 3가지 방법: var, let, const
1. var -> 재선언이 가능하다
2. let -> 재선언이 불가능하다
3. const -> 재선언, 재할당이 불가능하다
let num1 = 10;
console.log(num1);
console.log(typeof num1);
10, number
1-2 실수
let num2 = 3.14;
console.log(num2);
console.log(typeof num2);
3.14, number
1-3 지수형
let num3 = 2.5e5; // 2.5 * 10^5
console.log(num3);
console.log(typeof num3);
250000, number
1-4 NaN: not a number
let num4 = "hello" / 2;
console.log(num4);
NaN
1-5 infinity (무한대)
let num5 = 1 / 0;
console.log(num5);
console.log(typeof num5);
let num6 = -1 / 0;
console.log(num6);
console.log(typeof num6);
Infinity, number / -Infinity, number
2 문자열
let str = "hello world";
console.log(str);
console.log(typeof str);
hello world, string
2-1 문자열 길이 확인하기
console.log(str.length);
11
2-2 문자열 결합하기
let str1 = "hello, ";
let str2 = "world!";
let result = str1.concat(str2);
console.log(result);
hellow, world!
2-3 문자열 자르기
let str3 = "hello, world!";
console.log(str3.substr(7, 5));
console.log(str3.slice(7, 12));
world / world
2-4 문자열 검색
let str4 = "hello, world!";
console.log(str4.search("world"));
7
2-5 문자열 대체
let str5 = "hello, world!";
let result01 = str5.replace("world", "javascript");
console.log(result01);
hellow, javascript
2-6 문자열 분할
let str6 = "apple, banana, kiwi";
let result02 = str6.split(",");
console.log(result02);
['apple', 'banana', 'kiwi']
let bool1 = true;
let bool2 = false;
console.log(bool1);
console.log(typeof bool1);
console.log(bool2);
console.log(typeof bool2);
true, boolean / false, boolean
let x;
console.log(x);
undefined
let y = null;
console.log(y);
null
let person = {
name: "choi",
age: 20,
test: true,
};
console.log(person);
console.log(typeof person);
{ name: 'choi', age: 20, test: true }, object
let number = [1, 2, 3, 4, 5];
let fruits = ["apple", "banana", "orange"];
*형변환: 암시적 형변환과 명시적 형변환이 있다
let result1 = 1 + "2";
console.log(result1);
console.log(typeof result1);
12, string
let result2 = "1" + true;
console.log(result2);
console.log(typeof result2);
1true, string
=> +하면 문자열
1-2 숫자
let result3 = 1 - "2";
console.log(result3);
console.log(typeof result3);
-1, number
let result4 = "2" * "3";
console.log(result4);
console.log(typeof result4);
=> -하거나 *하면 숫자, /도 숫자로 됨을 확인하였다.
console.log(Boolean(0));
console.log(Boolean(""));
console.log(Boolean(null));
console.log(Boolean(undefined));
console.log(Boolean(NaN));
console.log("===============");
console.log(Boolean("false"));
console.log(Boolean({}));
false, false, false, false, false
===================================
true, true
=> 0은 false, 1은 true / 빈문자열은 false / null, undefined, NaN을 불리언으로 변환 시 false가 됨을 알 수 있다. 문자열 "false"는 빈 문자열이 아니므로 true / 객체는 true를 반환한다. 추가로 빈 배열도 true를 반환하는 것을 확인하였다.
2-2 문자열
let result5 = String(123);
console.log(typeof result5);
console.log(result5);
string, 123 => string으로 형변환하였으므로 타입은 string, 숫자 123을 형변환하여 문자열 123
let result6 = String(true);
console.log(typeof result6);
console.log(result6);
string, true => string으로 형변환하였으므로 타입은 string, true를 형변환하여 문자열 true
2-3 숫자
let result10 = Number("123");
console.log(result10);
console.log(typeof result10);
123, number => 문자열 123을 숫자로 형변환하였다.
*연산자
1. 더하기 연산자
console.log(1 + 1);
console.log(1 + "1");
2, 11 => 문자열과 더할 경우 문자열로 반환
console.log(1 - "2");
console.log(1 - 2);
-1, -1 => 뺄 경우 숫자로 반환
console.log(2 * 3);
console.log("2" * 3);
6, 6 => 곱할 경우 숫자로 반환
console.log(4 / 2);
console.log("4" / 2);
2, 2 => 나눌 경우 숫자로 반환
console.log(5 % 2);
1
let x = 10;
console.log(x);
10
6-2 더하기 등호 연산자
let x = 10;
x += 5;
console.log(x);
15
6-2 빼기 등호 연산자
let x = 10;
x -= 5;
console.log(x);
5
6-3 곱하기 등호 연산자
let x = 10;
x *= 2;
console.log(x);
20
6-4 나누기 등호 연산자
let x = 10;
x /= 2;
console.log(x);
5
*비교 연산자: true 혹은 false를 반환
1. 일치 연산자 ===: 타입까지 일치해야 true를 반환한다
console.log(2 === 2);
console.log("2" === 2);
true, false => 문자열 2와 숫자 2의 타입이 달라 false
==은 타입이 달라도 값만 일치하면 true를 반환한다
console.log(2 !== 2);
console.log("2" !== 2);
false, true => 문자열 2와 숫자 2의 타입이 달라 true
!=은 타입이 달라도 값만 일치하면 false를 반환한다
console.log(2 < 3);
console.log(2 <= 3);
true, true
console.log(true && true);
console.log(true && false);
true, false
4-2 논리합 연산자: 둘 중 하나라도 true일 때 true 반환
console.log(true || true);
console.log(true || false);
true, true
4-3 논리 부정 연산자: 값을 반대로 바꿈
console.log(!true);
let as = true;
console.log(!as);
false, false
let x = 10;
let result = x > 5 ? "크다" : "작다";
console.log("-------");
console.log(result);
console.log("------------");
let y = 20;
console.log(y < 10 ? "작다" : "크다");
크다
크다
=> (조건) ? true : false
console.log(typeof "5");
string
*함수
1. 함수 선언문
function 함수명(매개변수) {
//함수 내부에서 실행할 로직
}
function add(x, y) {
return x + y;
}
=> x, y를 입력 받아 더한 후 내보내는 함수
let add2 = function (x, y) {
return x + y;
};
let add2Result = add(10, 20);
console.log(add2(10, 20));
console.log(add2Result);
30, 30
*화살표 함수
1-1 기본적인 화살표 함수
let arrowFunc01 = (x, y) => {
return x + y;
}
1-2 한줄로
let arrowFunc02 = (x, y) => x+y;
function arrowFunc03(x) {
return x;
}
//화살표 함수로
let arrowFunc03 = (x) => x;
*스코프, 전역변수, 지역변수
let x = 10; //전역변수
function printX() {
console.log(x);
}
console.log(x);
printX();
10, 10 => 전역 변수로 선언하여 함수 내,외부로 참조가 가능하다
function printX() {
let x = 10; // 함수 스코프 내 지역변수
console.log(x);
}
console.log(x); // error
printX();
ReferenceError: x is not defined => 함수 내에서 지역변수로 선언되어 함수 바깥에서 참조가 불가능하다
*조건문
1. if 문
let x = 10;
if (x > 0) {
console.log("x는 양수입니다");
}
x는 양수입니다
let y = "hellow world";
// y의 길이가 5보다 크거나 같으면 길이를 console.log로 출력
if (y.length >= 5) {
console.log(y.length);
}
12
1-2. else if 문
let xa = -3;
if (xa > 0) {
console.log("xa는 양수입니다");
} else {
console.log("xa는 음수입니다");
}
xa는 음수입니다
1-3 if - else if - else 문
let xb = 10;
if (xb < 0) {
console.log("1");
} else if (xb >= 0 && xb < 10) {
console.log("2");
} else {
console.log("3");
}
1-4. switch 문
let fruit = "사과";
switch (fruit) {
case "사과":
console.log("사과입니다");
break;
case "바나나":
console.log("바나나입니다");
break;
case "키위":
console.log("키위입니다");
break;
default:
console.log("아무것도 아닙니다");
break;
}
*조건문의 중첩
let age = 20;
let gender = "여성"
if (age >= 18) {
console.log("성인입니다");
if (gender === "여성") {
console.log("성인 여성입니다");
} else {
console.log("성인 남성입니다");
}
} else {
if (gender === "여성") {
console.log("미성년 여성입니다");
} else {
console.log("미성년 남성입니다");
}
}
성인 여성입니다
*조건부 실행
let x = 10;
//and 조건
x > 0 && console.log("x는 양수입니다");
//or 조건
//삼항 연산자와 단축평가
let y; // undefined
let z = y || 20;
console.log(z);
x는 양수입니다 -> x>0 -> true 이므로 두번째 피연산자 평가
20 -> y는 undefined로 falsy값, || 연산자에 의해 두번째 20을 저장함
if (0) {
console.log("hello");
}
if ("") {
console.log("hello");
}
if (null) {
console.log("hello");
}
if (undefined) {
console.log("hello");
}
if (NaN) {
console.log("hello");
}
if (false) {
console.log("hello");
}
console.log("hello");
hello -> 0, 빈 문자열, null, undefined, NaN, false가 if문 조건에서 false를 반환
*객체: 하나의 변수에 여러개의 값을 넣을 수 있다
let person = {
name: "홍길동",
age: 30,
gender: "남자",
};
1-2 생성자 함수를 이용한 방법
function Person(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
let person1 = new Person("홍길동", 30, "남자");
let person2 = new Person("홍길순", 30, "여자");
console.log(person1);
Person { name: '홍길동', age: 30, gender: '남자' }
this를 통해 새로 생성된 인스턴스 객체를 참조, 인스턴스의 name 속성에 입력 받은 파라미터 값 name 할당.
console.log(person.name);
console.log(person.age);
console.log(person.gender);
홍길동, 30, 남자
let persona = {
name: "홍길동",
age: 30,
gender: "남자",
};
let keys = Object.keys(persona);
console.log("keys =>", keys);
keys => ['name', 'age', 'gender']
키를 배열 형태로 가져온다
3-2 values
let values = Object.values(persona);
console.log("values =>", values);
values => [ '홍길동', 30, '남자' ]
값을 배열 형태로 가져온다
3-3 entries: key와 value를 묶어 2차원 배열 형태로 가져온다
let entries = Object.entries(person);
console.log("entries =>", entries);
entries => [ [ 'name', '홍길동' ], [ 'age', 30 ], [ 'gender', '남자' ] ]
3-4 assign: 객체 복사 (얕은 복사)
let newPerson = {};
Object.assign(newPerson, person, { age: 31 });
console.log("newPerson =>", newPerson);
newPerson => { name: '홍길동', age: 31, gender: '남자' }
Object.assign(붙여넣을 객체, 복사할 객체, 복사할 객체2...)
=> newPerson에 person 객체를 복사하고 {age: 31} 객체를 추가로 복사하였다 이때 기존에 person으로부터 복사했던 age 속성이 대체되어 age: 31이 된다
3-5 객체 비교
let personb = {
name: "홍길동",
age: 30,
gender: "남자",
}; // persona 와 personb가 같음
console.log("answer =>", persona === personb); // false -> 주소가 다르다
console.log(JSON.stringify(persona) === JSON.stringify(personb));
객체는 크기가 커서 별도의 메모리 공간에 저장된다. 이때 주소가 달라 같은 속성과 값을 가지고 있어도 ===로 비교시 false가 출력된다. 따라서 JSON.stringify() 메서드로 객체를 문자열로 바꾸어 비교할 수 있다.
3-6 객체 병합
let personc = {
name: "홍길동",
age: 30,
};
let persond = {
gender: "남자",
};
let perfectMan = { ...personc, ...persond };
console.log(perfectMan);
전개 연산자로 각 객체를 perfectMan 객체에 병합하였다.
*배열
1. 생성
1-1 기본 생성
let fruits = ["사과", "바나나", "오렌지"];
[]안에 배열 요소를 넣는다
1-2 크기 지정
let number = new Array(5);
길이가 5인 배열을 만든다
console.log(fruits[0]);
console.log(fruits[1]);
console.log(fruits[2]);
사과, 바나나, 오렌지 => 각각의 요소 인덱스로 접근할 수 있다
let fruitsa = ["사과", "바나나"];
console.log("1 =>", fruitsa);
fruitsa.push("오렌지");
console.log("2 =>", fruitsa);
1 => [ '사과', '바나나' ]
2 => [ '사과', '바나나', '오렌지' ]
=> 배열의 맨 끝에 새로운 요소를 추가한다
3-2 pop
let fruitsb = ["사과", "바나나"];
console.log("1 =>", fruitsb);
fruitsb.pop();
console.log("2 =>", fruitsb);
1 => [ '사과', '바나나' ]
2 => [ '사과' ]
=> 배열의 맨 끝 요소를 삭제한다
3-3 shift
let fruitsc = ["사과", "바나나", "키위"];
console.log("1 =>", fruitsc);
fruitsc.shift();
console.log("2 =>", fruitsc);
1 => [ '사과', '바나나', '키위' ]
2 => [ '바나나', '키위' ]
=> 배열의 맨 앞 요소를 삭제한다
3-4 unshift
let fruitsd = ["사과", "바나나", "키위"];
fruitsd.unshift("포도");
console.log(fruitsd);
[ '포도', '사과', '바나나', '키위' ] => 배열의 맨 앞에 새로운 요소를 추가한다
3-5 splice
let fruitse = ["사과", "바나나", "키위"];
fruitse.splice(1, 1, "포도");
console.log(fruitse);
[ '사과', '포도', '키위' ] => 1번 인덱스에서 1개의 요소, 즉 바나나를 포도로 바꾸었다
3-6 slice
let fruitsf = ["사과", "바나나", "키위"];
let slice = fruitsf.slice(1, 2);
console.log(slice);
['바나나'] => slice는 기존 배열을 변경하지 않기 때문에 새로운 slice 배열에 할당하였다. 1번 인덱스에서 2번 인덱스 이전까지의 요소를 할당한다.
let numbers = [4, 1, 5, 4, 5];
// 매개변수 자리에 함수를 넣는 것 : 콜백함수
numbers.forEach(function (item) {
console.log("item입니다 =>" + item);
});
item입니다 =>4
item입니다 =>1
item입니다 =>5
item입니다 =>4
item입니다 =>5
=> 배열을 순회하며 각 요소에 대한 콜백함수를 불러온다
let newNumbers = numbers.map(function (item) {
return item * 2;
});
console.log(newNumbers);
[ 8, 2, 10, 8, 10 ] => 원본 배열을 변경하지 않으며 새로운 배열을 반환하므로 새 변수에 할당한다
let numbersFilter = numbers.filter(function (item) {
return item > 3;
});
console.log(numbersFilter);
[4,5,4,5] => 특정 조건에 맞는 요소들을 필터링 하여 새로운 배열을 반환한다
let findNum = numbers.find(function (item) {
return item > 3;
});
console.log(findNum);
4 => filter와 다르게 조건에 충족하는 첫번째 요소만 반환한다. 조건에 맞는 요소가 없으면 undefined를 반환한다.
*반복문
1. for
for (let i = 0; i < 10; i++) {
console.log(i);
}
1,2,3,4,5,6,7,8,9 => 초기값 0부터 9까지 1씩 더하며 반복
let person = {
name: "John",
age: 30,
gender: "male",
};
// person[key]
for (let key in person) {
console.log(key + ": " + person[key]);
}
name: John, age: 30, gender: male => person 객체의 속성을 출력한다
let i = 0;
while (i < 10) {
console.log(i);
i++;
}
1,2,3,4,5,6,7,8,9 => 조건이 참이면 블록 안의 구문을 반복 실행 증감식을 블록 안에 따로 작성해야 한다.
let j = 0;
do {
console.log(j);
j++;
} while (j < 10);
0,1,2,3,4,5,6,7,8,9 => 조건과 상관없이 do 블록 안의 구문을 한 번 실행한 후, 조건을 적용하여 반복한다
for (let i = 0; i < 10; i++) {
if (i === 5) {
break;
}
console.log(i);
}
0,1,2,3,4 => break 시 반복문 종료
out:
for (let i = 0; i < 3; i++) {
console.log("외부:", i);
for (let j = 0; j < 3; j++) {
console.log("내부:", j);
if (j === 1) {
break out;
}
}
}
for (let i = 0; i < 10; i++) {
if (i === 5) {
continue;
}
console.log(i);
}
break와 마찬가지로 반복문을 종료하되, 다음 시행으로 넘어간다
*ES6 문법
1. 구조분해할당
1-1 배열의 경우
let [value1, value2] = [1, "new"];
console.log("1", value1);
console.log("2", value2);
let arr = ["value1", "value2", "value3", "value4"];
let [a, b, c, d = 4] = arr;
console.log(a);
console.log(b);
console.log(c);
console.log(d);
1 1, 2 new, value1,value2,value3,value4
=> 배열 형태로 변수를 선언할 수 있다. 선언 시 초기값을 할당할 수 있으며 초기값이 없이 할당되는 값이 없을 경우 undefined. 변수명으로 각 배열의 요소에 접근할 수 있다
let { name, age } = {
name: "abc",
age: 30,
};
console.log("name ->", name);
console.log("age ->", age);
name -> abc
age -> 30
=> 객체 형태로 변수를 선언할 수 있다
2-1 새로운 이름으로 할당
let user = {
name: "abc",
age: 30,
};
let { name: newName, age: newAge } = user;
console.log("newName ->", newName);
console.log("newAge ->", newAge);
let { name, age, birthday = "today" } = user;
console.log(name);
console.log(age);
console.log(birthday);
newName -> abc
newAge -> 30
abc
30
today
=> 객체의 속성명 대신 새로운 변수명으로 선언할 수 있다 (name: newName)
배열의 구조분해할당과 마찬가지로 초기값을 할당할 수 있다.
*단축 속성명
const obj = { name, age };
const obj1 = {
name: name,
age: age,
};
=> 키와 값이 같으면 값을 생략할 수 있다
*전개 구문
1. 배열
let arr = [1, 2, 3];
console.log(arr);
console.log(...arr);
[1,2,3], 1 2 3 => 배열을 전개한다
let user = {
name: "nbc",
age: 30,
};
let user2 = { ...user, gender: "male" };
console.log(user);
console.log(user2);
{ name: 'nbc', age: 30 }
{ name: 'nbc', age: 30, gender: 'male' }
=> 객체를 전개한다. 객체에 할당할 때 전개하여 다른 객체와 병합할 수 있다
function exFunction(a, b, c, ...args) {
console.log(a, b, c);
console.log(...args);
}
exFunction(1, 2, 3, 4, 5, 6, 7);
1 2 3,
4 5 6 7
=> 나머지 매개변수들을 받을 수 있다 나머지 매개변수는 배열로 받는다. 전개 연산자로 배열로 받은 파라미터를 전개할 수 있다.
*템플릿 리터럴
const test = "안녕하세요";
console.log(`hellow world ${test}`);
// 멀티 라인을 지원한다
console.log(`hello
hi
bye`);
hello
hi
bye
=> ``으로 템플릿 리터럴을 사용하여 변수와 멀티라인을 작성할 수 있다
const sayHello = function () {
console.log("hello");
};
function callFunc(func) {
// 매개변수로 받은 변수가 사실 함수다
func();
}
const sayHello = function () {
console.log("hello");
};
callFunc(sayHello);
hello => function () { console.log("hello") } 를 매개 변수로 받아 함수로 호출한다
function createAdder(num) {
return function (x) {
return x + num;
};
}
const addFive = createAdder(5);
console.log(addFive(10));
15 => addFive는 5를 매개변수로 하는 함수 createAdder를 반환한다 따라서 function (x) { return x + 5; }; 이때 콘솔 로그로 10을 매개 변수로 하는 addFive를 호출한다. 따라서 function (10) { return 10 + 5; }; ==> 15
*일급 객체로서의 함수 2: 함수를 객체 속성으로 할당할 수 있다
const person = {
name: "Jhon",
age: 31,
isMarried: true,
sayHello: function () {
console.log(`hello, my name is ${this.name}` + this.name);
},
};
person.sayHello();
hello, my name is JhonJhon => 함수를 객체 속성으로 할당하여 메서드 정의. 이때 this로 메서드가 속한 객체를 참조하였다.
const person = {
name: "Jhon",
age: 31,
isMarried: true,
sayHello: () => {
console.log(`hello, my name is ${person.name}`);
// 화살표 함수는 this를 바인딩하지 않는다
},
};
person.sayHello();
화살표 함수는 this를 바인딩하지 않는다
const myArr = [
function (a, b) {
return a + b;
},
function (a, b) {
return a - b;
},
];
// 더하기
console.log(myArr[0](1, 3));
// 빼기
console.log(myArr[1](10, 7));
4, 3 => 0번째 인덱스 함수에 1, 3 파라미터를 전달하여 호출하였다
*예제
function mutiplyBy(num) {
return function (x) {
return x * num;
};
}
function add(x, y) {
return x + y;
}
const mutiplyByTwo = mutiplyBy(2);
const mutiplyByThree = mutiplyBy(3);
console.log(mutiplyByTwo(10));
console.log(mutiplyByThree(10));
const result = add(mutiplyByTwo(5), mutiplyByThree(10));
console.log(`Final => ${result}`);
Final => 40
=> mutiplyByTwo에 mutiplyBy 함수에 매개변수 2를 전달하여 반환한 값을 할당한다. 즉 function (x) { return x 2; };
=> mutiplyByThree도 위와 동일. 즉 function (x) { return x 3; };
=> mutiplyByTwo 함수에 매개변수 10을 전달하여 출력한다. 즉 10 2 = 20
=> mutiplyByThree 함수에 매개변수 10을 전달하여 출력한다. 즉 10 3 = 30
=> mutiplyByTwo(5) 반환값과 mutiplyByThree(10) 반환값을 매개변수로 전달하는 add 함수를 호출하여 그 반환값을 result 할당한다 => 40
const myMap = new Map();
myMap.set("key", "value");
myMap.get("key");
const myMap = new Map();
myMap.set("one", 1);
myMap.set("two", 2);
myMap.set("three", 3);
console.log(myMap.keys());
for (const key of myMap.keys()) {
console.log(key);
}
console.log(myMap.values());
for (const value of myMap.values()) {
console.log(value);
}
console.log(myMap.entries());
for (const entry of myMap.entries()) {
console.log(entry);
}
console.log(myMap.size);
console.log(myMap.has("two"));
[Map Iterator] { 'one', 'two', 'three' }
one
two
three
[Map Iterator] { 1, 2, 3 }
1
2
3
[Map Entries] { [ 'one', 1 ], [ 'two', 2 ], [ 'three', 3 ] }
[ 'one', 1 ][ 'two', 2 ]
[ 'three', 3 ]
3
true
=> key() 메서드로 myMap의 키를 Iterator로 반환하였다. 이를 for ...of로 반복하여 키를 출력하였다. value() 메서드로 myMap의 값을 Iterator로 반환하였다. ..이하생략 entries() 메서드로 myMap의 키-값을 배열 형태의 Iterator로 반환하였다 ..이하생략
=> size 프로퍼티로 Map에 저장된 키-값의 개수를 구할 수 있다
=> has("키") 메서드로 해당 키가 있는지 반환한다. => two 키가 있으므로 true
const mySet = new Set();
mySet.add("value1");
mySet.add("value2");
mySet.add("value3");
mySet.add("value5");
mySet.add("value8");
console.log(mySet.size);
console.log(mySet.has("value1"));
console.log(mySet.has("value2"));
console.log(mySet.has("value3"));
// Iterator
for (const value of mySet.values()) {
console.log(value);
}
5
true
true
true
value1
value2
value3
value5
value8
=> size 프로퍼티로 저장된 값의 개수를 알 수 있다. 이때 저장된 5개의 값들이 중복되지 않으므로 5
=> has("값") 메서드로 해당 값이 있는지 반환한다.
=> mySet.values()로 값을 Iterator로 반환하여 for ...of로 순회