<TIL> Javascript_함수, 재귀함수, 스코프, 객체생성함수, 프로토타입
2021.08.10
실시간 시계 만들기
<body>
<h1>자바스크립트 시계</h1>
<h2 id="time"></h2>
<script>
let timeShow = document.getElementById('time');
let weekDay = [
'일요일',
'월요일',
'화요일',
'수요일',
'목요일',
'금요일',
'토요일',
];
function clock() {
let date = new Date();
let clockMonth = date.getMonth() + 1;
let clockDate = date.getDate();
let clockDay = weekDay[date.getDay()];
let clockHour =
date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
let clockMinute =
date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
let clockSecond = `${
date.getSeconds() < 10 ? `0${date.getSeconds()}` : date.getSeconds()
}`; // 이중 백틱
let today = `${clockMonth}/${clockDate} ${clockDay} ${clockHour}:${clockMinute}:${clockSecond}`;
timeShow.innerHTML = today;
}
setInterval(clock, 1000);
</script>
</body>
지난번에 했던 시계 구현에서 다른 것은 두자리수로 숫자를 표현하기 위해 조건문을 사용해 값이 10보다 작으면 앞자리에 0을 붙혀주어서 출력하게 해준다.
1초마다 해당 함수를 반복하여 실제 시계처럼 동작하기 위해 setInterval(함수, 1000)을 사용해서 반복시켜준다.
이중백틱 사용법
백틱 내부에 백틱을 또 사용하여 특정부분만 문자로 표현하고 싶을때 사용한다.`${변수 조건 `문자${참}` 거짓}`
자동실행함수
함수이름 ();
(function(){})();
(function(){}());
익명함수를 변수에 담아 바로 실행시킬때 사용
let result = (function () { return 1 + 2; })(); console.log(result); // 3
let result2 = (function (a, b) { return a + b; })(5, 8);
console.log(result2); // 13
재귀함수
함수가 실행될때 내부 로직엣 다시 자신을 실행하여 실행이 반복되는 함수
<script>
let num = 0;
test();
function test() {
num++;
document.write(num, '<br>');
if (num == 10) return;
// 함수 반복을 종료하기 위해 조건을 걸어 return하여 함수 종료
test();
// 함수 안에서 다시 자신을 실행 = 재귀함수 -> 함수 무한 반복
}
</script>
test라는 함수 내부에 다시 test();이 마지막에 실행되어 다시 반복되는 재귀함수로 위 코드에서는 반복을 끊어주기 위해 조건을 주어 return으로 함수를 종료시켰다.
return문이 없었다면 계속 num 변수가 증가되어 출력된다.
객체생성함수
자주 사용하는 기능을 정의한 함수를 여러번 만들어내기 위한 틀을 저장해놓은 객체타입함수를 만들어 사용한다.
객체를 만들어 놓으면 해당 객체를 변수에 선언한 뒤 해당하는 객체에 속한 프로퍼티에 값을 입력하고 객체에 속한 메서드를 이용할 수 있게 된다.
객체생성함수
function 객체이름(매개변수1, ..) {
this.프로퍼티1(객체에서 사용할 변수) = 받아올 값1(매개변수1),
this.프로퍼티2(객체에서 사용할 변수) = 받아올 값2(매개변수2),
..
this.함수이름 = function () {
내부 로직
}
}
객체생성 후 사용법
1. 객체 생성
let 참조변수명 = new 객체이름();
2. 객체 내부 프로퍼티 값 입력
생성할때 입력하는 법 -> let 참조변수명 = new 객체이름(값1, 값2);
따로따로 입력하는 법 -> 참조변수명.프로퍼티명 = 값;
3. 객체 내부 메서드 사용법
참조변수명.함수명();
<body>
<script>
// 이름, 키, 몸무게, 정상몸무게 계산함수
function Checkweight(name, height, weight) {
// let userName = ''
this.userName = name;
this.userHeight = height;
this.userWeight = weight;
this.minWeight;
this.maxWeight;
this.getInfo = function () {
// 개인 정보 출력 함수
let str = '';
str += `이름: ${this.userName}, `;
str += `키: ${this.userHeight}, `;
str += `몸무게: ${this.userWeight} <br>`;
return str;
};
this.getResult = function () {
this.minWeight = (this.userHeight - 100) * 0.9 - 5;
this.maxWeight = (this.userHeight - 100) * 0.9 + 5;
if (
this.userWeight >= this.minWeight &&
this.userWeight <= this.maxWeight
) {
//정상몸무게
return '정상 몸무게입니다. <br><br>';
} else if (this.userWeight < this.minWeight) {
//저체중
return '몸무게 미달입니다. <br><br>';
} else {
//과체중
return '몸무게 초과입니다. <br><br>';
}
};
}
let kim = new Checkweight('김가루', 176, 70);
document.write(kim.getInfo());
// 이름: 고길동, 키: 176, 몸무게: 70
document.write(kim.getResult());
// 정상 몸무게입니다.
let park = new Checkweight('박치기', 180, 65);
document.write(park.getInfo());
// 이름: 박치기, 키: 180, 몸무게: 65
document.write(park.getResult());
// 몸무게 미달입니다.
</script>
</body>
사람들의 정상몸무게를 측정하기 위해 객체를 생성하여 데이터를 지정한 값으로 편하게 받아오고 계산을 위한 함수를 메서드로 가져와서 정의하지 않고 바로 사용함으로써 편하게 원하는 값을 얻을 수 있다.
prototype
객체에 자주 중복사용되는 메서드를 객체를 생성될때마다 생성하고 사용하는 것아니라 prototype에 묶어서 객체 밖에서 정의해줌으로써 메서드 사용시 prototype chaining으로 연결하여 필요시에만 가져와 사용해 객체 생성시 데이터저장소의 낭비를 줄일 수 있다.
<body>
<script>
// 이름, 키, 몸무게, 정상몸무게 계산함수
function Checkweight(name, height, weight) {
// let userName = ''
this.userName = name;
this.userHeight = height;
this.userWeight = weight;
this.minWeight;
this.maxWeight;
}
Checkweight.prototype.getInfo = function () {
// 개인 정보 출력 함수
let str = '';
str += `이름: ${this.userName}, `;
str += `키: ${this.userHeight}, `;
str += `몸무게: ${this.userWeight} <br>`;
return str;
};
Checkweight.prototype.getResult = function () {
this.minWeight = (this.userHeight - 100) * 0.9 - 5;
this.maxWeight = (this.userHeight - 100) * 0.9 + 5;
if (
this.userWeight >= this.minWeight &&
this.userWeight <= this.maxWeight
) {
//정상몸무게
return '정상 몸무게입니다. <br><br>';
} else if (this.userWeight < this.minWeight) {
//저체중
return '몸무게 미달입니다. <br><br>';
} else {
//과체중
return '몸무게 초과입니다. <br><br>';
}
};
let kim = new Checkweight('김가루', 176, 70);
document.write(kim.getInfo()); // 이름: 고길동, 키: 176, 몸무게: 70
document.write(kim.getResult()); // 정상 몸무게입니다.
let park = new Checkweight('박치기', 180, 65);
document.write(park.getInfo()); // 이름: 박치기, 키: 180, 몸무게: 65
document.write(park.getResult()); // 몸무게 미달입니다.
</script>
</body>
함수 스코프
함수나 변수가 참조가 유효한 범위
크게 전역, 지역으로 나뉠 수 있음
변수 참조시에는 같은 내부에 있는 지역스코프에서 참조할 변수가 없을시 전역스코프로 해당하는 변수를 찾아서 사용할 수 있지만, 전역변수에서 내부 지역변수에 정의된 변수를 사용할 수는 없다.
함수 실행시에도 마찬가지이다.
<body>
<script>
function test() {
alert('전역함수');
}
function test2() {
function test3() {
alert('지역함수');
}
test();
}
test();
// 전역함수
test2();
// 전역함수
function test2() {
function test() {
alert('지역함수');
}
test();
}
test2();
// 지역함수
function test2() {
function test4() {
alert('지역함수');
}
test4();
}
test4();
//undefined
</script>
</body>
위 함수들과 실행문을 거치고 나온 결과를 보면 같은 스코프에서 선언하면 해당 함수 로직이 실행되고 내부 스코프에 함수 실행문에 해당하는 함수가 없을 시 전역스코프로가서 함수를 찾아 실행한다.
반대로 내부 지역스코프에서 정의된 함수를 전역스코프에서 실행하면 undefined로 정의되지 않았다고 나타난다.
그리고 코드들 하단에 아래 코드를 추가하면
function test() {
alert('전역함수재선언');
}
이전에 test()로 실행했던 결과들이 제일 하단에 정의된 위 함수의 결과값으로 바뀌어 나타나는 것을 볼 수 있다. 이는 코드를 위에서 아래로 읽어 제일 하단에 있는 값을 최신 값으로 판단하여 적용하는 특성과 함수가 호이스팅되어 실행문 위로 끌어올려져 함수를 실행할 수 있는 특성의 결과이다.
setAttribute('속성이름', '속성값')
javascript에서 html의 원하는 속성을 잡아서 해당 값을 바꿀때 사용하는 메서드
예시)
document.getElementById('photo').setAttribute('src', `images/n${num}.jpeg`);
id가 photo인 태그를 잡아서 태그의 속성 중 src의 값을 images/n${num}.jpeg으로 바꾼다.
알아두면 좋은 예제
토글구현1
<body>
<h1 id="title">노란 사각형</h1>
<div id="block" onclick="change('red')"></div>
<script>
function change(value) {
if (value == 'red') {
document.getElementById('title').innerHTML = '빨강색 원';
document.getElementById('block').style.backgroundColor = 'red';
document.getElementById('block').style.borderRadius = '50%';
document
.getElementById('block')
.setAttribute('onclick', "change('yellow')");
} else {
document.getElementById('title').innerHTML = '노란사각형';
document.getElementById('block').style.backgroundColor = 'yellow';
document.getElementById('block').style.borderRadius = '0%';
document
.getElementById('block')
.setAttribute('onclick', "change('red')");
}
}
</script>
</body>
조건문을 사용해 onclick에 연결된 change 함수에 매개변수가 기존의 html에 설정해놓은 'red'을 가져오게되고 조건에 의해 참을 실행하고 속성들을 바꾸게 되고 setAttribute으로 onlick을 선택해 값을 change('yellow')로 바꾸어 다음 클릭 시 조건문의 거짓실행문이 작동되게 한다.
토글구현2
<body>
<h1 id="title">노란 사각형</h1>
<div id="block"></div>
<script>
document.getElementById('block').addEventListener('click', change);
let bg = document.getElementById('block');
// 실행하면 한번클릭이후 바로 안바뀌고 한번 더 클릭했을때 바뀌는 이유
// getElementById('block').style.backgroundColor과 같은 변경은 태그의 인라인 구조를 바꾸는 것으로
// 기존에 설정된 css 속성을 바꾸지는 못한다.
// 따라서 바로 변경되게 하려면 처음부터 인라인 속성을 넣어주어야 바로 바꾸는 것이 가능하다.
function change() {
if (bg.style.backgroundColor == 'yellow') {
document.getElementById('title').innerHTML = '빨강색 원';
document.getElementById('block').style.backgroundColor = 'red';
document.getElementById('block').style.borderRadius = '50%';
} else {
document.getElementById('title').innerHTML = '노란 사각형';
document.getElementById('block').style.backgroundColor = 'yellow';
document.getElementById('block').style.borderRadius = '0%';
}
}
</script>
</body>
위도 구현되는 기능은 같지만 addEventListener를 사용해 click 이벤트를 감지하고 change 함수를 실행하게 한다.
조건에 클릭이벤트가 발생하는 태그의 배경속성을 선택하고 해당 값이 노란색이면 참 실행문이 실행되고 컬러값을 바꿔주어 다음에 클릭될 때 거짓실행문이 작동되게 해준다.
하지만, 이 함수를 실행하면 한번클릭시에는 바로 바뀌지 않고 두번클릭해야 바뀌는데 이유는 javascript에서 속성을 잡아서 바꾸는 값은 인라인 속성을 바꾸는 것으로 본질적인 css에 작성된 코드를 바꾸는게 아니여서 기존인라인값에는 아무값도 지정되어 있지 않아 거짓 실행문이 작동해 아무변화가 없는 거처럼 보이는 것이다.
초기 화면
한번 클릭시
인라인 값이 따로 채워지는 것을 볼 수 있다.
이 값이 채워지고 나서 의도했던대로 토글이 구현되는 것을 볼 수 있다.
바로 실행되게하려면 인라인값에 조건의 값을 미리 설정해두어야 한다.
Author And Source
이 문제에 관하여(<TIL> Javascript_함수, 재귀함수, 스코프, 객체생성함수, 프로토타입), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@padd60/TIL-Javascript함수-재귀함수-스코프-객체생성함수-프로토타입저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)