<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>0905실습</title>
<script type="text/javascript">
//1. 단어 s의 가운데 글자를 반환하는 함수 (단어의 길이가 짝수라면 가운데 두 글자를 반환)
function calculate1(s) {
var input = prompt("가운데 글자 반환함수", "글자 s를 입력해주세요.");
if (input.length % 2 == 0){
alert(input.substring((input.length/2)-1, (input.length/2)+1));
}else{
alert(input.substring((input.length/2), (input.length/2)+1));
}
}
//2. 배열 arr의 각 원소는 숫자 0부터 9까지로 이루어져 있습니다.
// 배열 arr에서 연속적으로 나타나는 숫자는 하나만 남기고 전부 제거하여 리턴하는 함수
function calculate2(arr) {
var arr = [0,1,1,2,3,4,5,7,7,9];
var answer = [];
var length = arr.length;
// for문에서 arr.length 사용하면 왜곡이 되므로
// length 변수 받아서 쓰던가 var i in arr 로 써라.
for(i=0; i<length; i++){ // var i in arr 로 쓰면 작동안됨.
if(arr[i] !== arr[i+1]){
answer.push(arr[i]);
}
}
alert(answer);
}
//3. 두 정수 a, b가 주어졌을 때 a와 b 사이에 속한 모든 정수의 합을 리턴하는 함수
function calculate3(a, b) {
var input = prompt("a와 b 사이에 속한 모든 정수의 합을 리턴하는 함수", "a를 입력해주세요.");
var input1 = prompt("a와 b 사이에 속한 모든 정수의 합을 리턴하는 함수", "b를 입력해주세요.");
var arr = [input, input1];
var answer = 0;
if(arr[0] == arr[1]){
answer = arr[0];
} else {
for(var i = arr[0]; i<=arr[1]; i++){
answer += Number(i); // Number로 변환해야 숫자로 인식됨.
}
}
alert(answer);
}
//4. 정수를 담고 있는 배열 arr의 평균값을 return하는 함수
function calculate4(arr) {
var arr = [1,2,3,4,5,6,7,8,9,10];
let result = 0; // let은 변수에 재할당이 가능
for(let i = 0; i<arr.length; i++){
result += arr[i];
}
alert(result/arr.length);
}
/* ★★★★★★★★★★★★★★★★ 클로저 ★★★★★★★★★★★★★★★ */
// 실행이 끝난 함수의 스코프를 참조할 수 있는 함수
function parent() {
var a = 'Parent is done';
function child() {
console.log(a);
}
return child;
}
var closure = parent();
closure();
위 내부함수의 정의대로라면 parent 의 내부함수인 child() 는 외부에서 접근이 불가능하다.
하지만 return 값에 child 를 넘김으로써 외부에서도 child 를 호출할 수 있게 된다.
따라서, child() 에서 parent 의 값을 참고하고 있다면,
child() 를 밖에서 호출함으로써 parent() 의 변수에 접근이 가능하게 된다. 이것이 클로져
// 클로저 : 지역변수의 범위를 벗어나서 사용가능하게 해줌.
function test(name){
var output = 'Hello' + name + '...!'; //private 멤버변수
//내부 메소드에서는 private 멤버변수 사용가능
return function(){ // 내부메소드를 통해서 메모리 할당됨
alert(output);
};
}
// 지역변수 output은 test()가 호출될때 생성(메소드가 끝났음에도 사용가능)
test('JavaScript')(); // 결과값 : HelloJavaScript...! ( 함수가 리턴되므로)
// 전역변수는 var문을 생략해도 되지만 지역변수는 반드시 var문을 써야한다.
scope = "global";
function checkscope(){
scope = "local"; // 전역변수를 바꾸어버림
myscope = "local"; // 새로운 전역변수 생성
}
//클로저를 사용하여 Counter 만들기
//아래소스는 외부에서 counter값을 변경할 수 있는 문제 존재
uniqueInteger.counter = 0;
function uniqueInteger(){
return uniqueInteger.counter++;
}
//클로저를 이용해 해결한 소스
var uniqueID = (function(){
var id = 0; // private 속성을 가진다. 함수만이 접근가능
// uniqueID에 저장되는 것은 값이 아닌 중첩된 함수이다.
return function(){return id++;} // 값을 증가시켜서 반환
})();
for(var i=0; i<3; i++){
alert(uniqueID()); // 결과값 : 0, 1, 2
}
// 클로저 : 중첩함수
function makefunc(x){
return function(){return x;}
}
//리턴된 함수를 배열요소에 저장
var a = [makefunc('x'), makefunc('y'), makefunc('z')];
alert(a[0]()); // x출력
alert(a[1]()); // y출력
alert(a[2]()); // z출력
// 클로저를 사용한 private 멤버변수
function makeProperty(o, name, predicate){ // o는 object
var value; //private 변수
//getter메소드
o['get'+ name] = function(){return value;};
//setter메소드
o['set'+ name] = function(v){
if(predicate && !predicate(v)) // 메소드가 존재하고 false를 리턴하면
throw 'set'+name+': invalid value' + v;
else
value = v;
}
}
var o = {};
//Name Property 추가, set은 string만 가능
makeProperty(o, 'Name', function(x){return typeof x == 'string';});
o.setName('Frank'); // 값 설정
console.log(o.getName()); // 값 출력 : Frank 찍힘.
// 클로저 문제
var counter = (function(){
var a = 0;
return {
inc : function(){return a++;}, // 메소드 선언시 ':' 을 사용한다.
dec : function(){return a--;},
val : function(){return a;}
};
})();
counter.inc(); // 1증가
counter.inc(); // 1증가
counter.dec(); // 1감소
console.log(counter.val()); // 1출력
/* Scope 예제 */
// 함수단위 유효범위
function scopeTest(){
var a = 0;
if(true){
var b = 0;
for(var c=0; c<5; c++){
console.log("c1= " + c); // 0, 1, 2, 3, 4, 5
}
console.log("c2 = " + c); // 5
}
console.log("b = " + b); // 결과값 0. block외부에서 b에 접근가능 => 블록단위 유효범위가 없다.
}
scopeTest();
// 변수명이 동일할 때는 가장 가까운 범위의 변수를 참조한다.
var scope = 10;
function scopeExam(){
var scope = 20;
console.log("scope = " + scope);
}
scopeExam(); // 20. 20이 더 가까움
// var 키워드를 생략하면 전역변수로 설정된다.
function scopeExam(){
scope = 20; // var가 없으므로 전역변수화 됨.
console.log("scope = " + scope);
}
function scopeExam2(){
console.log("scope = " + scope);
}
scopeExam(); // 20
scopeExam2(); // 20
// 변수 선언문을 끌어 올린다.
function hoistingExam(){
console.log("value = " + value); // 아래 선언된 변수를 사용, undefined 출력
var value = 10;
console.log("value = " + value); // 10출력
}
hoistingExam();
</script>
</head>
<body>
<input type="button" value="문제1번" onClick="calculate1()"><br><br>
<input type="button" value="문제2번" onClick="calculate2()"><br><br>
<input type="button" value="문제3번" onClick="calculate3()"><br><br>
<input type="button" value="문제4번" onClick="calculate4()"><br><br>
<input type="button" value="실습" onClick="makeProperty()"><br><br>
</body>
</html>