HTML/CSS/Javascript

[Do it! HTML+CSS+자바스크립트 웹 표준의 정석] 15

EunaSon 2023. 8. 13. 14:17

15-1 함수와 이벤트

함수

처리해야할 명령들을 묶어놓은 것.

 

두 수를 더해서 알람창으로 보여주기 위한 명령들

var num1 = 2;

var num2 - 3;

var sum = num1 + num2;

alert("결과값 : " + sum);

 

이를 함수로 묶어서 나타내보자

function addNumber() {

  var num1 = 2;

  var num2 - 3;

  var sum = num1 + num2;

  alert("결과값 : " + sum);

}

addNumber();

 

함수의 시작과 끝이 명확해짐

정의된 함수의 이름을 호출하여 언제든 사용할 수 있음.

 

[기본형]

function 함수이름(매개변수) {

  수행할 명령들

}

 

var과 let

let는 ES6(ECMAScript6, 자바스크립트 표준화 6버전) 이후에 나온 예약어임.

var로 선언한 변수와 let로 선언한 변수에 어떤 차이가 있는지 알아보자

 

var 변수의 특징

변수가 유효한 범위를 scope라 함

함수 addNumber에서 sum이라는 변수가 var을 통해 선언되었음

-> sum이 유효한 범위는 이 함수 안으로 국한됨 = 지역변수

=> 함수 밖에서는 sum을 사용할 수 없음

 

따라서 함수 밖에서도 변수를 사용하기 위해서는 sum을 전역변수로 선언해주어야함

함수 안에서 var을 빼고 함수를 선언하거나,

var을 붙이려면 함수 밖에서 선언해주어야 함

 

-var의 단점

1. 만약 실수로 함수안에서 지역변수로 사용할 변수에 var을 사용하지 않아 전역변수가 되어

함수 밖에서 이 변수를 조작하여 의도치않게 값을 바꾸게 될 수도 있음

 

2. var을 통해 정의한 변수는 지역변수이므로 함수 밖에서 같은 이름으로 다시 변수를 선언하고 값을 할당할 수 있음(변수 재선언 가능)

 

3. 호이스팅(= 끌어올린다는 뜻) 의 문제

var x = 10;

function displayNumber() {

  console.log("x is " + x);

  console.log("y is " + y);

  var y = 20;

}

이를 실행시키면, 오류가 나는 것이 아니라 예상치못하게 y가 undefined로 표시되는 문제가 발생함

이는 var y = 20이 처리되는 방식에 의한 것이다

 

var x = 10;

var y;

function displayNumber() {

  console.log("x is " + x);

  console.log("y is " + y);

  y = 20;

}

 

var y 가 위에서 선언되었고, 뒤에서 할당했다고 인식하기 때문임.

이것이 호이스팅의 개념임

이는 변수에만 국한되는 개념이 아니라 함수에도 적용됨

 

호이스팅으로 인해 함수의 정의는 뒤에 몰아놓고, 앞에서 사용하는 것이 가능함

 

따라서 es6에서는 var 보다 let 사용을 추천함

 

let 변수의 특징

let으로 선언한 블록 변수라고 함

scope가 블록에 국한됨

 

function calcSum(n) {

  let sum = 0;

  for (let i = 1; i < n+1; i++) {

    sum += i;

  }

  console.log(sum);

}

calcSum(10);

 

for문 안에서 선언된 i는 for문을 벗어나면 사용할 수 없음

calcSum 함수 안에서 선언된 sum은 함수를 벗어나면 사용할 수 없음

 

만약 sum을 전역변수로 사용하고 싶으면 let이든 var이든 빼고 선언하면 됨

차이가 있다면, let으로 선언한 변수는 재할당이 안됨

 

function calcSum(n) {

  let sum = 0;

  for (let i = 1; i < n+1; i++) {

    sum += i;

  }

  console.log(sum);

  sum = 100; // sum에 값을 할당

  console.log(sum); // 콘솔창에 할당한 값인 100이 뜸

  let sum; // 식별자 sum이 이미 선언되었다는 오류가 발생함

}

calcSum(10);

 

var을 사용했을 때는 똑같은 이름의 변수를 다시 선언할 수 있었지만(변수의 재선언 가능)

let을 사용할때는 오류가 발생하게 됨(변수 재선언 불가)

 

마찬가지로 let으로 선언한 변수는 호이스팅되지 않음

var x = 10;

function displayNumber() {

  console.log("x is " + x);

  console.log("y is " + y);

  let y = 20;

}

var로 선언한 y는 호이스팅 되어 선언 전 호출해도 오류가 발생하지 않았지만

let을 사용한 경우, 초기화되기 전에 y에 접근할 수없다는 오류가 발생


15-2 함수와 이벤트

입력을 바꿔서 여러 번 사용할 수 있는 성질을 함수의 재사용성이라 함

함수를 재사용할 수 있게 만들려면?

 

매개변수와 인수, return문

15-1에서 addNumber()의 경우, 2와 3의 합만 볼 수 있었지만 조금만 수정하면 다른 수들의 합도 알수있게 만들 수 있다

이렇게 재사용할 수 있는 함수를 만들려면 함수 외부에서 입력값을 받아줄 수 있는 장치가 필요함. 이를 매개변수라고 한다. 함수의 괄호 안에 매개변수를 써주면 됨. 매개변수를 여러개 사용시에는 콤마로 구분함.

 

정해진 두 수의 합만 알 수 있는 함수 - 항상 결과값이 같음. num1과 num2가 함수 안에 고정되어있기 때문

<script>
    function addNumber() {
    	var num1 = 2;
        var num2 = 3;
        var sum = num1 + num2;
  
        alert("결과값 : " + sum);
    }
</script>

 

매개변수를 사용 - 인수로 넣어주는 값에 따라 다른 결과를 얻을 수 있음.  

<script>
    function addNumber(num1, num2) {
    	var sum = num1 + num2;
        return sum;
    }
</script>

함수안의 num1과 num2를 매개변수로 지정, 외부에서 받아서 합을 return함

return은 함수의 결과값을 호출한 곳으로 돌려줌

 

var result = addNumber(2,3);

-> addNumber()의 인수로 2, 3을 사용,

-> 결과값 5는 sum에 저장되고, 이는 addNumber(2, 3)을 호출한 그 위치로 반환

=> 따라서 var result = 5 가 됨

 

이후 addNumber() 의 인수로 20, 30을 사용할 수도 있고 ,100, 200을 줄 수도 있음. 이것이 함수의 재사용성임

 

즉시 실행 함수

앞의 addNumber() 예제는 함수의 정의와 실행 부분이 따로 였음

but 한번만 실행할 함수라면 굳이 따로 정의해서 실행할 필요 없이 정의하면서 동시에 실행할 수 있음. 이를 즉시 실행 함수라 함.

즉시실행함수는 함수를 정의하는 부분에서 함수 이름 부분만 빠진다고 생각하면 됨

 

예) 프롬프트창을 이용해 사용자에게 이름을 입력받고, 그를 이용해 인삿말을 남겨보자

<script>
    (function (){
    	var userName = prompt("이름을 입력하세요");
        document.write("안녕하세요? " + userName + "님!");
    }()); // 매개변수 필요하지 않음, 매개변수 필요하면 인수값 여기 괄호에 넣어줌
</script>

즉시실행함수 전체를 소괄호() 로 묶어줌

해당 함수는 매개변수가 필요하지 않아 빈괄호로 두었음

 

예) 이번에는 매개변수가 있는 경우. addNumber()를 다시 만들어보자.

<script>
    (function(num1, num2){
    	sum = num1 + num2; // 전역변수로 쓰기 위해 sum에 let이나 var 쓰지 않았음
    }(10, 20));
    document.write("실행 결과 : " + sum);
</script>

 

익명함수

함수의 이름이 없는 함수. 즉시실행함수도 익명함수의 일종임.

1. 즉시실행함수로 만들어서 사용할 수도 있고, 2. 함수를 변수에 할당한 수 변수를 사용해 실행할 수도 있음

후자의 방법에 대해 알아보자

<script>
    var hi = function() {
    	alert("안녕하세요?");
    }
    
    hi(); // 웹브라우저에서 alert창이 뜨는 것을 확인할 수 있음
</script>

이는 함수를 변수 hi에 집어넣은 것

항상 고정된 값이 나타나므로 hi를 var이 아니라 const로 지정할 수도 있음

const는 상수를 나타내는 예약어임

 

es6에 와서는 편의를 위해 화살표 기호를 사용한 화살표함수를 사용할 수 있게 되었음

<script>
    //  const hi = function() {
    // 	    alert("안녕하세요?");
    //	}

    const hi = () => { alert("안녕하세요?"); };
    
    hi;
</script>

해당 함수는 매개변수가 없으므로 빈괄호 () 로 두고,

화살표 => 입력,

{ } 안에 실행할 명령을 넣어주고 세미콜론 붙임

 

화살표 함수는 화살표를 기준으로 왼쪽에는 매개변수, 오른쪽에는 실행하려는 명령을 넣어줌

실행할 명령이 한줄 뿐이라면 중괄호 생략 가능

 

매개변수가 있는 화살표 함수의 예도 살펴보자

<script>
    // let hi = function(user) {
    //     document.write(user + "님, 안녕하세요?");
    // }
    
    let hi = (user) => { document.write(user + "님, 안녕하세요?"); };
    
    hi("경희");
</script>

매개변수가 1개일때  소괄호도 생략 가능함

괄호 가능한 것 모두 생략하면 다음과 같음

let hi = (user) => { document.write(user + "님, 안녕하세요?");};

->

let hi = user => document.write(user + "님, 안녕하세요?");

 

매개변수가 2개인 경우

<script>
    // let sum = function(a,b) {
    //    return a+b;
    // }
    
    let sum = (a,b) => { return a+b };
    
    document.write("두 수의 합 : " + sum(10, 20));
</script>

매개변수 괄호는 매개변수가 2개 이상인 경우 생략할 수 없음

실행할 문장이 한줄이거나, 또는 return문인 경우 괄호 생략 가능

 

화살표 함수를 사용하면 보는바와 같이 코드 줄수가 줄어드는 것을 볼 수 있음


15-3 함수와 이벤트

자바스크립트에서 이벤트를 처리하는 방법에 대해 알아보자

 

이벤트와 이벤트 처리기

이벤트

웹 브라우저나 사용자가 행하는 동작

웹 문서 영역 안에서 이루어지는 동작만 가리킴

주로 마우스나 키보드를 사용할 때, 웹 문서를 불러올 때, 폼에 내용을 입력할 때 발생함

이벤트는 이미 정의되어 있으므로 미리 숙지해놓아야 함

 

- 마우스 이벤트

종류 설명
click 사용자가 html 요소를 클릭할 때 이벤트가 발생함
dbclick 사용자가 html 요소를 더블클릭할 때 이벤트가 발생함
mousedown 사용자가 요소 위에서 마우스 버튼을 눌렀을 때 이벤트가 발생함
mousemove 사용자가 요소 위에서 마우스 포인터를 움직일 때 이벤트가 발생함
mouseover 마우스 포인터가 요소 위로 옮겨질 때 이벤트가 발생함
mouseout 마우스 포인터가 요소를 벗어날 때 이벤트가 발생함
mouseup 사용자가 요소 위에 놓인 마우스 버튼에서 손을 뗄 때 이벤트가 발생함

 

- 키보드 이벤트

종류 설명
keydown 사용자가 키를 누르는 동안 이벤트가 발생함
keypress 사용자가 키를 눌렀을 때 이벤트가 발생함
keyup 사용자가 키에서 손을 뗄 때 이벤트가 발생함

 

- 문서 로딩 이벤트

종류 설명
abort 문서가 완전히 로딩되기 전에 불러오기를 멈췄을 때 이벤트가 발생함
error 문서가 정확히 로딩되지 않았을 때 이벤트가 발생함
load 문서 로딩이 끝나면 이벤트가 발생함
resize 문서 화면 크기가 바뀌었을 때 이벤트가 발생함
scroll 문서 화면이 스크롤되었을 때 이벤트가 발생함
unload 문서에서 벗어날 때 이벤트가 발생함

 

- 폼 이벤트

종류 설명
blur 폼 요소에 포커스를 잃었을 때 이벤트가 발생함
change 목록이나 체크 상태 등이 변경되면 이벤트가 발생함
<input>, <select>, <textarea> 태그에서 사용함
focus 폼 요소에 포커스가 놓였을 때 이벤트가 발생함
<label>, <select>, <textarea>, <button> 태그에서 사용함
reset 폼이 리셋되었을 때 이벤트가 발생함
submit submit 버튼을 클릭했을 때 이벤트가 발생함

 

이벤트 처리기

이벤트가 발생했을 때 이벤트를 처리하는 함수

이벤트 핸들러(event handler)라고도 함

 

이벤트(작은 이미지 클릭) = 실행 => 이벤트 처리기(큰 이미지 표시)

 

이벤트가 발생한 html 태그에 이벤트 처리기를 직접 연결

[기본형] <태그 on이벤트명 = "함수명">

 

예) 버튼을 클릭하면 알림 창 표시하기

<body>
    <ul> // 순서없는 목록 생성, 가로로 배치해 버튼처럼 만듬, 클릭 이벤트 처리
    	<li><a href="#" onclick="alert('버튼을 클릭했습니다')">Green</a></li>
    	<li><a href="#" onclick="alert('버튼을 클릭했습니다')">Orange</a></li>
    	<li><a href="#" onclick="alert('버튼을 클릭했습니다')">Purple</a></li>
    </ul>
</body>

버튼처럼 만들어진 링크를 클릭했을 때, 알림창이 나타나도록 할것이므로

a 태그 안에 클릭(click) 이벤트를 처리하도록 onclick을 써주고,

큰따옴표 " " 안에 함수명을 써주는데, 여기서는 함수를 이용하지 않고 바로 alert문을 써주도록 하자.

onclick 이벤트를 처리할 문장들(이벤트 처리기)을 이미 큰따옴표로 묶었기 때문에

alert() 안에 써줄 문장은 큰따옴표가 아닌 작은따옴표로 묶어주어야 함! 

 

예) 클릭했을 때 함수를 연결하기

<body>
    <ul>
    	<li><a href=#" onclick="changeBg('green')">Green</a></li>
        <li><a href=#" onclick="changeBg('orange')">Orange</a></li>
        <li><a href=#" onclick="changeBg('purple')">Pruple</a></li>
    </ul>
    
    <script>
    	function changeBg(color) {
            var result = document.querySelector('#result');
            result.style.backgroundColor = color;
        }
    </script>
</body>

 

태그 안에 이벤트와 함수명까지 같이 들어가있음

이벤트를 처리하기 위해 태그와 이벤트 관련 소스가 섞여있기 때문에(마크업과 스크립트가 분리되지 않음)

이후 이벤트 처리 함수가 바뀌는 등의 일이 생기면 일일이 찾아다녀야 하므로 유지관리가 어려움

=> 소스가 짧을때는 태그안에 이벤트를 처리하지만, 소스가 길어지게되면 자바스크립트 소스 안에서 html 요소를 가져다 사용하는 방법을 사용(17장 개념인 DOM을 이용함)

 

DOM을 이용한 방법 - 마크업과 스크립트를 분리

예) 글자색 바꾸기 버튼을 클릭 시 본문 글자의 색깔이 바뀜

 

방법 1. 웹 요소를 변수로 지정하고 미리 만들어둔 함수를 사용함

: 해당 태그(<button>)에 id값을 주고(#change), 자바스크립트에서는 이 id를 가져와 변수(changeBttn)에 저장하고, 이후 해당 요소에 이벤트(click)가 발생하면 특정 함수(changeColor)를 실행함

<body>
    <button id="change">글자색 바꾸기</button>
    <p>abcdefghijklmnopqrstuvwxyz</p>
    
    <script>
    	// 방법 1 : 웹 요소를 변수로 지정 & 미리 만든 함수를 사용함
    	var changeBttn = document.querySelector("#change");
        changeBttn.onclick = changeColor;
        
        function changeColor() {
            document.querySelector("p").style.color = "#f00";
        }
    </script>
</body>

 

방법 2. 웹 요소를 따로 변수로 만들지 않고 사용

: 방법 1과 비교했을때, 변수를 따로 지정하지 않는다는 차이만 있음. 코드가 좀더 짧아짐.

<body>
    <button id="change">글자색 바꾸기</button>
    <p>abcdefghijklmnopqrstuvwxyz</p>
    
    <script>
    	// 방법 2 : 웹 요소를 따로 변수로 만들지 않고 사용
    	document.querySelector("#change").onclick = changeColor;
        
        function changeColor() {
            document.querySelector("p").style.color = "#f00";
        }
    </script>
</body>

 

방법 3. 직접 함수를 선언함

: 변수를 따로 지정하지도 않고, 함수도 따로 정의 후 사용하지 않음

웹 요소에 바로 이벤트를 지정하고, 함수의 이름 지정 없이 정의하며 동시에 실행하도록 함(익명함수)

<body>
    <button id="change">글자색 바꾸기</button>
    <p>abcdefghijklmnopqrstuvwxyz</p>
    
    <script>
    	// 방법 3 : 직접 함수를 선언함
        document.querySelector("#change").onclick = function() {
            document.querySelector("p").style.color = "#f00";
        }
    </script>
</body>