JavaScript 문법 종합반 1주차

·2023년 5월 22일

1. JS 언어의 역사, 특징

1.1 JS의 역사

  • 1995, 자바스크립트 탄생 (넷스케이프 커뮤니케이션) : LiveScript -> JavaScript 마케팅을 위해 관련은 없었으나 당시 인기있던 Java로 이름을 바꿈, (웹) 브라우저에서 동적인 액션들을 제어하기 위해 생김
  • 2005, AJAX 등장 : 버튼 하나로 해당 영역만 새로고침 가능 -> 이로 인해 UX(User Experience) 증가
  • 2008, V8 엔진 출신 (구글 크롬에 탑재) : 브라우저 속도 증가
  • 2009, Node.js 등장 : 서버 개발 활성화 -> FrontEnd + BackEnd + DB(MongoDB) = FullStack
  • 2015, ECMAScript 6(ES6) 버전 출시
  • 2016, 프론트엔드 프레임워크(React, Vue, Angular) 대중화, SPA 개발 활성화

1.2 JS의 특징

  • 객체 지향(<-> 절차 지향) 프로그래밍 지원 : 위에서 아래로 순서대로 실행하는 것이 아닌 어떠한 역할을 가진 객체라는 그룹으로 묶어서 객체 단위로 프로그래밍을 수행하는 것 -> 코드 재사용 용이 (지금 시대에 적합한 이유)
  • 동적 타이핑 : 변수의 타입을 따로 지정하지 않음 -> 런타임(프로그램이 돌아갈 때) 시점에 변수의 데이터 타입이 정해짐
  • 함수형 프로그래밍 지원 : 함수를 일급 객체로 취급하여 변수 할당이나 인자로 전달, 반환값으로 사용 가능
  • 비동기 처리 : 작업 병렬 처리
  • 클라이언트 측 및 서버 측 모두에서 사용 가능 : Node.js를 이용하여 서버 측에서도 사용됨

2. 기본 문법

2.1 변수와 상수

변수 : 변하는 수 (Variable)

var myVar = "Hello World";
console.log(myVar); // "Hello World"로 출력
  • 변수 이름 : myVar
  • 변수 값 : "Hello World"
  • 변수 할당 : var myVar = "Hello World"; // 변수에 값을 저장
  • 변수 선언 : var myVar = "Hello World"; // var로 변수 선언
  • 변수 참조 : 변수에 할당된 값을 읽어오는것

자바스크립트에서 변수는 var, let, const 이렇게 3가지 방법으로 선언 가능

  • var은 동일한 이름으로 여러 번 선언가능, 가장 마지막 값으로 덮어씌워짐
  • let은 동일한 이름으로 선언 불가
  • const도 동일한 이름으로 선언 불가, 선언 후 상수(= 변하지 않는 고정된 값, <-> 변수) 선언할 때 사용

2.2 데이터 타입과 형 변환

데이터 타입

  1. 숫자(Number) : 정수, 실수, 지수, Nan(Not a Number), Infinity,
let num = 3;
console.log(num); // 3
console.log(typeof num); // number , 즉 num의 타입이 출력됨

let num2 = 1 / 0; // 0으로 나누면 무한대로 발산 
console.log(num2); // Infinity
console.log(typeof num2); // "number"

let num3 = -1 / 0; // 0으로 나누면 마이너스 무한대로 발산 
console.log(num3); // -Infinity
console.log(typeof num3); // "number"
  1. 문자열(String) : 길이 확인(length), 결합(concatenation), 자르기(substr, slice), 검색(search), 대체(replace), 분할(split)
let str = "Hello, world!";
console.log(str.length); // 13 (문자, 기호, 띄어쓰기 모두 포함하며 인덱스 순서와 달리 1부터 시작)

let str1 = "Hello, ";
let str2 = "world!";
let result = str1.concat(str2); // (붙이려는 변수를 괄호 안에 넣음)
console.log(result); // "Hello, world!"

let str = "Hello, world!";
console.log(str.substr(7, 5)); // "world" (7 다음부터 5개의 문자)
console.log(str.slice(7, 12)); // "world" (7 다음부터 12까지의 문자)

let str = "Hello, world!";
console.log(str.search("world")); // 7 (몇 번째 부처 시작되는지 검색)

let str = "Hello, world!";
let result = str.replace("world", "JavaScript"); // (world를 JavaScript로 대체)
console.log(result); // "Hello, JavaScript!"

let str = "apple, banana, kiwi";
let result = str.split(","); // (','을 기준으로 문자열을 자르고 싶음)
console.log(result); // ["apple", " banana", " kiwi"]
  1. 불리언(Boolean) : true, false

  2. undefined : 값이 할당(저장)되지 않은 변수

  3. null : 값이 존재하지 않음

  4. 객체 (Object) : { }, key + value

    자바스크립트의 기본 타입(data type)은 객체(object) 이다. '객체란 속성(key)와 값(value) 으로 구성된 프로퍼티(property)'의 정렬되지 않은 집합이다.

  5. 배열 (Array) : [ ], 인덱스

형 변환

  1. 암시적 형 변환 (implicit coercion) 넌지시 알리는 : 자동으로 수행되는 형 변환, 주로 연산자 사용할 때 발생
console.log(1 + "2");   // "12"
console.log("1" + true);   // "1true"
console.log("1" + {});   // "1[object Object]"
console.log("1" + null);   // "1null"
console.log("1" + undefined);   // "1undefined"
  • +연산자로 다른 자료형(ex. 숫자, 불리언, 배열 등)을 문자열로 변환 후 계산 수행
console.log(1 - "2");   // -1
console.log("2" * "3");   // 6
console.log(4 + +"5");   // 9
  • - * ++ / %연산자는 문자를 숫자로 변환 후 연산 수행
console.log(Boolean(0));   // false
console.log(Boolean(""));   // false
console.log(Boolean(null));   // false
console.log(Boolean(undefined));   // false
console.log(Boolean(NaN));   // false
console.log(Boolean("false"));   // true
console.log(Boolean({}));   // true
  • Boolean() 함수를 사용하여 불리언 값으로 변환되는데 0 "" null undefined NaN은 false로 변환

 

  1. 명시적 형 변환 (explicit coercion) 내용이나 뜻이 분명한 : 개발자가 직접 자료형을 변환
console.log(String(123));       // "123"
console.log(String(true));      // "true"
console.log(String(false));     // "false"
console.log(String(null));      // "null"
console.log(String(undefined)); // "undefined"
console.log(String({}));        // "[object Object]"
  • String() 함수를 사용하여 다른 자료형(ex. 숫자, 불리언, 배열 등)을 문자열로 변환
console.log(Number("123"));   // 123
console.log(Number(""));      // 0
console.log(Number("  "));    // 0
console.log(Number(true));    // 1
console.log(Number(false));   // 0
  • Number() 함수를 사용하여 다른 자료형(ex. 숫자, 불리언, 배열 등)을 숫자로 변환

2.3 연산자

  1. 산술 연산자 (arithmetic operators) : + (숫자, 문자가 함께 있으면 숫자를 문자열로 변환하여 계산) - * / % (숫자와 문자열이 함께 있으면 문자열을 숫자로 변환하여 계산)

  2. 할당 연산자(assignment operators) : = (변수에 값을 할당할 수 있음) += -= *= /= %=

  3. 비교 연산자(comparison operators) : === (자료형까지 비교) !== (자료형까지 비교) < > <= >= (부등호 연산자는 숫자, 문자가 함께 있으면 문자열을 숫자로 변환하여 계산)

  4. 논리 연산자(logical operators) : && (논리곱) || (논리합) ! (논리부정, 값을 반대로 바꿀 수 있음, ex. true->false)

console.log(!(2 > 1));   // false
  1. 삼항 연산자(ternary operator) : ?:
let x = 7;
let result = (x > 10) ? "크다" : "작다";
console.log(result);   // "작다"
  1. 타입 연산자(type operators) : typeof (값의 자료형을 확인할 수 있음, 이때 객체나 함수일 경우 object와 function으로 반환)
console.log(typeof true);   // "boolean"
console.log(typeof undefined);   // "undefined"
console.log(typeof null);   // "object" // 버그임
console.log(typeof {});   // "object"
console.log(typeof []);   // "object"
console.log(typeof function(){});   // "function"

2.4 함수

함수를 사용하면 코드의 재사용성이 용이

  1. 함수 정의하기
  • 함수 선언문 : function 키워드를 사용해 add라는 함수를 선언
function add(x, y) {
  return x + y;
}

console.log(add(2, 3));   // 5
  • 함수 표현식 (함수 표현식을 사용하면 함수를 변수에 할당하여 익명 함수를 생성할 수 있음)
// 첫번째 타입
let add = function(x, y) {
  return x + y;
}

console.log(add(2, 3));   // 5

// 두번째 타입
const dog = {
  name: '멍멍이'
};

function getName(animal) {
  return animal.name;
}

const name = getName(dog);
console.log(name); // 멍멍이
  1. 함수 호출하기
  2. 함수 매개변수와 반환값
function add(x, y) { // 매개변수는 x와 y
  return x + y; // x + y의 결과 값이 반환값
}

console.log(add(2, 3));   // 함수 호출
  1. 함수 스코프 (=범위)
  • 전역 스코프 (전역 : 모든 구역에서 참조 가능)
  • 지역 스코프 (지역 : 정해진 구역에서만 참조 가능, 주로 { } 안)
  • 블록 스코프 (해당 블록 내에서만 참조 가능)

지역 스코프와 블록 스코프의 차이 !
참고 링크 ,  참고 링크 2

function printX() { // printX() 함수
  let x = 10;
  console.log(x);
}
printX();   // 지역 스코프


if (true) { // if문
  let x = 10;
  console.log(x);
}
console.log(x);   // 블록 스코프
				 // ReferenceError: x is not defined

간략하게 설명하자면, 지역 스코프 안에 함수 스코프와 블록 스코프가 있는데, 함수 스코프는 var을 따르기에 블록 내부에서 선언해도 블록 바깥에서 접근 사용이 가능하나, 블록 스코프는 let, const로 선언된 변수를 따르며 함수가 아닌 블록 단위에서 지역변수로 선언되어 블록 바깥에서는 변수 접근이 불가.

  1. 화살표 함수
  • 기본적인 화살표 함수 : 아래 코드에서 볼 수 있듯이 변수에 화살표 함수를 사용하여 add에 함수를 할당시키는 방법
let add(x, y) { // 기본적인 함수
	return x + y;
}
console.log(add(2, 3)); // 5

let add = (x, y) => { // 기본적인 '화살표' 함수
  return x + y;
}

console.log(add(2, 3));   // 5
  • 한 줄로 된 화살표 함수 : 아래 코드처럼 return문이 한 줄이라면 중괄호와 return을 생략하고 화살표함수 다음 (반환) 값을 주어 작성 가능
let add = (x, y) => x + y;

console.log(add(2, 3));   // 5
  • 매개변수가 하나인 화살표 함수 : 아래 코드처럼 매개변수가 하나인 경우 괄호를 생략하고 화살표 함수 사용 가능
let square = x => x * x;

console.log(square(3));   // 9

3. 문

3.1 조건문

  1. if문, if-else문, if-else if-else문
let a = "여자";

if (a === "남자") {
	console.log("a는 남자입니다.");
} else if (a === "여자") {
	console.log("a는 여자입니다."); // 출력
} else {
	console.log("a는 남자도 여자도 아닙니다.");
}	
  • 알다시피 else if를 계속 쓰다가도 마지막엔 아무 조건이 없는 else문을 작성해줘야 함
  1. switch문
let animal = "호랑이"

switch (animal) {
	case "호랑이" :
    	console.log("어흥어흥");
        break;
	case "소" :
    	console.log("음메음메");
		break;
    case "토끼" :
    	console.log("깡총깡총");
        break;
    default:
    	console.log("해당 동물이 없습니다.");
        break;
}
  • 이처럼 switch문에 빠지면 안되는 3가지는 'case', 'break', 'default'
  1. 삼항 연산자
let height = 168;
let msg = (height >= 170) ? "키가 170을 넘습니다." : "키가 170을 넘지 않습니다."
console.log(msg);
  • 위 코드처럼 괄호를 씌워 조건을 설정해주어도 됨
  1. 조건문 중첩 (= 중첩된 if문) : 중첩 사용도 가능

  2. 조건부 실행 (실행순서 좌->우) : 논리 연산자 && 를 사용하여 앞 조건이 truthy하면 뒤 조건을 바로 실행 (즉, 앞 조건이 falsy하면 바로 fasly한 값 출력)

let x = 100;

(x > 99) && console.log("x는 100이 넘습니다.");
  1. 삼항 연산자와 단축 평가 (실행순서 좌->우) : 논리 연산자 || 를 사용하여 앞조건이 falsy하면 뒤 조건을 바로 실행 (즉, 앞조건이 truthy 앞조건 출력)
// 기본적으로 이러한 결과 값
"apple" || "banana";  // "apple"

// 첫번째 타입
let x; // falsy한 값 -> why ? 변수가 undefined 상태여서
let y = x || 100;

console.log(y) // 100

// 두번째 타입
const namelessDog = {
  name: '' //falsy한 값  -> why ? key값이 undefined 상태여서
};

function getName(animal) {
  const name = animal && animal.name;
  return name || '이름이 없는 동물입니다.'; //name 값이 falsy하므로 뒤 조건 출력
}

const name = getName(namelessDog); // 함수 표현식
console.log(name); // 이름이 없는 동물입니다.

// 세번째 타입
let condition = true; // truthy한 값
let result = "";

result = condition || "참"; // 단축평가 사용, 앞 조건인 condition이 truthy함으로 바로 앞조건인 condition의 true를 출력

console.log(result); // true

단축 평가에 대해 더 자세한 내용
참고 링크참고 링크2,  참고 링크3

  1. falsy한 값과 truthy한 값 : falsy한 값(0 "" null undefined NaN false)들은 if문의 조건을 만족시키지 못함, 이 외의 값은 truthy한 값으로 if문의 조건을 만족
if (0) { // 0 "" null undefined NaN false
  console.log("이 코드는 실행되지 않습니다.");
}

3.2 반복문

  1. for문
  • for ... in 문
let person = { name: "John", age: 30, gender: "male" };

for (let key in person) {
  console.log(key + ": " + person[key]); // 객체의 프로퍼티를 순서대로 접근 가능
}							// 객체 뒤에 [key]를 붙여 (속성을 통해) 객체의 value 값에 접근 가능
  1. while문 : 꼭 증감식이나 감소식을 적어줘야 함 -> 안그러면 무한 루프에 빠지게 됨 ...

  2. do-while문 : 꼭 증감식이나 감소식을 적어줘야 함 -> 안그러면 무한 루프에 빠지게 됨 ...

let i = 5;

do {
	console.log(i);
    i--;
} while (i > 0); // i가 0보다 클 때까지 실행
  1. break문

  2. continue문 : continue문은 break문과 달리 그 문을 제외하고 다음부터 다시 실행됨

for (let i = 0; i < 5; i++) {
	if (i === 3) {
    	continue;
    }
    console.log(i); // 0 1 2 4
}

4. 배열, 객체 기초

4.1 객체와 객체 메소드

  1. 객체 생성과 속성 접근
  • 기본적인 객체 생성 : 객체 person을 생성, 속성(key)와 값(value)를 :으로 구분하고 각 속성과 값은 ','로 구분
let person = {
	name : "김미영",
    age : 28,
    gender : "여자"
}

console.log(person.age) // 28 => 객체 person의 속성에 접근해 '.'을 통해 값을 출력
  • 생성자 함수 사용하여 객체 생성
let person = {
	this.name : name,
    this.age : age,
    this.gender : gender
}

let person = new person("이미영", 40, "여자"); // 생성자 함수 !
  1. 객체 메소드
  • Object.keys(), Object.values(), Object.entries(), Object.assign()
let animal = {
	name : "양",
    color : "흰색",
	age : 5
}

// Object.keys() 는 객체의 속성 이름을 배열로 반환
let keys = Object.keys(animal);

console.log(keys); // ["name", "color", "age"]

// Object.values() 는 객체의 속성 값들을 배열로 반환
let values = Object.values(animal)

console.log(values); // ["양", "흰색", 5]

// Object.entries() 는 객체의 속성 이름과 속성 값을 2차원 배열로 반환
let entries = Object.entries(animal);

console.log(entries); // [ [ 'name', '양' ], [ 'color', '흰색' ], [ 'age', 5 ] ]

//Object.assign() 는 기존 객체를 복사하여 새로운 객체를 만듦
let newAnimal = {};

Object.assign(newAnimal, animal, { color: "검정색" }); // (어디에 복사할래, 뭘 복사할래, 뭘 바꿀래)

console.log(newPerson);   // { name: '양', color: '검정색', age: 5 }
  • 객체 비교, 객체 병합
// 객체 비교 에서 일반적인 비교 연산자 === 는 사용할 수 없고, 
// JSON.stringify() 사용해서 객체를 문자열로 변환 후 문자열끼리 비교해서 값을 도출

let animal1 = {
  name: "양",
  age: 5,
  color: "흰색"
};

let animal2 = {
  name: "양",
  age: 5,
  color: "흰색"
};

console.log(animal1 === animal2);   // false
console.log(JSON.stringify(animal1) === JSON.stringify(animal2));   // true
// 객체 병합 에서는 ...을 사용하여 객체끼리 병합이 가능

let animal1 = {
  name: "양",
  age: 5,
};

let animal2 = {
  color: "흰색" // 만약 속성 이름이 같은데 병합시킨다면 뒤에 있던 값으로 덮어져서 출력됨 
};

let mergedAnimal = {...animal1, ...animal2};

console.log(mergedAnimal);   // { name: "양", age: 5, color: "흰색" }

4.2 배열과 배열 메소드

  1. 기본적인 배열 생성과 크기 지정
let flower = ["해바라기", "무궁화", "개나리"]; // 기본적인 배열 생성

let flower = new Array(4); // 배열 크기 지정
  1. 배열 요소 접근 : 인덱스 값을 통해 배열의 요소에 접근할 수 있음
let flower = ["해바라기", "무궁화", "개나리"];

console.log(flower[1]);   // "무궁화"
console.log(flower[2]);   // "개나리"
  1. 배열 메소드
  • push(), pop(), shift(), unshift(), splice(), slice()
let flower = ["해바라기", "무궁화", "개나리"];

// push() 는 배열 끝에 괄호 안에 적은 요소를 추가할 수 있음
flower.push("진달래");

console.log(flower); // ["해바라기", "무궁화", "개나리", "진달래"];

// pop() 는 배열 끝 요소를 삭제할 수 있음 (지정은 불가)
flower.pop();

console.log(flower); // ["해바라기", "무궁화", "개나리"];

// shift() 는 배열 가장 첫번째 요소를 삭제할 수 있음
flower.shift();

console.log(flower);   // ["무궁화", "개나리"];

// unshift() 는 shift()와 반대로 배열 가장 첫번째 위치에 괄호 안에 적은 요소를 추가할 수 있음
flower.unshift("튤립");

console.log(flower); // ["튤립", "무궁화", "개나리"];

// splice() 는 특정 위치를 선택해 그 위치에 있던 요소를 삭제할 수 있고 새로운 요소를 추가까지 할 수 있음
flower.splice(1, 1, "민들레") // (삭제가 시작되는 위치, 삭제할 개수, 추가할 요소 값(생략가능))

console.log(flower); // ["튤립", "민들레", "개나리"];

// slice() 는 해당되는 요소들이 팅겨져나와 새로운 배열로 생성됨
let slicedFlower = flower.slice(1, 2); // 새로운 변수 설정 필요, (시작되는 위치, 끝나는 위치) = 1부터 2전까지의 요소가 해당

console.log(slicedFlower);   // ["민들레"]
  • forEach(), map(), filter(), find(), reduce(), some(), every(), sort(), reverse()

    매개변수 자리에 함수를 넣는 것 = '콜백함수'

    요소가 문자열인 배열을 사용하여 메소드 실행
    참고 링크

let num = [5, 4, 3, 2, 1];

// forEach() 는 배열의 각 요소에 대해 콜백함수를 실행하여 flower의 모든 요소를 출력
num.forEach(function(number) {
  console.log(num); // 5 4 3 2 1 
});

// map() 는 배열의 각 요소에 대해 콜백함수를 실행하고 새로운 변수에 할당하여 새로운 배열로 반환
let squaredNums = num.map(function(number) {
  return num * num;
});

console.log(squaredNums); // [25, 16, 9, 4, 1]

// filter() 는 배열의 각 요소에 대해 콜백함수를 실행하고, 그 결과가 true인 요소만 새로운 배열로 반환
let evenNums = num.filter(function(number) {
  return number % 2 === 0;
});

console.log(evenNums);   // [2, 4]

// find() 는 배열의 각 요소에 대해 콜백함수를 실행하고, 그 결과가 조건에 맞는 첫번째 요소만 출력
let foundNum = num.find(function(number) {
  return number > 3;
});

console.log(foundNum);   // 4
let people = ["김씨", "이씨", "박씨", "최씨"];

people.forEach(function (name) {
  //(name) 콜백함수의 매개변수
  console.log(name); // 5 4 3 2 1
});

// let squaredpeoples = people.map(function (name) {
//   return name * name;
// });

// console.log(squaredpeoples); //

let evenPeople = people.filter(function (p) {
  return p === "박씨";
});

console.log(evenPeople); // [ '박씨' ]

let foundPeople = people.find(function (p) {
  return p === "이씨";
});

console.log(foundPeople); // 이씨

일단은 문자열로 메소드 사용해봤는데 이 부분은 잘 이해가 되지 않음
filter는 ['박씨']로 출력되고 find는 이씨로 출력되는 이유
문자열이라 뭘 검사해봐야할지도 모르겠음


5. 숙제

5.1

  1. 문제

  2. 해설

5.2

  1. 문제

  2. 해설

0개의 댓글