<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>0906 실습</title>
<script type="text/Javascript">
/*구구단 만들기 실습*/
function calculate(gugu){
// $("#gugu").val(gugu); jquery 방식
// var gugu = $("#gugu").val(); jquery 방식
var gugu = document.getElementById('gugu').value; // 자바스크립트로 input 값 가져오기
gugu = Number(gugu);
if(isNaN(gugu) || gugu <=0 ){ // isNaN : number가 NaN(숫자가 아님)인지 확인.(숫자 체크)
alert('숫자를 입력해주세요');
} else {
document.write("<table border=1>");
document.write("<tr>" + "<td>" + "X" + "</td>");
for(var j=1; j<=9; j++){ // * 9까지
document.write("<td>" + j + "</td>");
}
for(var i=1; i<=gugu; i++){ // 몇단까지
document.write("<tr>" + "<td>" + i + "</td>");
for(var j=1; j<=9; j++){ // * 9까지
document.write("<td>" + i*j + "</td>");
}
document.write("</tr>");
}
document.write("</table>");
}
}
/*내장함수
//타이머함수
setTimeout(function(){
alert('3초가 지났습니다. ㅇㅂㅇ');
}, 3000) // 3초후에 함수를 실행(3000은 milesecond)
//1초마다 함수를 실행
var intervalID = setInterval(function(){
alert('<p>' + new Date() + '</p>');
}, 1000); // 1초마다 함수를 실행 // Fri Sep 06 2019 14:25:46 GMT+0900 (한국 표준시)
//5초 함수를 실행 후, 타이머를 종료
setTimeout(function(){
clearInterval(intervalID);
},5000);
//인코딩과 디코딩 함수
var URI = "http://hanb.co.kr?test=한글입니다.";
document.write(escape(URI)); // 적절한 정도로 인코딩
document.write(encodeURI(URI)); // 최소한의 문자만 인코딩
document.write(encodeURIComponent(URI)); // 대부분의 문자를 모두 인코딩
//코드실행함수
var willEval = '';
willEval += 'var number = 10;';
willEval += 'alert(number);';
eval(willEval); // String을 JavaScript코드로 실행 . 결과 10 alert 출력
//JavaScript 실행순서 A->C->B
//setTimeout은 script 블록이 모두 끝난 뒤에 호출
alert('A');
setTimeout(function(){
alert('B');
}, 0);
alert('C');*/
//반복문과 콜백함수
//0,1,2 차례로 호출을 원하지만 3만 3번 호출됨
for(var i = 0; i < 3; i++){
// (function (closed_i){ //클로저를 통해 0,1,2 가 호출되게 처리
setTimeout(function (){
alert(i); // alert(closed_i);
},0);
// })(i) //클로저를 통해 0,1,2 가 호출되게 처리
}
/*객체*/
//속성과 메소드
var person = {
name: '홍길동',
friend: '임꺽정',
eat: function(food){
alert(this.name + '이 ' + this.friend + '과 ' + food + '을 먹습니다.');
}
};
person.eat('밥'); // 메소드 호출 : '홍길동이 임꺽정과 밥을 먹습니다.'
var output = '';
for(var item in person){ // 객체와 반복문
output += item + ': ' + person[item] + '\n';
// item은 name, friend, eat / person은 value
}
/*객체관련 키워드*/
// in 키워드 : 객체 내 속성존재여부 확인
output += "'name' in person: " + ('name' in person) + '\n'; // 결과 : true
// with 키워드 : 객체명 생략
with(person){
output += 'name: ' + name + '\n'; // name: 홍길동
output += 'friend: ' + friend + '\n'; // friend: 임꺽정
}
/*객체의 속성 추가와 제거*/
var stu = {};
stu.이름 = '피구'; // 속성 추가
stu.장래희망 = '날강두';
stu.toString = function(){ // 메소드 추가
var answer = '';
for(var key in this){
if(key != 'toString'){ // toString 메소드는 출력하지 않게함.
answer += key + '\t' + this[key] + '\n';
}
}
alert(answer);
};
delete(stu.이름); // 속성제거. 배열에서의 delete는 undefined로 만드는 것.
//객체실습
var students = [];
students.push({ 이름 : '포그바', 국어: 99, 수학:88, 영어:77, 과학: 55});
students.push({ 이름 : '드록바', 국어: 89, 수학:78, 영어:67, 과학: 95});
students.push({ 이름 : '바밤바', 국어: 79, 수학:98, 영어:87, 과학: 15});
//모든 students 배열 내의 객체에 메소드를 추가합니다.
for(var i in students){
//총점 구하는 메소드를 추가
students[i].getSum = function(){
return this.국어 + this.수학 + this.영어 + this.과학;
}
//평균을 구하는 메소드를 추가
students[i].getAverage = function(){
return this.getSum() / 4;
};
}
//출력
var output = '이름\t총점\t평균\n';
for(var i in students){
with(students[i]){
output += 이름 + '\t' + getSum() + '\t' + getAverage() + '\n';
}
}/*이름 총점 평균
포그바 319 79.75
드록바 329 82.25
바밤바 279 69.75*/
/*생성자 함수 : 자바의 class 와 같다. return 값이 없음. new를 통해서 생성가능. */
//객체실습 : 함수를 사용한 객체생성
function makeStudent(name, korean, math, english, science){
var willReturn = {
//속성
이름 : name, 국어 : korean, 수학 : math, 영어 : english, 과학 : science,
//메소드
getSum: function(){
return this.국어 + this.수학 + this.영어 + this.과학;
},
getAverage: function(){
return this.getSum() / 4;
},
toString: function(){
return this.이름 + '\t' + this.getSum() + '\t' + this.getAverage();
}
};
return willReturn;
}
//1. 객체의 Property를 배열로 반환
function getPropertynames(o){
var a = [];
for(property in o) a.push(property); // 객체 o의 속성을 a 배열에 넣어라.
return r;
}
// 2. from의 객체를 to로 Copy ( from의 프로퍼티를 to에 넣으면 됨.)
function copyProperties(from, to){
if(!to) to = {};
for(p in from) to[p] = from[p]; // from 에 있는 p를 반복해서 to 배열에 넣어라.
return to;
}
// 3. From의객체를 to로 Copy하되 to에 없는 속성만 Copy
function copyUndefineProperties(from, to){
for(p in from){ // from에 있는 p를 반복
if(!(p in to)) to[p] = from[p]; // to에 있는 p가 아닌 경우에만 -> from의 p를 to의 p에 넣어라.
}
}
/*생성자함수
//생성자 함수 예제1
//Circle 클래스
function Circle(radius){ // 생성자 함수 정의
this.r = radius;
}
//클래스 프로퍼티, 생성자함수의 프로퍼티
Circle.PI = 3.14159;
//인스턴스 메소드
Circle.prototype.area = function(){return Circle.PI * this.r * this.r;}
//클래스 메소드
Circle.max = function(a,b){
if(a.r > b.r) return a;
else return b;
}
var c = new Circle(1.0); //인스턴스 생성
c.r = 2.2; //인스턴스 프로퍼티
var a = c.area(); // 인스턴스 메소드
var x = Math.exp(Circle.PI); // 클래스 프로퍼티
var d = new Circle(1.2); // 다른 인스턴스
var bigger = Circle.max(c, d); // 클래스 메소드
/*캡슐화*/
function Rectangle(w,h){// 변수를 선언
var width = w;
var height = h;
//메소드선언
this.getWidth = function(){return width;};
this.getHeight = function(){return height;};
// this.area = function(){return this.width * this.height;} // 생성자 함수에 메소드 속성 추가
this.setWidth = function(w){
if(w<0){
throw '길이는 음수일 수 없습니다.';
} else {
width = w;
}
};
this.setHeight = function(h){
if(w<0){
throw '길이는 음수일 수 없습니다.';
} else {
height = h;
}
}
}
Rectangle.prototype.getArea = function(){ // prototype에서 객체의 this에 접근가능
return this.getWidth() * this.getHeight();
};
// var a = r.area(); //각 인스턴스들이 공유해야 하는 Property나 메소드를 정의(생성자 함수를 더 효율적으로 개선 :prototype사용)
var rectangle = new Rectangle(5, 7); //변수를 선언. property를 초기화하며 new와 함께 사용된다.
rectangle.setWidth(5); // 음수면 '길이는 음수일 수 없습니다.' 출력
alert('AREA : ' + rectangle.getArea()); // AREA : 35
/*상속 - JavaScript에서 정확한 상속방법은 없다.
instanceof 키워드로 특정 객체의 instance인지 확인 */
function Square(length){
this.base = Rectangle; // 생성자로 Rectangle를 속성으로
this.base(length, length); // 생성자 함수 Rectangle 호출
}
Square.prototype = Rectangle.prototype;
Square.prototype.constructor = Square; // 생략가능. constructor : 자신의 원소를 물어볼때 쓰임.
var square = new Square(5);
alert(square instanceof Rectangle); // 상속확인 : 결과값 true
/*상속예제
//모든 함수는 apply(), call() 메소드가 존재한다.
// 함수는 f()에 두 숫자를 전달하고 이 함수가 객체 o의 메소드 인 것처럼 호출할 경우
// 첫번째인자 : 함수가 소속되어 호출될 객체
// 나머지인자 : 함수의 전달인자
f.call(0, 1, 2);
//다음코드와 동일
o.m = f;
o.m(1,2);
delete o.m;
//apply()는 call()과 유사하지만 전달인자를 배열로 지정하는 것이 다름
f.apply(o, [1.2]);*/
//===============================
/*prototype(원형) : 상속의 구체적인 수단*/
// prototype에 저장된 속성들은 생성자를 통해서 객체가 만들어질 때 그 객체에 연결됨(prototype chain)
function MyParent(){
this.property1 = "부모속성";
console.log('Parent');
}
MyParent.prototype.info = function(){
console.log('property1: ' + this.property1);
};
function MyChild(){
this.property2 = "자식속성";
console.log('Child');
}
MyChild.prototype = new MyParent(); //부모클래스 상속
MyChild.prototype.constructor = MyChild(); // 생성자 설정
MyChild.prototype.info = function(){ // 오버라이딩을 통한 기능확장 MyChild.prototype 은 MyParent를 가리킨다.
MyParent.prototype.info.call(this); // 부모클래스의 info함수 호출
console.log('info기능확장');
}
var child = new MyChild(); // 자식인스턴스 생성
child.info(); // 자식정보출력
/*기본자료형과 객체*/
// 기본자료형에 메소드 추가
var primitiveNumber = 273;
var objectNumber = new Number(273);
// Number 객체에 메소드를 추가하면 number dataType인 primitiveNumber도 추가된 메소드 사용가능
Number.prototype.method = function(){
return 'Method on Prototype';
};
// 메소드 실행
var a1 = '';
a1 += primitiveNumber.method() + '\n';
a1 += objectNumber.method();
/*자료형 구분*/
//객체의 속성인 Constructor를 이용하면 같은 Type인지 비교하는 것이 명확함
var numberFromLiteral = 273;
var numberFromObject = new Number(273);
//자료형 확인
if(numberFromLiteral.constructor == Number){
alert('numberFromLiteral은 숫자입니다.'); // 얼럿뜸
}
if(numberFromObject.constructor == Number){
alert('numberFromObject는 숫자입니다.'); // 얼럿뜸
}
</script>
</head>
<body>
몇단을 만들까요?<input type="text" id="gugu" name="gugu" >
<input type="hidden" id="gugu" name="gugu" />
<input type="button" id="make" name="make" value="구구단 만들기" onClick="calculate(gugu)"/>
</body>
</html>