1. JavaScript란?
- 웹페이지를 동적, 프로그래밍적으로 제어하기 위해 고안된 언어
- 브라우저에서 웹서버까지 확장(Node.js)
- ECMAScript라는 자바스크립트 표준안을 따름
2. 자료형(Data Type)
- 자바스크립트는 동적 언어로 변수의 타입을 미리 선언할 필요가 없음
let a = 42;
let b = "bar";
let c = true;
- 기본 자료형 / 원시 타입
1) Boolean
2) Null
3) Undefined
4) Number
5) String
6) Symbol
👉 ES6에서 새로 추가됨, 변경이 불가능한 원시 타입
👉 주로 충돌 위험이 없는 유일한 객체의 속성 키를 만들기 위해 사용
- 객체 타입
1) Object
3. 연산자
- 할당연산자: 오른쪽 피연산자의 값을 왼쪽 피연산자에 할당
종류: =
- 비교연산자: 피연산자들을 비교하고 비교에 따라 논리값을 반환
종류: ==, !==, ===, >, >=, <, <=
- 산술연산자: 피연산자로 숫자로 갖고 하나의 숫자 값을 반환
종류: +, -, *, /, %, --, ++
- 논리연산자: bool값과 사용될때 bool값 반환, (&&,||)는 실제 명시된 피연산자들 중 하나를 반환
종류: &&, ||, !
- 비트연산자: 숫자 1과 0로만 구성된 값인 이진수로 연산 가능
1) 비트 논리 연산자
👉 AND(곱) a&b
👉 NOT(반대값) ~a
👉 OR(하나라도 1이면 1반환) a|b
👉 XOR(배타적으로 1인경우 1반환) a^b
2) 비트 이동 연산자:
👉 a << b
👉 a >> b
👉 a >>> b
※ 비트연산자 개념정리
4. for/while 반복문
for(i=0;i<10;i++){
console.log(i);}
for in
👉 객체에서 문자열로 키가 지정된 모든 속성에 대해 반복
for(const item in store){
console.log(store[item]);}
while(i<10){
console.log(i);
--i;
}
5. 함수🍊
함수 표현식과 함수 선언문
1) 함수 표현식: 함수를 정의하면서 동시에 변수에 함수 리터럴 할당
2) 함수 선언문: 함수 이름으로 선언
const printName = function(name){
console.log(name);
};
function Print(name){
console.log(name);
};
printName('Max');
Print('Max');
예외처리
1) 에러 발생을 대비하기 위한 예외 처리
2) throw문과 try-catch-finally문
👉 throw문 : 사용자가 고의로 예외를 정의
👉 try문 : 실행될 선언들
👉 catch문 : try문에서 예외가 발생했을때 실행될 선언들
👉 finally문: try문 선언이 완료된 이후 실행될 선언들
function checkNumber(val){
if(typeof val !== 'number')
throw '유효하지 않은 값';
console.log('숫자형 값으로 확인');
}
try{
checkNumber(100);
checkNumber('Wrong Type');
} catch (e){
console.log(e);
} finally {
console.log('완료');
}
arguments 객체
👉 함수에 전달되는 인자로 배열 형태의 객체
👉 length 속성 외에 배열의 어떤 속성, 메소드를 가지고 있지 않음
function sum(){
const newArr = Array.prototype.slice.call(arguments);
console.log(arguments, newArr);
}
sum(1,2,3);
function sum(...args){
console.log(args);
}
sum(1,2,3);
스코프 이해하기
1) 스코프(scope): 유효 범위로써 변수와 매개변수가 어띠가지 유효한지 나타냄
2) 자바스크립트는 기본적으로 전역과 함수 단위로 스코프를 생성
3) 자바스크립트는 렉시컬 스코프이므로 코드를 작성한 시점에서 상위 스코프 결정
let a = 1;
function printA(){
console.log(a);
}
function printB(){
let a = 2;
printA(a);
}
printA();
printB();
함수 호이스팅 이해하기
1) 호이스팅: 함수를 선언하기 전에 호출이 가능한 동작
2) 자바스크립트는 초기화가 아닌 선언만 끌어올림
hello();
function hello(){
console.log('안녕');
};
bye();
let bye = function(){
console.log('bye');
};
6. 배열
- 대괄호와 괄호 사이의 요소(들)로 구성
- 여러개의 데이터를 하나의 변수에 저장
- 연관된 데이터를 모아서 관리하기 위해 사용되는 데이터 타입
1) 추가: push(), unshift(), concat() <= 복수의 원소 추가
2) 제거: pop(), shift()
3) 정렬: sort(), reverse()
4) splice(): splice(인덱스, 제거할 개수, 인덱스~인덱스+제거할개수 사이에 추가할 원소)
- 인덱스: 배열 안에 위치한 요소의 좌표
7. 객체🍓
- 값들을 그룹으로 묶은 데이터 모음
- 표현식으로 {} 사용;
- 키(key)와 값(value)를 한쌍으로 정의하며 이를 속성이라 부름
- this 키워드를 통해 속성 접근
const myObj = {
group: {
minsoo:26,
gildong:20
},
show1: () => {
console.log(this.group);
for(person in myObj.group){
console.log(person+':'+myObj.group[person]);
}
},
show2: function() {
console.log(this.group);
for(person in myObj.group){
console.log(person+':'+myObj.group[person]);
}
}
};
- 화살표 함수에서 this 주의사항
1) 화살표 함수는 자신의 this가 없다
2) 렉시컬 범위의 this가 사용되고 없을 경우 바깥 범위에서 this를 찾는 것으로 검색을 끝낸다
- 속성 접근/추가/삭제
const family = {
members:{}
};
const members = family.members;
members['nephew'] = {age:5,name:'lyn'};
members.niece = {age:3,name:'hyun'};
delete members['nephew'];
delete members.niece;
단축 속성명: 변수명으로 속성의 키와 값을 한번에 정의
const city = 'Seoul',
member = {},
addFamily = function(role,age,name){
this.member[role] = {age, name};
}
const family = {city, member, addFamily};
family.addFamily('father',30,'Max');
const obj = {
a:1,
b:2
}
const {a, b} = obj;
const arr = [1,2,3];
const [e,f,g] = arr;
8. var / let / const 변수 선언🍅
- var : 함수 단위의 유효범위를 가짐
- let : 블록 단위의 유효범위를 가짐
- const : 블록 단위의 유효범위를 가지고 선언시 값을 할당해야 하고 이후에 재할당을 할 수 없음
if(true){
var v = 'function-scope';
let l = 'block-scope';
}
console.log(v);
console.log(l);
- let 은 블록 시작부터 선언이 이루어진 라인까지 일시적으로 접근을 막음
- const 에 객체를 할당하면 불변 객체가 되지 않고 속성에 다른 값을 할당할 수 있음
let l = '바깥';
if(true){
console.log(l);
let l = "안";
}
const user = {
name: 'Jeong',
age: 26
};
console.log(user.name, user.age);
user.name = 'Jay';
user.age = 20;
console.log(user.name, user.age);
9. 스코프 체인🍌
- 스코프체인 : 유효범위(스코프)가 연결되어 있음을 나타냄
- 실행 컨텍스트
1) 코드가 실행되기 위해 필요한 정보를 가짐
2) 실행 가능한 코드가 실행될 때 생성
3) 렉시컬 환경을 가짐
4) 전역컨텍스트 👉 전역코드 평가 👉 실행컨텍스트 👉 코드 실행/종료 후 제거
- 렉시컬 환경 : 환경 레코드와 외부 렉시컬 환경으로 구성
- 환경 레코드: 식별자와 가르키는 값이 키(key)와 값(value)로 기록
- 외부 렉시컬 환경: 자신의 실행 환경을 감싸는 외부 실행 환경에 대한 참조
실행 컨텍스트 = {
렉시컬 환경: {
환경 레코드: {},
외부 렉시컬 환경: 참조
}
}
let student = 'Jeong';
function printName(){
let teacher = 'Kim';
function printBoth(){
console.log(student);
console.log(teacher);
}
printBoth();
console.log('print finished');
}
printName();
console.log('finished');
10. 클로저🍉
- 클로저 : 함수가 정의될 때의 렉시컬 환경을 기억하는 함수
function Count(){
let count = 0;
return {
increase: function(){
++count;
},
get: function(){
return count;
}
};
};
const counter1 = Count();
const counter2 = Count();
counter1.increase();
counter1.increase();
counter2.increase();
console.log(counter1.get());
console.log(counter2.get());
- counter1과 counter2는 다른 렉시컬 환경에서 환경 레코드에서 count에 접근
- increase와 get 함수는 실행 컨텍스트가 각각 생성되고 각각의 실행 컨텍스트 렉시컬 환경을 기억하는 클로저
11. 화살표 함수🍇
- 매개변수가 하나일 경우 인자를 정의할 때 괄호 생략 가능
- 매개변수가 없거나 둘 이상일 경우 괄호 작성
- 코드 블록을 지정하지 않고 한 문장으로 작성 시 return 문을 사용하지 않아도 결과값 반환
- 코드 블록을 지정했을 경우 return 문을 작성해야 결과값을 반환하고 없을 시 undefined 반환
const sum1 = a => a + a;
const sum2 = (a,b) => a + b;
const sum3 = (a,b) => {
return a + b;
}
console.log(sum1(2));
console.log(sum2(1,2));
console.log(sum3(1,2));
12. 객체지향 프로그래밍🍋
- 객체지향 프로그래밍 : 프로그램을 객체들로 구성하고 객체들 간에 서로 상호작용하도록 작성하는 방법
- 객체지향에서 "객체" : 식별 가능한 구체적인 사물 또는 추상적인 개념
- 객체는 특징적인 행동(메소드)과 변경 가능한 상태를 가짐
- 함수 값으로 가지는 속성을 메소드, 그 외는 변경 가능한 상태
const teacher = {
name: 'Jeong',
age: 30,
teach: function(student){
student.gainKnowledge();
}
}
const student = {
name: 'Kim',
age: 10,
knowledge: 0,
gainKnowledge: function(){
++this.knowledge;
}
}
teacher.teach(student);
console.log(student.knowledge);
- 메소드 teach를 통해 객체 teacher, student 간에 메시지 전달
const gainKnowledgeProto = {
gainKnowledge: function(){
++this.knowledge;
}
}
const student = {
name: 'Jeong',
knowledge: 10,
__proto__: gainKnowledgeProto
}
student.gainKnowledge();
console.log(student.knowledge);
- 자바스크립트는 프로토타입 기반으로 객체지향 프로그래밍을 지원
- 기존 객체를 복사하여 새로운 새로운 객체를 생성
- 프로토타입으로 객체에 공통 사항을 적용할 수 있음
- __proto__ 속성으로 원형 객체를 정의
- __proto__ 속성에 객체를 할당하지 않으면 기본적으로 Object.prototype 객체가 연결
13. 생성자 함수🍆
- 객체를 생성하기 위한 방법으로 함수 사용
- new 키워드를 사용하여 함수를 호출하면 return 문이 없어도 새로운 객체 반환
- 생성자 함수 : 객체를 생성하는 역할을 하는 함수
- 함수명을 대문자로 시작하는 관례를 가짐
function Teacher(name,age,subject){
this.name = name;
this.age = age;
this.subject = subject;
this.teach = function(student){
console.log(`${student}에게 ${this.subject}를 가르쳤습니다.`);
}
}
const Jeong = new Teacher('Jeong',30,'JavaScript');
Jeong.teach('Kim');
- 객체에 타입이 적용되면 해당 객체는 그 타입의 인스턴스라 부름
- 위 코드에서 Jeong 객체는 Teacher 생성자 함수의 인스턴스
14. 프로토타입 기반 상속🥭
- 모든 함수는 prototype 속성으로 프로토타입 객체를 가짐
- 모든 인스턴스는 해당 생성자 함수의 프로토타입 객체의 속성과 메소드를 상속
- 모든 객체는 __proto__ 속성을 가지고 __proto__ 속성은 해당 객체를 생성한 생성자 함수의 프로토타입 객체를 가르킴
function Storage(){
this.dataStore = {};
}
Storage.prototype.put = function(key, data){
this.dataStore[key] = data;
}
Storage.prototype.get = function(key){
return this.dataStore[key];
}
const productStorage = new Storage();
productStorage.put('Iphone',{price:'$900', color:'black'});
console.log(productStorage);
function RemovableStorage(){
Storage.call(this);
}
RemovableStorage.prototype = Object.create(Storage.prototype);
RemovableStorage.prototype.removeAll = function(){
this.dataStore = {};
}
const productStorage2 = new RemovableStorage();
productStorage2.put('Iphone',{price:'$900', color:'white'});
console.log(productStorage2);
productStorage2.removeAll();
console.log(productStorage2);
- Storage 생성자 함수에 내부 속성 dataStore, 메소드 put, get을 추가
- Storage 타입의 인스턴스 productStorage는 Storage 생성자 함수에 정의된 메소드, 속성을 상속
- Storage.call(this) : Storage 생성자 함수에서 정의된 속성(dataStore)을 추가
- Object.create(Storage.prototype) : Storage 생성자 함수의 프로토타입 객체가 RemovableStorage 함수의 프로토타입 객체의 __proto__에 할당
- Storage와 RemovableStorage의 프로토타입이 상속관계를 가짐
- RemovableStorage 생성자 함수에 의해 만들어진 인스턴스는 내부에 없는 메소드를 RemovableStorage 생성자 함수의 프로토타입에서 먼저 찾고 없으면
Storage 생성자 함수의 프로토타입에서 찾음
- 프로토타입 객체가 서로 연결되어 있음을 프로토타입 체인이라 함
15. 클래스🍐
클래스
- 별도 타입의 객체를 생성하는 설계 도면
- 클래스를 통해 객체가 가져야 할 상태와 행위들을 속성와 메소드로 정의
- 해당 클래스에서 만들어진 객체들은 클래스에 정의된 특성에 따라 행위를 함
- 클래스에 의해 만들어진 객체들을 해당 클래스의 인스턴스라고 함
class Cart {
constructor() {
this.store = {};
}
addProduct(product<) {
this.store[product.id] = product;
}
getProduct(id) {
return this.store[id];
}
}
const cart1 = new Cart();
cart1.addProduct({id:0,name:'노트북'});
console.log(cart1);
const noteBook = cart1.getProduct(0);
console.log(noteBook);
- constructor로 생성자 함수 정의
- new 키워드를 사용하여 객체를 생성
클래스 상속
class Parent {
constructor(mom,dad){
this.mom = mom;
this.dad = dad;
}
showFamily(){
console.log('We are Family');
}
}
class Children extends Parent{
constructor(mom,dad,son){
super(mom,dad);
this.son = son;
}
showAll(){
this.showFamily();
console.log(`${this.mom} ${this.dad} ${this.son}`);
}
}
const myFamily = new Children('Amy','John','Tom');
myFamily.showAll();
- extends 키워드를 사용해 클래스 상속
- super 키워드를 사용해 생성자 함수에 상속한 부모 클래스의 생성자 함수 호출
- 상속을 통해 부모 클래스에 정의된 메소드를 사용할 수 있음
클래스 정적 메소드와 속성
class Product {
static build(name,price){
const id = Math.floor(Math.random() * 1000);
return new Product(id, name, price);
}
static getTaxPrice(product){
return (product.price * 0.1) + product.price;
}
constructor(id, name, price){
this.id = id;
this.name = name;
this.price = price;
}
}
class DeposableProduct extends Product {
depose(){
this.depose = true;
}
}
const gum = Product.build('껌',1000);
console.log(gum);
const cloth = new DeposableProduct(1,'옷',5000);
const clothTax = DeposableProduct.getTaxPrice(cloth);
console.log(clothTax);
- 정적 메소드는 클래스를 통해 직접 호출하는 메소드
- 클래스로 상속하게 되면 정적 메소드 또한 상속
class ProductCode{
static get Default_Code(){
return "SeungOk's ";
}
constructor(id){
this.id = id;
this.code = ProductCode.Default_Code + id;
}
}
ProductCode.getNumber = '1234';
const firstProduct = new ProductCode('001');
console.log(ProductCode.Default_Code);
console.log(firstProduct.code);
console.log(ProductCode.getNumber);
console.log(firstProduct.number);
- 정적 속성 또한 static 키워드와 get 키워드를 통해 정의
- 클래스 몸통 블록 밖에서도 정의할 수 있음
- 가독성을 위해 몸통 블록 안에서 정의하는 것이 좋음
16. this🌰
this.valueA = 'a'
console.log(valueA);
valueB = 'b';
console.log(this.valueB);
function checkThis(){
console.log(this);
}
function checkThis2(){
'use strict'
console.log(this);
}
- 브라우저 환경에서 this를 전역으로 사용하면 전역 객체인 Window 객체를 가르킴
- 엄격한 모드에서 실행하면 this는 undefined가 됨
function Product(name,price){
this.name = name;
this.price = price;
}
const product1 = Product('패딩',10000);
console.log(window.name, window.price);
- 생성자 함수를 new 키워드 없이 호출하면 this는 window 객체를 가르킴
- new 키워드와 함께 호출해야 this는 해당 객체를 가르킴
const product2 = {
name: '바지',
price: 5000,
getVAT: function(){
return this.price / 10;
}
};
const calVAT1 = product2.getVAT();
console.log(calVAT1);
const calVAT2 = product2.getVAT;
const VAT2 = calVAT2();
console.log(VAT2);
const calVAT3 = calVAT2.bind(product2);
const VAT3 = calVAT3();
console.log(VAT3)
- 메소드를 다른 변수에 저장하고 그 변수를 통해 호출하면 일반적인 함수가 호출되어 this는 전역객체를 가르침
- 그러므로 이전 코드의 window.price를 기준으로 계산됨
- 호출되는 시점에 점(.)연산자와 객체가 함께 주어져야 this가 해당 객체가 됨
- bind 메소드를 통해 전달한 인자값으로 this를 변경할 수 있음
const counter1 = {
count: 0,
findThis: function(){
const me = this;
console<.log(me);
function innerBlock(){
me.count += 1;
console.log(this.count);
}
innerBlock();
}
}
counter1.findThis();
const counter2 = {
count: 0,
findThis: function(){
const me = this;
const innerBlock = () => {
me.count += 1;
console.log(this.count);
}
innerBlock();
}
}
counter2.findThis();
- 메소드 안에서 중첩함수로 작정되면 this는 전역객체를 가르킴
- 화살표 함수에서 this는 부모 환경의 this를 가리킴
- 화살표 함수는 작성하는 시점의 부모 환경에서의 this로 정의되고 변경이 불가능
17. 모듈🥦
모듈 이해하기
- 파일이나 코드의 묶음 단위
- 애플리케이션의 구성요소
- 모듈 단위로 코드를 재사용
- 작은 기능 단위로 분리하여 관리
export function hello(name){
console.log(`${name}! Hello!`);
}
import {hello} from './hello.js';
hello('SeungOk');
- export 키워드를 통해 모듈 내 특정 코드를 외부에서 사용
- import 키워드를 통해 export한 코드들을 가져옴
- export와 import를 통해 모듈은 의존 관계를 형성
- 여러 모듈들이 의존 관계를 맺어 의존 그래프를 형성
- 위코드를 실행하면 SyntaxError: Cannot use import statement outside a module 에러 발생
- package.json에서 "type" : "module"로 설정하면 에러 해결
- 모듈로 정의된 파일들을 실행하는 방법
1) 런타임 로딩
👉 의존 관계가 형성된 모듈들을 애플리케이션 구동 시점에 HTTP 요청으로 불러오고 실행
👉 system.js나 require.js같은 모듈 로더 필요
2) 번들링
👉 의존 관계가 형성된 모듈들을 하나의 파일로 묶음
👉 애플리케이션이 구동할 때 묶여진 파일을 로드
👉 개발시점에서 이루어지고 브라우저 환경이 아닌 node.js 환경에서 이루어짐
👉 대표적인 모듈 번들러로 웹팩이 있음
모듈 기본값
export default class Hello{
constructor(greeting){
this.greeting = greeting;
}
hi(name){
console.log(`${name} ${this.greeting}`);
}
}
import Hello from './hello.js'
const greet = new Hello('Nice to Meet You!');
greet.hi('SeungOk!');
- 기본으로 내보내는 값을 정의
- 기본형 값과 객체, 함수, 클래스 모두 올 수 있음
- 단, 하나의 모듈에서 한번만 사용 가능
- 즉, 하나의 값만 defualt로 정의 가능
- var, let, const와 같은 변수선언 키워드는 올 수 없음
모듈 여러이름 내보내고 가져오기
export const version = 'v1.0';
export const sum = (a,b) => a+b;
import {version, sum} from './multiModule.js';
console.log(version, sum(1,2));
- 기본값과 달리 중복되지 않는 한 여러이름을 내보낼 수 있음
모듈 다양한 방식으로 사용하기
export default function sum(a,b){
return a+b;
}
export const version = 'v1.0';
export let value = 1;
setTimeout(()=>{
value++;
},1000);
import {version as moduleVersion} from './version.js';
import * as Version from './version.js';
import {value} from './version.js';
console.log(moduleVersion);
console.log(Version.default(1,2), Version.version)
setTimeout(()=>{
console.log(value);
},2000);
- as 키워드로 가져온 값을 다른 이름으로 사용
- *을 이용하여 전체를 가져오고 as 키워드로 이름 부여
- Version은 모듈 객체로 version, default 속성을 가짐
- 내보낸 모듈에서 값을 변경하게 되면 가져온 모듈에서도 영향을 받음