1.  문서 객체 모델 DOM  Document Object Model

👩🏻‍💻  문서 객체를 조합해서 만든 전체적인 형태를 말함

👩🏻‍💻  자바 스크립트를 사용하는 목적은 html을 다루는 것
        ▶️  자바 스크립트에서는 html 요소를 문서 객체 document object를 이용해 조작을 함

👩🏻‍💻  HTML 페이지는 코드를 위에서 아래로 차례대로 실행

        ➡️  body 태그 생성되기 이전인 head 태그에서 body 태그에 무언가 출력하려면 문제 발생

       ➡️  기본적으로 head 태그 내부에 script 태그를 배치하면 body 태그에 있는 문서 객체(요소)에 접근 불가

<head>    
    <script>
        const h1 = (text) => `<h1>${text}</h1>`;
    </script>
    <script>
        document.addEventListener('DOMContentLoaded', function () {
            document.body.innerHTML += h1('1번째 script 태그');
        });
    </script>
</head>
<body>

    <h1>1번째 h1 태그</h1>
    <script>
        document.body.innerHTML += h1('3번째 script 태그');
    </script>
    <h1>2번째 h1 태그</h1>

</body>

 


 

(1)  DOMContentLoaded 이벤트

💡  DOMContentLoaded 이벤트는 웹 브라우저가 문서 객체를 모두 읽고 나서 실행       
       ▶️  script 태그가 body 태그 이전에 위치해도 문제없이 코드 실행
<script>
    // DOMContentLoaded를 연결. DOMContentLoaded 상태가 되었을 때 콜백 함수를 호출
    document.addEventListener('DOMContentLoaded', () => {
        const h1 = (text) => `<h1>${text}</h1>`;
        document.body.innerHTML += h1('DocumentLoaded 이벤트 발생');
    });
</script>

📌  DOMContentLoaded 사용한 배경색 변경 예제
<head>
    <script>
        document.addEventListener('DOMContentLoaded', function () {
            const changeBtn = document.querySelector('#changeBtn');
            const resetBtn = document.querySelector('#resetBtn');

            let i = 0;

            const bodyTag = document.querySelector('body');
            const color = ['red', 'orange', 'yellow', 'blue'];
            const handleColor = () => {
                bodyTag.style.backgroundColor = color[i++ % color.length];
            }

            changeBtn.addEventListener('click', handleColor);
            resetBtn.addEventListener('click', () => {
                changeBtn.removeEventListener('click', handleColor);
                bodyTag.style.backgroundColor = '';
            })
        })
    </script>
</head>
<body>
    <button id="changeBtn">배경색 변경</button>
    <button id="resetBtn">배경색 초기화</button>
</body>

 


 

💡  addEventListener('이벤트', '콜백함수') 메소드
     -  document라는 문서 객체의 이벤트가 발생했을 때, 매개변수로 지정한 콜백 함수를 실행하라는 의미

 


(2) 문서 객체 가져오기

document.head / document.body / document.title

        
    👩🏻‍💻  head와 body 요소 내부에 다른 요소들은 다음과 같은 별도의 메소드를 사용해서 접근
         ⚡️  document.querySelector(선택자) : 요소를 하나만 추출
         ⚡️  document.querySelectorAll(선택자) : 선택자에 해당하는 모든 문서 객체를 배열로 가져옴
     👩🏻‍💻  선택자 부분에는 CSS 선택자를 입력

이름 선택자 형태 설명
태그 선택자 태그 특정 태그를 가진 요소를 추출
아이디 선택자 #아이디 특정 id 속성을 가진 요소를 추출
클래스 선택자 .클래스 특정 class 속성을 가진 요소를 추출
속성 선택자 [속성=값] 특정 속성 값을 갖고 있는 요소 추출
후손 선택자 선택자_A 선택자_B 선택자_A 아래에 있는 선택자_B 선택

 

<head>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const header = document.querySelector('h1'); // 요소를 읽어들임. 제일 먼저 나오는 요소 하나만 가져옴.
            // 텍스트와 스타일을 변경.
            header.textContent = 'HEADERS';
            header.style.color = 'white';
            header.style.backgroundColor = 'black';
            header.style.padding = '10px';

            const headersAll = document.querySelectorAll('h2'); // 요소를 읽어들임.
            console.log(headersAll)
            headersAll.forEach((item) => { // 일반적으로 forEach() 메소드를 사용해서 반복을 돌림.
                item.textContent = 'headersAll';
                item.style.color = 'red';
                item.style.backgroundColor = 'black';
                item.style.padding = '20px';
            })

            // 1. for문을 사용해서 글자색을 빨강으로 변경
            for(let idx = 0; idx < headersAll.length; idx++) {
                headersAll[idx].style.color = 'red';
            }

            // 2. for in 문을 사용해서 글자색을 파랑으로 변경
            for(let idx in [...headersAll]) {
                headersAll[idx].style.color = 'blue';
            }

            // 3. for of 문을 사용해서 글자색을 주황으로 변경
            for(const i of headersAll) {
                i.style.color = 'orange';
            }

        })
    </script>
</head>
<body>
    <h1></h1>
    <h1>2</h1>
    <h2></h2>
    <h2></h2>
    <h2></h2>
    <h2></h2>
</body>

 

 

 

 

[ 내용참고 : IT 학원 강의 및 책 '혼자 공부하는 자바스크립트' ]


1.  형변환 Casting

· 변수 또는 상수의 타입을 다른 타입으로 변환하는 것

· 형변환 방법 ; (타입)피연산자

· float 타입의 값을 int 타입으로 변환할 때 소수점 이하의 값은 버림으로 처리됨

 

    ⚡️  자동 형변환 : 값의 범위가 작은 타입에서 큰 타입으로의 형변환은 생략가능

    ⚡️  명시적 형변환 : 변수의 자료형을 강제로 바꾸는 것 ▶️ 숫자크기 상관없이 앞에 형변환 해줘야 함

 
<기본형의 자동 형변환이 가능한 방향>

 

public class Etc0208 {

	public static void main(String[] args) {
		
		byte b = 10;
		int i = b;
	
		System.out.println("i=" + i); // 10
		System.out.println("b=" + b); // 10
		
		int i2 = 10;
		byte b2 = (byte)i2;

		System.out.println("i2=" + i2); // 10
		System.out.println("b2=" + b2); // 10

	}
}

 

public class Exma001 {

	public static void main(String[] args) {

		byte a = 127; // byte가 가질 수 있는 최대값
		int b = a; // 자동 형변환 (byte -> int)
		System.out.println(b); // 127
		
		float c = b; // 자동형변환 (int -> float) 값손실이 없기 때문.
		System.out.println(c); // 127.0
		
		//int d = c; // float 자료형을 int 변수에 대입하면 자동형변환이 안됨.

	}

}

 


문자열을 기본 타입으로 강제 타입 변환


  📌  String은 int나 char처럼 기본 자료 타입이 아닌 클래스의 객체 형태라서 일반적인 형변환과 다름

public class MyVar_09 {
    public static void main(String[] args) {
		
		String str = "1a";
		//int value = Integer.parseInt(str); // 문자열에 숫자외의 문자가 있으면 변환이 되지 않음
		
		// String -> byte
		String str1 = "10";
		byte value1 = Byte.parseByte(str1);
		System.out.println(value1); // 10
		
		// String -> short
		String str2 = "200";
		short value2 = Short.parseShort(str2);
		System.out.println(value2); // 200
		
		// String -> int
		String str3 = "300000";
		int value3 = Integer.parseInt(str3);
		System.out.println(value3); // 300000
		
		// String -> long
		String str4 = "400000000";
		long value4 = Long.parseLong(str4);
		System.out.println(value4); // 400000000
		
		// String -> float
		String str5 = "12.345";
		float value5 = Float.parseFloat(str5);
		System.out.println(value5); // 12.345
		
		// String -> double
		String str6 = "12.345";
		double value6 = Double.parseDouble(str6);
		System.out.println(value6); // 12.345
		
		// String -> boolean
		String str7 = "true";
		boolean value7 = Boolean.parseBoolean(str7);
		System.out.println(value7); // true
		
	}
}

 


기본 타입과 문자열 간의 변환


  📌  기본 타입의 값을 문자열로 변경하는 경우에는 String.valueOf() 메소드를 이용

String str = String.valueOf(기본타입값);
public class MyVar_10 {
	public static void main(String[] args) {
		
		// 문자열을 기본 타입으로 변환
		int value1 = Integer.parseInt("10");
		double value2 = Double.parseDouble("3.14");
		boolean value3 = Boolean.parseBoolean("true");
		
		System.out.println("value1 : " + value1); // value1 : 10
		System.out.println("value2 : " + value2); // value2 : 3.14
		System.out.println("value3 : " + value3); // value3 : true
		
		// 기본 타입을 문자열로 변환
		String str1 = String.valueOf(10);
		String str2 = String.valueOf(3.14);
		String str3 = String.valueOf(false);
		
		System.out.println("str1 : " + str1); // str1 : 10
		System.out.println("str2 : " + str2); // str2 : 3.14
		System.out.println("str3 : " + str3); // str3 : false
	}
}

 


연습 문제

 

   📌  'int result = '에 1) 변수 4개를 모두 사용하고 2) 사칙연산중 + 연산만 사용해서 9가 나오도록 코드를 완성

public class Ex_01 {
	public static void main(String[] args) {
		
		long var1 = 2L;
		float var2 = 1.8f;
		double var3 = 2.5;
		String var4 = "3.9";
		
		int result = (int)var1 + (int)(var2 + var3) + (int)Double.parseDouble(var4); 
        // 이 부분만 수정. 0대신 코드 입력.
		System.out.println(result); // 9
	}
}

 


2.  연산자  Operator

 

· 연산자 : 연산을 수행하는 기호

· 피연산자(operand) : 연산자의 작업 대상 (변수, 상수, 리터럴, 수식)

· 단항 연산자의 우선순위가 이항 연산자보다 높다.

· 단항 연산자와 대입 연산자를 제외한 모든 연산의 진행방향은 왼쪽에서 오른쪽

 

 

(1)  산술 연산자

 

    a) 사칙 연산자 :  +(덧셈), -(뺄셈), *(곱셈), /(나눗셈)

    b) 나머지 연산자 :  %  ▶️ a를 b로 나눈 후 나머지를 반환, 주로 짝수 홀수 구분에 사용

public class Exam004 {
	public static void main(String[] args) {
		
		int num1 = 10; // 10을 대입
		int num2 = 3; // 3을 대입
		
		System.out.println(num1 + num2); // 13
		System.out.println(num1 - num2); // 7
		System.out.println(num1 * num2); // 30
		System.out.println(num1 / num2); // 3
		System.out.println(num1 % num2); // 1
		System.out.println(num1 % 2); // 0
		System.out.println(num2 % 2); // 1
	}
}

 


 

(2) 논리부정 연산자 : !

 

    -  피연산자가 true이면 false를, false면 true를 결과로 반환

public class Exam006 {
	public static void main(String[] args) {
		
		boolean a = true;
		boolean b = false;
		boolean c = !b; // b의 값을 반대로 바꾸어 입력
	
		System.out.println(a); // true
		System.out.println(!a); // false
		
		System.out.println(b); // false
		System.out.println(c); // true
	}
}

 


(3) 정수와 실수 연산

 

    - 정수와 정수의 연산의 결과 값은 정수. 정수와 실수 연산의 결과 값은 실수 

public class MyVar_11 {
	public static void main(String[] args) {

		byte kor, math, eng;
		kor = 55;
		math = 99;
		eng = 87;
		
		int sum = kor + math + eng;
		System.out.println("총점 : " + sum); // 총점 : 241
		
		int avg_01 = sum /3;
		System.out.println("평균 : " + avg_01); // 평균 : 80
		
		double avg_02 = sum /3; // 정수 / 정수
		System.out.println("평균 : " + avg_02); // 평균 : 80.0 -> 정수 연산으로 정수 값이 나온 후에 실수에 저장.
		
		double avg_03 = (double)sum / 3; // 실수 / 정수
		System.out.println("평균 : " + avg_03); // 평균 : 80.33333333333333
		
		double avg_04 = sum / 3.0; // 정수 / 실수
		System.out.println("평균 : " + avg_04); // 평균 : 80.33333333333333
		
		double avg_05 = (double)sum / 3.0; // 실수 / 실수
		System.out.println("평균 : " + avg_05); // 평균 : 80.33333333333333
		
	}
}

 

 

 

 

[ 내용 참고 : IT 학원 강의 및 자바의 정석 3rd ]


1.  변수 variable 란?

 

👩🏻‍💻  단 하나의 값을 저장할 수 있는 메모리 공간

       ex. int age = 25  ▶️ 변수 age를 선언하고 25로 초기화 한다.

 

변수 명명 규칙

 

     a.  예약어 사용 x

     b.  숫자로 시작 x

     c.  특수문자는 '_'와 '$'만 가능

     d.  클래스 이름 첫 글자는 항상 대문자, 변수와 메서드의 첫 글자는 항상 소문자

     e.  여러단어로 이루어진 경우 첫 글자만 대문자

     f.   상수의 이름은 모두 대문자

정수형 변수 타입 범위 크기
byte -128~127 1 byte, 8bit
short -32,768 ~ 32,767 2 byte, 16bit
int 2,147,483,648 ~ 2,147,483,6647 4 byte, 32bit
long -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 8 byte, 64bit

 

💡  float : 소수점 7자리
💡  double : 소수점 15자리

 


2.  변수 기본형  Primitive type

(1) 논리형 ; boolean - true, false 값만 가짐 (1byte)

public class BooleanExample {
	public static void main(String[] args) {
		// boolean 형은 두가지 값만 존재 : true, false
		boolean stop = false;
		if(stop) {
			System.out.println("중지합니다.");
		} else {
			System.out.println("시작합니다.");
		}
	}
}
// 출력결과 : 시작합니다.
 

 

(2) 문자형 'char' (2byte)

 

     📁  char단 하나의 문자만 저장, 여러 문자를 저장 할려면 String 사용
     📁  char''(작은 따옴표)로만 묶임
     📁  String클래스, ""(큰 따옴표)로만 묶어야 함

 
public class Etc0201 {
	public static void main(String[] args) {
		// 문자를 숫자로
		char ch = 'A'; // char ch = '\u0041';로 바꿔 써도 같다.
		int code = (int)ch; // ch에 저장된 값을 int형으로 변환하여 저장한다.
		System.out.println(ch); // A
		System.out.println(code); // 65
	}
}

 

(3) 정수형 byte / short / int / long

      - long 접미사 ; l or L

 


 

(4) 실수형 float / double

      - float 접미사 ; f ( 기본 타입이 double 이기 때문에 안 붙이면 에러남)

 


※  아스키코드 
   미국정보교환표준부호, 또는 줄여서 ASCII는 영문 알파벳을 사용하는 대표적인 문자 인코딩이다. 아스키는 컴퓨터와 통신 장비 
   를  비롯한 문자를 사용하는 많은 장치에서 사용되며, 대부분의 문자 인코딩이 아스키에 기초를 두고 있다.
(출처 ; 위키백과)

※  유니코드   
   전 세계의 거의 모든 문자에 고유 숫자를 부여한 문자 집합

 


💡 데이터 단위 (출처; 삼성반도체 사이트)

3.  상수 constant 와 리터럴 literal 

 

(1) 상수

형식 : final 데이터 타입 상수명 = 값;

 

  · 변수와 달리 한 번 값을 저장하면 다른 값으로 변경할 수 없다. 대문자로 선언

  · 변수 타입 앞에 'final' 붙이면 된다.

public class Exam003 {
	public static void main(String[] args) {
		int a =3;
		System.out.println(a); // 3
		a = 4;
		System.out.println(a); // 4
		
		final double PI = 3.14;
		// PI = 3.15; // 에러발생
		System.out.println(PI); // 3.14 이 문장만 봐도 PI가 상수인걸 할 수 있도록 대문자로 작성.
	}
}

 


 

(2)  리터럴

 

· 문자 리터럴 : 작은따옴표로 문자 하나를 표현한 것  ▶️  ''안에 하나의 문자가 있어야 함

· 문자열 리터럴 : 큰 따옴표로 감싼 두 문자 이상  ▶️  "" 안에 아무런 문자도 넣지 않는 것 ok

· 덧셈 연산자는 피연산자 중 어느 한 쪽이 String이면 나머지 한 쪽을 먼저 String으로 변환한 다음 두 String을 결합한다.

    * 왼쪽에서 오른쪽 방향으로 연산을 수행

 

char sample = '\'' = ''';

 

public class MyVar_06 {
	public static void main(String[] args) {
		/* 문자열 표현 */
		char single = '\''; 
		String db1Quote = "\"Hello\""; // 겹따옴표를 출력하려면 이렇게 한다.
	    String root = "c:\\";
	    
	    System.out.println(single); // '
	    System.out.println(db1Quote); // "Hello"
	    System.out.println(root); // c:\
	    
	    char single2 = '"';
	    String single3 = "'";
	    String db1Quote2 = "'Hello'";
	    //String db1Quote3 = 'Hello';  // 에러
	    
	    System.out.println(single2); // "
	    System.out.println(single3); // '
	    System.out.println(db1Quote2); // 'Hello'
	}
}

 


4.  문자열 연산

 

'+' 연산자의 두 가지 기능


    1) 피연산자가 숫자일 경우에는 덧셈 연산
    2) 피연산자 중 하나라도 문자열이면 나머지 피연산자도 문자열로 자동 변환되어서 문자열 결합 연산을 수행

public class MyVar_07 {
	public static void main(String[] args) {
		// 숫자 결합 연산
		int value = 10 + 2 + 8;
		System.out.println("value : " + value); // 20
		
		
		// 문자 결합 연산
		String str1 = 10 + 2 + "8";
		System.out.println("str1 : " + str1); // 128 :
		// 연산자는 왼쪽에서 오른쪽으로 순서대로 실행이 되기 때문에
		// 12 + "8" 이 됨 
		
		String str2 = 10 + "2" + 8;
		System.out.println("str2 : " + str2); // str2 : 1028
		
		String str3 = "10" + 2 + 8;
		System.out.println("str3 : " + str3); // str3 : 1028
		
		String str4 = "10" + (2 + 8);
		System.out.println("str4 : " + str4); // str4 : 1010

	}

}

 


문자열 연산 예제
public class MyVar_08 {
	public static void main(String[] args) {

		String a = 7 + " ";
		String b = " " + 7;
		String c = 7 + "";
		String d = "" + 7;
		String e = "" + "";
		String f = 7 + 7 + "";
		String g = "" + 7 + 7;
		
		System.out.println(a); // 7
		System.out.println(b); //  7
		System.out.println(c); // 7
		System.out.println(d); // 7
		System.out.println(e); 
		System.out.println(f); // 14
		System.out.println(g); // 77
	}
}

 

 

 

 

 

[내용 출처 : 자바의정석 및 학원강의]


1.  타이머 timer 함수  

🐰  특정 시간 이후에 콜백함수를 호출할 수 있는 함수

함수 이름 설명
setTimeout(함수, 시간) 특정 시간 후에 함수를 한 번 호출
setInterval(함수, 시간) 특정 시간마다 함수를 호출

 

<script>
    setTimeout(function () {
        console.log(`2초 후에 실행됩니다.`);
    }, 2 * 1000); // 시간의 기초단위는 밀리 초 단위.

    let count = 0;
    setInterval(() => {
        console.log(`2초마다 실행됩니다.(${count}번째)`);
        count++;
    }, 2 * 1000);
</script>

 


타이머 함수를 종료하고 싶은 경우

 

함수 이름 설명
clearTimeout(타이머_ID) setTimeout() 함수로 설정한 타이머를 제거
clearInterval(타이머_ID) setInterval() 함수로 설정한 타이머를 제거

 

🐰  타이머 ID는 setTimeout()과 setInterval() 함수를 호출할 때 리턴 값으로 나오는 숫자

<script>
    let count = 0;
    let id = setInterval(() => { // setInterval은 반환형이 있는 함수이기 때문에 변수에 저장 가능
        console.log(`1초마다 실행됩니다(${count}번째)`);
        count++;
    }, 1000);

    setTimeout(() => {
        console.log('타이머를 종료합니다.');
        clearInterval(id);
    }, 5 * 1000); // 5초후 종료
</script>

 


응용 문제 - 정지 & 시작버튼

 

<head>
    <style>
        * {
            padding: 0;
            margin: 0;
        }

        #numb {
            width: 100vw;
            height: 400px;
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 300px;
        }

        #box {
            display: flex;
            justify-content: center;
            align-content: center;
        }

        button {
            width: 50px;
            height: 20px;
            margin: 0 10px;
        }

    </style>

    <script>
        /* '정지' 버튼을 클릭하면 정지 */
        const rainbow = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'];
        let count = 1;
        const timer = function () {
            document.querySelector('div').innerHTML = String(count);
            document.querySelector('div').style.color = rainbow[count % rainbow.length];
            count++;
        };

        let id = setInterval(timer, 1000);

        const stopTimer = function () {
            clearInterval(id);
        };

        const reStart = function () {
            id = setInterval(timer, 1000);
        };
    </script>
</head>
<body>
    <div id="numb">0</div>
    <div id="box">
        <button onclick="stopTimer()">정지</button>
        <button onclick="reStart()">재시작</button>
    </div>
</body>

 

 


2.  기본 매개변수


🐰  매개 변수에 기본 값을 지정, 매개 변수가 들어오지 않는 경우에 기본 값으로 대체
🐰  기본 매개 변수와 일반 매개 변수를 섞어서 사용할 경우에는 기본 매개 변수가 오른쪽으로 가야됨

함수이름(매개변수, 매개변수=기본값, 매개변수=기본값)
<script>

  const earnings = function (name, wage = 8590, hours = 40) {
    console.log(`# ${name}님의 급여 정보`);
    console.log(`- 시급: ${wage}원`);
    console.log(`- 근무 시간: ${hours}시간`);
    console.log(`- 급여: ${wage * hours}원`);
    console.log('');
  }

  // 최저 임금으로 최대한 일하는 경우
  earnings('smith');

  // 시급 1만원으로 최대한 일하는 경우
  earnings('adam', 10000);

  // 시급 1만원으로 52시간 일한 경우
  earnings('tom', 10000, 52);
</script>


응용 문제
<script>
    // 년도를 인수로 전달하지 않은 경우에는 현재 년을 기본값으로 함.
    // 윤년을 확인하는 함수를 정의 - 정수 연도를 입력받아서 윤년의 여부를 불린형으로 반환.
    const isLeapYear = function (year = new Date().getFullYear()) {
        const isLeapYear = (year % 4 === 0) && (year % 100 !== 0) || (year % 400 === 0);
        return isLeapYear;
    }

    console.log(`올해는 윤년일까? === ${isLeapYear()}`); 
</script>

 


3.  즉시 호출 함수  Immediately-invoked function expression

(function () { })();


 🐰  선언과 동시에 함수가 실행되며 보통은 함수명 없이 사용하기 때문에 재호출이 안됨
 🐰  변수의 충돌을 막기 위해 사용. 재사용을 위해서 함수를 만드는게 아닌 변수의 충돌을 막기 위해 블록화를 하는 목적으로 사용

💡  자바 스크립트에서 선언적 함수보다 익명함수를 생성하고 바로 호출하는 패턴이 많은 이유 

 

       -  이름 충돌 방지
       -  다른 프로그램에 비해 자바 스크립트는 라이브러리를 많이 사용하고
           한 페이지에 사용하는 프로그램이 여러 개의 파일로 나누어져 있거나 여러 개로 분리되어 있어서
           다른 프로그래밍 언어보다 이름 충돌되는 경우가 많음
       -  익명함수를 사용해서 이름이 중복되는 함수를 만드는 것을 방지

<!-- 이름 충돌 문제 발생 -->
<!-- 다른 곳에서 가져온 자바스크립트 코드 -->
<script>
    let pi = 3.14;
    console.log(`파이 값은 ${pi}입니다.`);
</script>

<!-- 내가 만든 자바스크립트 코드 -->
<script> // Uncaught SyntaxError: Identifier 'pi' has already been declared
    let pi = 3.141592; // 중복 선언
    console.log(`파이 값은 ${pi}입니다.`);
</script>

<script>
    // 1. 재호출이 안되는 형태
    (function() {
        life();
    })();
    function life() {
        console.log(`즉시 실행 함수1`); // 즉시 실행 함수1
    }

    // 1) 익명함수처럼 보이니까 즉석 실행 함수를 변수에 저장한다면?
    let instant = (function() {
        console.log('즉시 실행 함수2'); // 즉시 실행 함수2
    })();
    console.log(typeof instant); // undefined. 변수에 할당되지는 않고 실행만 됨.
    // instant(); // Uncaught TypeError: instant is not a function

    // 2) 선언적 함수처럼 이름을 지정하면 재실행 되지 않을까?
    (function instant3rd () {
        console.log(`즉시 실행 함수3`);
    })();

    // instant3rd(); // Uncaught ReferenceError: instant3rd is not defined

    // 2. 재실행이 가능한 경우
    let instant4th;
    (instant4th = function() {
        console.log('즉시 실행 함수4'); // 즉시 실행 함수4
    })();
    console.log(typeof instant4th); // function
    instant4th(); // 즉시 실행 함수4
</script>

 

 


스코프 scope : 변수가 존재하는 범위   

 

   -  같은 단계의 스코프에서 동일한 이름의 변수가 있으면 충돌
   -  스코프 단계를 변경하는 방법은 중괄호를 사용해서 블록을 만들거나, 함수를 생성해서 블록을 만듦
   -  블록 내부에서 같은 이름으로 변수를 선언하면 변수가 외부 변수와 충돌하지 않고

       외부 변수를 가려서 내부 블록에서 선언한 변수만 볼 수 있음
   -  블록이 다른 경우 내부 변수가 외부 변수를 가리는 현상을 섀도잉 shadowing 이라고 함

💡  블록({}) 생성으로 이름 충돌 문제를 해결하는 방법은  구 브라우저나, var 키워드 사용하는 경우에는 사용할 수 없어서 대체재로 즉시 호출 함수를 사용
<script>
    let pi = 3.14;
    console.log(`파이 값은 ${pi}입니다.`); // 파이 값은 3.14입니다.

    // 블록을 사용한 스코프 생성
    {
        let pi = 3.141592; // 블록에서 선언한 변수는 블록 안에서만 사용 가능
        console.log(`파이 값은 ${pi}입니다.`); // 파이 값은 3.141592입니다. 블록에서 pi가 선언되지 않았다면 전역을 들고 옴.
    }

    console.log(`파이 값은 ${pi}입니다.`); // 파이 값은 3.14입니다.

    // 함수 블록을 사용한 스코프 생성
    function sample() {
        let pi = 3.141592;
        console.log(`파이 값은 ${pi}입니다.`);
    }
    sample(); // 파이 값은 3.141592입니다.
    console.log(`파이 값은 ${pi}입니다.`); // 파이 값은 3.14입니다.
</script>

 


var 에서 블럭 사용과 즉석 실행 함수
<script>
    var animal = 'dog';
    console.log(animal); // dog

    {
        var animal = 'cat';
        console.log(animal); // cat
    }
    console.log(animal); // cat. 블록에서 사용했지만 블록 밖에서 변수 사용이 됨

    var animal = 'dog';
    console.log(animal); // dog
    (function () {
        var animal = 'cat';
        console.log(animal); // cat
    })();

    console.log(animal); // dog. 즉시 호출 함수의 경우에는 함수 블럭 안에서만 변수의 범위가 제한 됨.
</script>

 


블록 사용으로 이름 충돌을 막을 수 없는 경우 즉시 호출 함수 사용
<!-- 다른 곳에서 가져온 자바스크립트 코드 -->
<script>
    let pi = 3.14;
    console.log(`파이 값은 ${pi}입니다.`); // 파이 값은 3.14입니다.
</script>

<!-- 내가 만든 자바스크립트 코드 -->
<script>
    /* 즉시 호출 함수를 사용해 변수 이름 충돌 문제를 해결 */
    (function () {
        let pi = 3.141592;
        console.log(`파이 값은 ${pi}입니다.`); // 파이 값은 3.141592입니다.
    })();
</script>

 


4.  엄격 모드  strict mode

🐰  'use strict' 문자열을 읽은 후 부터는 코드를 엄격하게 검사
🐰  초기의 자바 스크립트는 간단한 보조 프로그램을 만드는게 목적이라 어느 정도 오류가 있어도 정상적으로 작동.
      하지만 이후에 자바 스크립트의 사용이 활발해 지고, 규모가 있는 프로그램을 만들기 위해서는 코드의 오류를 엄격하게 검사를 해야돼서 엄격 모드 사용

      🥕  즉시 호출 함수를 만들고, 이 블록의 가장 윗쪽에 엄격 모드를 적용하는 경우가 많음
              ▶️  이렇게 하면 해당 블록 내부에서만 엄격 모드가 적용
 

 사용예:
    (function () {
        'use strict';
        문장;
        문장
     }) ();
<script>
    /* 변수를 선언하지 않아도 사용이 됨. */
    data = 10;
    console.log(data); // 10
</script>
<script>
    'use strict';
    data = 10; // Unresolved variable or type data
    console.log(data); // 10
</script>

 

 

 

 

[ 내용 참고 : IT 학원 강의 및 책 'Do it HTML+CSS+자바스크립트 웹 표준의 정석' ]


1.  재귀 함수

🐰  함수 정의문 내에서 작성한 코드로 함수를 다시 호출하는 것

<script>
    let num = 0;
    function testFnc() {
        // 재귀 함수 호출을 적용하여 1부터 10까지의 값을 출력
        num++;
        document.write(num, '<br>');

        if(num === 10) return; // num 값이 10이면 종료

        console.log(`${num} 번째 호출`); // 10번째는 출력 안됨
        testFnc(); // 재귀 함수 호출
    }
    testFnc();
</script>


2.  콜백 함수  callback function

🐰  매개 변수로 전달하는 함수. 자바 스크립트는 함수도 하나의 자료형이므로 매개변수로 전달 할 수 있음

🐰  매개변수를 통해 함수를 받고, 그 함수를 통해 결과값을 호출함

<script>
    function callThreeTimes (callback) { // 함수를 선언
        for (let i = 0; i < 3; i++) {
            callback(i);
        }
    }

    function print(i) {
        console.log(`${i}번째 함수 호출`);
    }

    // 함수를 호출.
    callThreeTimes(print); // 매개변수로 함수를 전달. 함수를 매개변수로 사용할 경우 ()는 제외
    /* 0번째 함수 호출
    1번째 함수 호출
    2번째 함수 호출
     */
</script>

 


 콜백함수와 익명함수 
<script>
    function callThreeTimes (callback) { // 함수를 선언
        for (let i = 0; i < 3; i++) {
            callback(i);
        }
    }

    // 함수를 호출. 다른 언어에서는 낯선 방법이나 자바 스크립트나 코틀린 같은 이벤트 기반을 프로그래밍에서는 자주 사용.
    callThreeTimes(function (i) {
        console.log(`${i}번째 함수 호출`);
    });
</script>

 


콜백함수를 활용하는 함수 : forEach() 메서드


    🥕  배열이 갖고 있는 함수(메서드)로써 단순하게 배열 내부 요소를 사용해서 콜백함수를 호출

/* 콜백함수 기본형 */
function (value, index, array) { } //  매개 변수가 다 필요하지 않음.
<script>
    const numbers = [273, 52, 103, 32, 57];

    numbers.forEach(function (value, index, array) {
        // 매개변수로 value, index, array를 갖는 콜백함수를 사용
        console.log(`${index}번째 요소 : ${value}`);
    });

    // 함수 선언한 후에 매개 변수로 넘겨도 됨
    const call = function (value, index, array) {
        // 매개변수로 value, index, array를 갖는 콜백함수를 사용
        console.log(`${index}번째 요소 : ${value}`);
    }
    numbers.forEach(call);

    numbers.forEach(function (v, i) { // 매개변수로 v, i만 사용
        console.log(`${i}번째 요소 : ${v}`);
    })

    numbers.forEach(function(item) { // 매개변수로 v만 사용
        console.log(`${item}`)
    })
</script>

 


콜백함수를 활용하는 함수 : map() 메서드

 

   🥕  콜백함수에서 리턴한 값들을 기반으로 새로운 배열을 만들고 리턴

<script>
    // 배열을 선언
    let numbers = [273, 52, 103, 32, 57];

    // 배열의 모든 값을 제곱
    let numbers2 = numbers.map(function (value, index, array) {
        return value * value;
    });
    console.log(numbers2); // (5) [74529, 2704, 10609, 1024, 3249]

    // 출력
    numbers2.forEach(console.log); // value, index, array 순서대로 출력
    /*
    74529 0 (5) [74529, 2704, 10609, 1024, 3249]
    2704 1 (5) [74529, 2704, 10609, 1024, 3249]
    10609 2 (5) [74529, 2704, 10609, 1024, 3249]
    1024 3 (5) [74529, 2704, 10609, 1024, 3249]
    3249 4 (5) [74529, 2704, 10609, 1024, 3249]
     */

    // for문을 이용해서 제곱 배열 생성
    let numbers3 = [];
    for (const item of numbers) {
        numbers3.push(item * item);
    }
    console.log(numbers3); // (5) [74529, 2704, 10609, 1024, 3249]
</script>

 


콜백함수를 활용하는 함수: filter()


    🥕  콜백함수에서 리턴하는 값이 true인 것들만 모아서 새로운 배열을 만듦
           ➡️  콜백함수의 리턴 타입이 불 형 이어야 함

<script>
    const numbers = [11, 12, 13, 14, 15, 16];
    
    // 짝수만 추출
    const evenNumbers = numbers.filter(function (value) {
        return value % 2 === 0;
    });

    // 인덱스가 짝수만 추출
    const evenIndexs = numbers.filter(function (value, index) {
       return index % 2 === 0;
    });

    console.log(`원래 배열: ${numbers}`); // 원래 배열: 11,12,13,14,15,16
    console.log(`값이 짝수만 추출: ${evenNumbers}`); // 값이 짝수만 추출: 12,14,16
    console.log(`인덱스가 짝수만 추출: ${evenIndexs}`);  // 인덱스가 짝수만 추출: 11,13,15

    // 1의 자리가 3의 배수인 경우만 추출
    const evenNumbers2 = numbers.filter(function (value) {
        return (value % 10) % 3 === 0;
    });

    console.log(`1의 자리가 3의 배수: ${evenNumbers2}`); // 1의 자리가 3의 배수: 13,16
</script>

 


3.  화살표 함수  Arrow function


🐰  ES6에 추가된 내용으로 '=>'를 이용하여 함수를 간결하게 표현할 때 사용

    1) function 키워드를 생략
    2) 부등호 '='과 '>'를 합쳐서 코딩
    3) 항상 익명함수 형식으로 표현
    4) 단일 명령문일 경우 함수의 중괄호 {}와 return을 생략

 

 

Arrow function expressions - JavaScript | MDN

An arrow function expression is a compact alternative to a traditional function expression, with some semantic differences and deliberate limitations in usage:

developer.mozilla.org

<script>
    const doAddition1 = function (s1, s2) {
        return (s1 + s2) / 2;
    }
    console.log(doAddition1(2, 5)); // 3.5

    const doAddition2 = (s1, s2) => {
        return (s1 + s2) / 2;
    }
    console.log(doAddition2(2, 5)); // 3.5

    const doAddition3 = (s1, s2) => (s1 + s2) / 2;
    console.log(doAddition3(2, 5)); // 3.5
</script>


🐰  map(), filter() 함수처럼 단순한 형태의 콜백 함수를 쉽게 입력
🐰  function 키워드 대신 화살표(=>)를 사용

/* 기본형 */ 
(매개변수) => { }

 

💡  메소드 체이닝 : 메소드가 리턴하는 값을 기반으로 해서 메서드를 줄줄이 사용하는 것
<script>
    // 배열 선언
    let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

    // numbers에서 2의 배수만 추출한 후, 제곱을 한 후에 로그에 출력.

    // 배열의 메소드를 연속적으로 사용. 메소드 체이닝.
    numbers.filter((value) => value % 2 === 0) // 2의 배수만 추출 / [0, 2, 4, 6, 8]
        .map((value) => value * value) // 제곱 추출 / [0 , 4, 6, 16, 36, 64]
        .forEach((value) => console.log(value)); // [0, 4, 16, 36, 64]
</script>

 

 

 

 

[ 내용 참고 : IT 학원 강의 ]

 


1.  나머지 매개변수  rest parameter

👩🏻‍💻  가변 매개변수 함수 : 호출할 때 매개변수의 갯수가 고정적이지 않은 함수
👩🏻‍💻  자바스크립트에서는 이러한 함수를 구현할 때 '나머지 매개 변수'를 사용
👩🏻‍💻  함수의 매개변수 앞에 마침표 3개(...)를 입력하면 매개변수가 배열로 들어옴

/* 기본형 */
function 함수명 (...items) {}
<script>
    function sample(...items) {
        console.log(items);
    }

    sample(1, 2); // [1, 2]
    sample(1, 2, 3); // [1, 2, 3]
    sample(1, 2, 3, 4); // [1, 2, 3, 4]

    function sample2nd(items) {
        console.log(items);
    }
    sample2nd([1,2]); // [1,2]
    sample2nd([1,2, 3]); // [1,2,3]
    sample2nd([1,2, 3, 4]); // [1,2,3,4]
</script>

 


  (1)  나머지 매개 변수와 일반 매개변수 조합하기

/* 기본형 */
function 함수명 (매개변수, 매개변수, ...나머지 매개변수) {}
<script>
    function sample(a, b, ...c) {
        console.log(a, b, c);
    }

    // 매개변수 a, b가 먼저 들어가고, 남은 것은 모두 c에 배열 형태로 들어감
    sample(1, 2); // 1 2 []
    sample(1, 2, 3); // 1 2 [3]
    sample(1, 2, 3, 4); // 1 2 [3, 4]
</script>

 

 

매개변수의 자료형에 따라 다르게 작동하는 함수 만들기

  <조건>
    1)  min(배열) : 매개 변수에 배열을 넣으면 배열 내부에서 최솟값을 찾아주는 함수
    2) min(숫자, 숫자) : 매개변수에 숫자를 넣으면 숫자들 중 최솟값을 찾아주는 함수
<script>
    function min(first, ...rests) {
        /*
        min(배열) 방식의 호출인 경우 first에는 배열이, ...rest에는 아무 값도 넘어오지 않음
        min(숫자, 숫자) 방식의 호출인 경우 first에는 첫번째 인수가, ...rests에는 두번째 인수부터 나머지가 배열로 들어옴.
         */

        // 변수 선언하기
        let min; // 최솟값을 저장할 공간
        let items; // 배열

        // 매개변수의 자료형에 따라 조건 분리하기
        if (Array.isArray(first)) { // first에 있는 변수가 배열인지 확인. 배열이면 나머지 매개변수가 없음
            min = first[0];
            items = first; // [52, 273, 32, 103, 275, 24, 57]
        } else if (typeof(first) === 'number') {
            min = first; // 52
            items = rests; // [273, 32, 103, 275, 24, 57]
        }


        // 최솟값 구하는 공식
        for (const item of items) {
            if (min > item) {
                min = item;
            }
        }
        return min;
    }

    console.log(`min(배열): ${min(52, 273, 32, 103, 275, 24, 57)}`); // 24
    console.log(`min(숫자, ...): ${min(52, 273, 32, 103, 275, 24, 57)}`); // 24
</script>

 


2.  전개 연산자  spread operator

👩🏻‍💻  배열을 전개해서 함수의 매개 변수로 전달  ▶️  배열 안의 요소 하나 하나 출력함  
👩🏻‍💻  전개 연산자는 일반적으로 함수 호출시 배열 앞에 마침표 3개(...)를 붙이는 형태로 사용

/* 기본형: 함수 호출시 */
함수이름(...배열)

 

 

(1)  기본적인 전개 연산자 사용법

인수로 전달
<script>
    'use strict';

    const array = [1, 2, 3, 4];

    function sample1st(a, b, c, d) {
        console.log('sample1st() 실행');
        console.log(a, b, c, d);
    }
    // 전개 연산자를 이용해서 배열을 인수로 전달.
    // 배열은 개개로 전개해서 전달한 것과 결과가 같음
    sample1st(...array);
    sample1st(array[0], array[1], array[2], array[3]);
</script>


함수의 리턴 값 배열로 하고 결과 값을 전개 할당
<script>
    function sample2nd() {
        console.log('sample2nd() 실행');
        let array = [1, 2, 3, 4];
        return array;
    }

    console.log(sample2nd()); // [1, 2, 3, 4]. 결과값은 배열
    // sample2nd() 호출 결과를 각각 변수에 저장하려면?
    //let arrayNew = sample2nd();
    //let a = arrayNew[0];
    //let b = arrayNew[1];
    //let c = arrayNew[2];
    //let d = arrayNew[3];
    let [a, b, c, d] = sample2nd(); // 배열을 각 변수에 할당
    console.log(a); // 1
</script>

 


(2)  나머지 매개 변수와 함께 사용하는 경우

<script>
    const array = [1, 2, 3, 4];
    
    function sample3rd(...items) { // 단순하게 매개변수를 모두 출력하는 함수
        document.write('<br>sample3rd() 실행<br>');
        document.write(items, '<br>');
        for (const item of items) {
            document.write(item, '<br>');
        }
    }

    console.log('# 전개 연산자를 사용하지 않은 경우');
    sample3rd(array); // 배열의 요소로 배열을 가진 매개변수가 됨. [[1,2,3,4]]
    console.log('# 전개 연산자를 사용한 경우');
    sample3rd(...array); // 숫자 하나하나가 전개되어서 들어옴. 배열의 요소가 4개인 매개변수가 됨.
    // [1,2,3,4]
</script>


(3)  일반 매개 변수에 전개 연산자 사용

<script>
    const array = [1, 2, 3, 4];

    function sample4th(items) {
        document.write('<br>sample4th() 실행<br>');
        document.write(items, '<br>');
        for (const item of items) {
            document.write(item, '<br>');
        }
    }
    // 전개 되어서 전달이 됨. sample4th(1, 2, 3, 4)과 동일한 결과.
    // items에 1만 전달이 되고, 배열이 아니기 때문에 for문으로 순회가 안됨
    sample4th(array);
    sample4th(...array); 
    // 1. Uncaught TypeError: items is not iterable at sample4th()
    sample4th(array[0], array[1], array[2], array[3]);
    // 1. Uncaught TypeError: items is not iterable at sample4th()
</script>

 

 

 

 

[ 내용 참고 : IT 학원 강의 ]

+ Recent posts