반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- isinterrupted()
- Linux셋팅
- String char[] 형변환
- ObjectInputStream
- 동기화
- 상관서브쿼리
- sleep()메소드
- include액션태그
- 메모리스트림
- include지시자
- first-of-child
- ID중복
- 리눅스셋팅
- 스레드그룸
- first-child
- include 지시자
- 리눅스세팅
- Daemon()
- Linux세팅
- MemoryStream
- StringReader
- InputDialog
- ThreadGroup()
- 상관 서브 쿼리
- interrupted()
- 아이디중복
- 표현 언어
- StringWriter
- char[] String 형변환
- interrupt()
Archives
- Today
- Total
다연이네
[days06] 클로저(Closure) (중요! 취업질문 多) 본문
반응형
클로저 == 함수 폐쇄
js는 중첩함수를 지원한다. (함수 안에 함수 만들기)
부모함수가 닫힌 후에도 부모 범위에 접근할 수 있는 함수 + 중첩함수
<body>
<button onclick="test()">test</button>
<div id="demo"></div>
<script>
var add = (function() {
var counter =0; //지역변수 (1 함수가 호출이 끝나면 사라져야 함)
return function() { //얘가 클로저
counter++; //그러나 버튼 누르면 계속 증가함 (2 사라지지 않았다 ? )
return counter; // 3 기본적인 지역변수는 사라지지만 클로저를 통해 접근한 것
};
})();
function test() {
document.getElementById("demo").innerHTML = add(); //클로저를 사용한 것
//클로저 == 중첩함수라고 해도 틀린말은 아니나, + 부모함수가 닫혀서 외부에서 접근을 못할때
// 부모의 멤버에 접근할 수 있는 함수이다.
}
</script>
</body>
버튼을 누를때마다 카운트가 증가한다. (클로저를 통한 접근)
<body>
<button onclick="add()">test</button>
<div id="demo"></div>
<script>
var counter = 0;
function add() {
var counter = 0;
counter++;
document.getElementById("demo").innerHTML = counter;
}
</script>
</body>
버튼을 눌러도 출력값이 1에서 변하지 않는다.
0에서 1증가해서 1이 되고 함수 호출 끝나면 지역변수 제거되고, 다시 호출되면 다시 0에서 1되고,..
버튼 누를때마다 항상 0->1 되기 때문에 1만 반복되는 것이다.
지역변수는 함수를 호출할때마다 새로 만들어진다.
만약 지역변수도 있고 전역변수도 있다면 ? 그래도 1만 출력된다.
=> 똑같은 변수가 있다면 지역변수가 우선시 된다. (지역변수 카운터 먼저 쓰고 있다)
<body>
<button onclick="test()">test</button>
<div id="demo"></div>
<script>
var n = 4;
function test() {
var n =3;
document.getElementById("demo").innerHTML = n*n;
}
</script>
</body>
9 출력, 지역변수가 전역변수보다 우선순위가 높다.
<body>
<button onclick="add()">test</button>
<div id="demo"></div>
<script>
function add() {
var counter = 0; //지역변수
function plus() { //이 내부 함수에서 외부 함수의 변수에 접근 가능
counter++;
}
plus();
return counter;
}
document.getElementById("demo").innerHTML =add(); //1 출력
</script>
</body>
<script>
//자체 함수 호출
var add = (function() {
var counter =0;
return function() {
counter++;
return counter;
};
})();
//document.getElementById("demo").innerHTML =add(); //함수 자체 return (리턴값이 함수 자체니까)
document.getElementById("demo").innerHTML =add();
</script>
위 둘처럼 코딩하면 1만 출력된다...
클로저 사용 예시 1
클릭하면 글자 크기 변하게 하기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style>
body{
font-size: 12px;
}
h1{
font-size: 1.5em;
}
h2{
font-size: 1.2em;
}
</style>
</head>
<body>
<p>Lorem ipsum dolor sit amet.</p>
<h1>Lorem ipsum dolor sit amet.</h1>
<h2>Lorem ipsum dolor sit amet.</h2>
<a href="#" id="size-12">12</a>
<a href="#" id="size-14">14</a>
<a href="#" id="size-16">16</a>
<script>
function makeSize(size) {
//size 지역변수
//var counter = 0;
return function() {
document.body.style.fontSize= size+"px";
};
}
var size12 = makeSize(12);
var size14 = makeSize(14);
var size16 = makeSize(16);
document.getElementById("size-12").onclick = size12;
document.getElementById("size-14").onclick = size14;
document.getElementById("size-16").onclick = size16;
</script>
</body>
</html>
모듈 패턴 : private 함수와 변수에 접근하는 public 함수를 정의하기 위해 클로저 사용
- java에서는 private 메소드()를 외부에선 접근할 수 없었다.
- js는 private 메소드()가 없기 때문에 -> 클로저(Closure)를 이용해서 private method 처리해야한다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<script>
var counter = (function() {
//부모 함수의 멤버들
var privateCounter = 0; //이 변수 외부에서 접근 못함
function changeBy(val) { //이 함수 외부에서 접근 못함 (클로저 통해 접근해야함)
privateCounter+=val;
}
return {
increment:function(){
changeBy(1);
},
decrement:function(){
changeBy(-1);
},
value:function(){
return privateCounter;
}
};
})();
counter.increment();
counter.increment();
counter.increment();
document.write(counter.value()+"<br>"); //3 value는 속성이 아니라 함수니까 ()
counter.decrement();
document.write(counter.value()+"<br>"); //2
</script>
</body>
</html>
클로저 사용 예시2
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style>
.myProgress{
width: 100%;
background: #ddd;
border: solid 1px gray;
}
.myBar{
width: 1%;
height: 30px;
background: #4CAF50;
text-align: right;
color: red;
}
</style>
</head>
<body>
<h3>Progress Bar</h3>
<div id="myprogress1" class="myProgress">
<div id="myBar1" class="myBar"></div>
<button id="btn1">진행</button>
</div>
<div id="myprogress2" class="myProgress">
<div id="myBar2" class="myBar"></div>
<button id="btn2">진행</button>
</div>
<div id="myprogress3" class="myProgress">
<div id="myBar3" class="myBar"></div>
<button id="btn3">진행</button>
</div>
<div id="myprogress4" class="myProgress">
<div id="myBar4" class="myBar"></div>
<button id="btn4">진행</button>
</div>
<div id="myprogress5" class="myProgress">
<div id="myBar5" class="myBar"></div>
<button id="btn6">진행</button>
</div>
<!-- 위에 div도 동적으로 만들어보기 -->
<script>
/*
var bar = document.getElementById("myBar1");
document.getElementById("btn1").onclick = progressbar;
var width = 1;
var timer ;
function progressbar() {
if(width<100){
width++;
bar.style.width = width+"%";
bar.innerHTML = width+"%";
timer = setTimeout(progressbar, 30);
}else{
clearTimeout(timer);
}
}
*/
</script>
<script>
//막대그래프가 1개가 아니라 5개면 그 개수만큼 width 변수, timer 변수 필요
//이럴때 클로저 사용
var btns = document.getElementsByTagName("button"); //버튼 다가져오기
var myBars = document.getElementsByClassName("myBar"); //막대바 다가져오기
for (var i = 0; i <btns.length; i++) { //각각 버튼 클릭할때 함수 등록
btns[i].onclick = function() { //부모함수
//alert("dd");
var width = 1;
var btn = event.srcElement; //클릭한 버튼
var timer = setInterval(function() { //클로저
if(width<100){
width++;
btn.previousElementSibling.style.width = width+"%"; //jquery: prev()
btn.previousElementSibling.innerHTML = width+"%";
}else{
clearInterval(timer);
}
}, 30);
}
}//클로저를 쓰고 나면 각각 호출할때 자기자신 변수들이 버튼마다 자기꺼 갖고 있다
//-> 코딩이 엄청 편리해짐
//클로저 취업질문 참 많이한다..
</script>
</body>
</html>
jQuery로 수정
<script>
$("button").click(function() {
var $bar = $(this).prev(); //변수앞에$를 붙히면 항상 jQuery객체가 된다.
var btn = event.srcElement;
var width =1;
var timer = setInterval(function() {
if(width<100){
width++;
$bar.css("width", width+"%");
$bar.html(width+"%");
}else{
clearInterval(timer);
}
}, 30);
});
</script>
반응형
'Web > JavaScript' 카테고리의 다른 글
[days06] 공 튀기기 (0) | 2020.12.16 |
---|---|
[days06] draggable()와 마우스 관련 이벤트 (0) | 2020.12.16 |
[days06] js call()/apply() 메소드 (0) | 2020.12.16 |
[days05] js 객체와 함수 (0) | 2020.12.15 |
[days05] 1) js 클래스 + constructor 2) form태그 유효성 검사 (0) | 2020.12.15 |
Comments