Learn & Record

HTML CSS JS (기본매개변수, 스코프, 즉시실행함수, 내부함수, 버튼+함수, 이벤트핸들러, 프로퍼티 방식, 메서드 방식) 본문

Dev/HTML CSS JS

HTML CSS JS (기본매개변수, 스코프, 즉시실행함수, 내부함수, 버튼+함수, 이벤트핸들러, 프로퍼티 방식, 메서드 방식)

Walker_ 2024. 4. 1. 17:09

1. 기본 매개변수

 - 매개 변수에 기본 값을 지정. 매개 변수가 들어오지 않는 경우에 기본 값으로 대체

 - 기본 매개 변수와 일반 매개 변수를 섞어서 사용할 경우에는 기본 매개 변수가 오른쪽으로 가야됨

<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('edam', 10000)

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

 

<script>

    // 올해 연도
    const now = new Date();
    const thisYear = Number(now.getFullYear());// 올해 연도를 저장할 수 있는 변수

    // 윤년 함수
    const isLeapYear = function (year) {
        const isLeapYear = (year % 4 == 0) && (year % 100 !== 0) || (year % 400 === 0);
        return isLeapYear;
    }

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

 

2. 이름 충돌 문제

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

 - 다른 프로그램에 비해 자바 스크립트는

 - 1) 라이브러리를 많이 사용하고

 - 2) 한 페이지에 사용하는 프로그램이 여러개의 파일로 나누어져 있거나 여러개로 분리되어 있어서

 - 다른 프로그래밍 언어보다 이름 충돌되는 경우가 많음

 - 익명함수를 사용해서 이름이 중복되는 함수를 만드는 것을 방지하게 됨

/* 이름 충돌 문제 발생 */
/* 다른 곳에서 가져온 자바스크립트 코드 */

 

3. 스코프 scope 

 - 변수가 존재하는 범위

 - 같은 단계의 스코프에서 동일한 이름의 변수가 있으면 충돌

 - 스코프 단계를 변경하는 중괄호를 사용해서 블록을 만들거나, 함수를 생성해서 블록을 만듬

 - 블록 내부에서 같은 이름으로 변수를 선언하면 변수가 외부 변수와 충돌하지 않고 외부 변수를 가려서 내부 블록에서 선언한 변수만 볼 수 있음

 - 블록이 다른 경우 내부 변수가 외부 변수를 가리는 현상을 섀도잉 shadowing 이라고함

 

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

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

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

// 함수 블록을 사용한 스코프 생성
function sample() {
    let pi = 314192 // 블록에서 선언한 변수는 블록안에서만 사용 가능
    console.log(`파이 값은 ${pi} 입니다.`)
}
sample(); // 파이 값은 3.154192

 

 

 4. 즉시 실행 함수

// 1. 재호출이 안되는 형태
(function () {
    life();
})();
function life() {
    console.log('즉시 실행 함수1'); // 즉시 실행 취소
}
// 1) 익명함수처럼 보이니까 즉석 실행 함수를 변수에 저장한다면?
let instant = (function () {
    console.log('즉시 실행 함수2') // 즉시 실행 함수 2
})();

console.log(typeof instant); // undefined. 변수에 할당되지는 않고 실행만 됨
instant(); // 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');
})();
console.log(typeof instant4th); // function
instant4th();

 

 

5. 엄격 모드 strict mode

 - 'use stirct' 문자열을 읽은 후 부터는 코드를 엄격하게 검사

 - 초기의 자바 스크립트는 간단한 보조 프로그램을 만드는 게 목적이라 어느 정도 오류가 있어도 정상적으로 작동

 - 하지만 이후에 자바 스크립트의 사용이 활발해지고,

 - 규모가 있는 프로그램을 만들기 위해서는 코드의 오류를 엄격하게 검사를 해야되서 엄격 모드 사용

 

 - 즉시 호출 함수를 만들고, 이 블록의 가장 윗쪽에 엄격 모드를 적용하는 경우가 많음

 - 이렇게 되면 해당 블록 내부에서만 엄격 모드가 적용

 - 사용예 : 

 - (function() {

             'use strict';

              문장;

               문장;

    })();

<script>
    'use strict';
    data = 10;
    console.log(data);
</script>

 

6. 내부 함수 

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
  <script>
    const changeColor = (function () {
      let i = 0;
      console.log(i)
      const color = ['white', 'yellow', 'aqua', 'purple']; // 배열 선언
      const exec = function() {
        const bodyTag = document.querySelector('body'); // body 태그를 불러옴
        bodyTag.style.backgroundColor = color[++i%color.length]; // body 태그의 backgroud-color를 변경
      }
      return exec
    })();
  </script>
</head>
<body>
<!-- 버튼을 클릭하면 changeColor() 함수 호출 -->
<button onclick="changeColor();">배경색 바꾸기</button>

</body>
</html>

 

7. 버튼 + 함수

<body>
    <button>Click me!</button>
    
    <!-- document.quetySelector() 전에 해당 html 요소가 있어야 자바 스크립트가 제대로 동작. -->
    <script>
        const myButton = document.querySelector('button')
        console.log(myButton)
        // 사용자가 버튼을 클릭하면 함수를 호출하도록 요청
        myButton.onclick = () => { alert("button click");};
    </script>
</body>

 

8. 이벤트 핸들러

 - 이벤트 : 사이트에서 방문자가 취하는 모든 행위

 - 이벤트 핸들러 : 이벤트가 발생했을 때 실행되는 코드

 

 - 이벤트 핸들러 등록 종류

 - 1. 이벤트 핸들러 어트리뷰트 방식

 - 이벤트 핸들러 어트리뷰트의 이름은 onclick과 같이 on 접두사와 이벤트의 종류를 나타내는 이벤트 타입으로 이루어짐

 - 주의할 점은 이벤트 핸들러 어트리뷰트 값으로 함수 참조가 아닌 함수 호출문 등의 문을 할당

 - 이때 '이벤트 핸들러 어트리뷰트 같은 사실 암묵적으로 생성될 이벤트 핸들러의 함수 몸체를 의미'.

 

 - 하지만 HTML과 자바 스크립트는 관심사가 다르므로 혼재하는 것보다 분리하는 것이 좋음

<body>
    <button onclick="sayHi('Lee')">Click me!</button>
    <script>
        function sayHi(name) {
            console.log(`Hi! ${name}`)
        }
    </script>
</body>

 

 - 2) 이벤트 핸들러 프로퍼티 방식

 - window 객체와 Document, HTMLElement 타입의 DOM 노드 객체는 이벤트에 대응하는 이벤트 핸들러 '프로퍼티' 가짐

 - 이벤트 핸들러 프로퍼티의 키는 이벤트 핸들러 '어트리뷰트'와 마찬가지로 onclick과 같이

 - on 접두사와 이벤트의 종류를 나타내는 이벤트 타입으로 이루어져 있음

 - 이벤트 핸들러 프로퍼티 방식은 이벤트 핸들러 어트리뷰트 방식의 HTML과 자바 스크립트가 뒤섞이는 문제를 해결가능

 

 - 하지만 이벤트 핸들러 프로퍼티에 하나의 이벤트 핸들러만 바인딩 할 수 있다는 단점이 있음

<body>
    <button>Click me!</button>
    <script>
        const btn = document.querySelector('button')
        console.log(typeof btn)
        // 이벤트 핸들러 프로퍼티에 이벤트 핸들러 바인딩
        btn.onclick = function () {
            console.log('button click');
        };
    </script>
</body>

 

 - 이벤트 핸들러 프로퍼티 방식은 하나의 이벤트에 하나의 이벤트 핸들러만 바인딩 할 수 있음

 - 첫 번째로 바인딩된 이벤트 핸들러는 두 번째 바인딩된 이벤트 핸들러에 의해 재할당되어 실행되지 않음

 

<body>
    <button>Click me!</button>
    <script>
        const btn = document.querySelector('button')
        console.log(typeof btn)
        // 이벤트 핸들러 프로퍼티에 이벤트 핸들러 바인딩
        btn.onclick = function () {
            console.log('button click 1');
        };
        btn.onclick = function () {
            console.log('button click 2');
        };
    </script>
</body>

 

 - 3) addEventListener 메서드 방식

 - DOM Level 2에서 도입된 Event.prototype.addEventListener 메서드를 사용하여 이벤트 핸들러를 등록할 수 있음

 - 앞서 살펴본 '이벤트 핸들러 어트리뷰트 방식'과 '이벤트 핸들러 프로퍼티 방식'은 DOM Level 0부터 제공되던 방식

<body>
    <button>Click me!</button>
    <script>
        const btn = document.querySelector('button')
        /*
        addEventListener 메서드의 첫 번째 매개변수에는 이벤트의 종류를 나타내는 문자열인 이벤트 타입을 전달.
        이때 이벤트 핸들러 프로퍼티 방식과는 달리 on 접두사를 붙이지 않음
        두 번째 매개변수에는 이벤트 핸들러를 전달
         */
        btn.addEventListener('click', function () {
            console.log('button click');
        });
    </script>
</body>
function btnClick() {
    console.log('button click');
}
btn.addEventListener('click', btnClick);

 

 - 이벤트 핸들러 프로퍼티 방식과 addEventListener 메서드 방식을 모두 사용하여 이벤트 핸들러를 등록하면?

 - addEventListener 메서드 방식은 이벤트 핸들러 프로퍼티에 바인딩된 이벤트 핸들러에 아무 영향을 주지 않음

 - 따라서 버튼 요소에서 클릭 이벤트가 발생하면 2개의 이벤트 핸들러가 모두 호출

 

<body>
    <button>Click me!</button>
    <script>
        const btn = document.querySelector('button')

        btn.onclick = function () {
            console.log('[이벤트 핸들러 프로퍼티 방식] button click');
        };

        btn.addEventListener('click', function () {
            console.log('[addEventListener 메서드 방식] button click');
        });
    </script>
</body>

 

 


공부 과정을 정리한 것이라 내용이 부족할 수 있습니다.

부족한 내용은 추가 자료들로 보충해주시면 좋을 것 같습니다.

읽어주셔서 감사합니다 :)