JavaScrpt/시간 날짜 달력

JavaScript Date - 달력 생성 함수 모듈화 2 (파라미터를 객체로 전달, 객체 병합을 통한 기본값 처리)

carrotweb 2022. 3. 27. 15:17
728x90
반응형

파라미터를 객체로 전달

함수에 전달되는 파라미터가 많아지면서 여러 설정 중 하나를 처리하기 위해 다른 설정도 처리되어야 하는 문제가 발생합니다.

calendar(date); --> 요일(숏 네임) 표시, 오늘 표시
calendar(date, false); --> 요일 표시 제거, 오늘 표시
calendar(date, true, true); --> 요일(풀 네임) 표시, 오늘 표시
calendar(date, true, false, false); --> 요일(숏 네임) 표시, 오늘 표시 제거

위의 예제처럼 오늘 표시를 제거하기 위해서 앞의 파라미터들을 설정해야 합니다. 이렇게 해도 문제는 없는지 함수의 파라미터가 길어집니다.

그래서 여러 파라미터들을 객체로 만들어 전달하면 설정 별로 처리할 수 있습니다.

스크립트에서는 중괄호({})로 객체를 만들 수 있습니다.

var options = {
	showDay : true,
	showFullDayName : false,
	showToday : false
};

// 오늘 표시만 제거할 경우
var options = {
	showToday : false
};

showDay와 showFullDayName은 연관된 설정입니다. showFullDayName는 showDay가 true가 아니면 요일일 표시되지 않기 때문에 showFullDayName를 true로 설정해도 showDay가 true가 아니면 표시되지 않습니다.

function()를 사용하여 객체를 만들 수 있지만 객체를 생성(new) 하여 전달해야 하기 때문에 코딩이 길어집니다.

var Options = function() {
	this.showToday = false;
}

var options = new Options();

 

중괄호({})로 객체를 만들어 적용하겠습니다. 테스트를 위해 오늘 표시를 제거하기 위한 설정만 적용합니다.

function calendar(date) {
	// 년월
	$(".calendar-yearmonth").html(date.getFullYear() + "." + (date.getMonth() + 1));
	
	var options = {
		showToday : false
	};
	
	var html = calendarHTML(date, options);
	$("#calendar").html(html);
}

 

함수에 파라미터들을 객체로 변경하고 적용하겠습니다.

function calendarHTML(date, options) {
	// 데이터 검증
	if (date == undefined || date == null || typeof date != "object" || !date instanceof Date) {
		return "";
	}
	
	// 기본값 처리
	if (options.showDay == undefined || options.showDay == null || typeof options.showDay != "boolean") {
		options.showDay = true;
	}
	if (options.showFullDayName == undefined || options.showFullDayName == null || typeof options.showFullDayName != "boolean") {
		options.showFullDayName = false;
	}
	if (options.showToday == undefined || options.showToday == null || typeof options.showToday != "boolean") {
		options.showToday = true;
	}
	
	// 요일
	var days = ["일", "월", "화", "수", "목", "금", "토"];
	
	// 달력 연도
	var calendarYear = date.getFullYear();
	// 달력 월
	var calendarMonth = date.getMonth() + 1;
	// 달력 일
	var calendarToday = date.getDate();
	
	var monthLastDate = new Date(calendarYear, calendarMonth, 0);
	// 달력 월의 마지막 일
	var calendarMonthLastDate = monthLastDate.getDate();
	
	var monthStartDay = new Date(calendarYear, date.getMonth(), 1);
	// 달력 월의 시작 요일
	var calendarMonthStartDay = monthStartDay.getDay();
	
	// 주 카운트
	var calendarWeekCount = Math.ceil((calendarMonthStartDay + calendarMonthLastDate) / 7);
	
	// 오늘
	var today = new Date();
	
	var html = "";
	html += "<table>";
	if (options.showDay) {
		html += "<thead><tr>";
		for (var index = 0; index < days.length; index++) {
			html += "<th";
			if (index == 0) {
				html += " class=\"sunday\"";
			} else if (index == 6) {
				html += " class=\"saturday\"";
			}
			html += ">" + days[index];
			if (options.showFullDayName) {
				html += "요일";
			}
			html += "</th>";
		}
		html += "</tr></thead>";
	}
	html += "<tbody>";
	// 위치
	var calendarPos = 0;
	// 날짜
	var calendarDay = 0;
	for (var index1 = 0; index1 < calendarWeekCount; index1++) {
		html += "<tr>";
		for (var index2 = 0; index2 < 7; index2++) {
			html += "<td>";
			if (calendarMonthStartDay <= calendarPos && calendarDay < calendarMonthLastDate) {
				calendarDay++;
				html += "<span";
				if (options.showToday && calendarYear == today.getFullYear() && calendarMonth == today.getMonth() + 1
					&& calendarDay == today.getDate()) {
					html += " class=\"today\"";
				} else {
					if (index2 == 0) {
						html += " class=\"sunday\"";
					} else if (index2 == 6) {
						html += " class=\"saturday\"";
					}
				}
				html += ">" + calendarDay + "</span>";
			}
			html += "</td>";
			calendarPos++;
		}
		html += "</tr>";
	}
	html += "</tbody>";
	html += "</table>";
	return html;
}

 

 

 

객체 병합을 통한 기본값 처리

스크립트에서는 객체를 병합할 수 있게 Object.assign() 메서드를 지원하고 있습니다.

Object.assign() 메서드는 한 개 이상의 source 객체를 target 객체에 병합합니다.

Object.assign(target, source);
Object.assign(target, source, ..., source);

target은 source 객체의 속성을 복사해 반영될 객체입니다. 그리고 리턴할 객체이기도 합니다.

source는 target 객체에 반영하고자 하는 속성들을 갖고 있는 객체입니다. (target 객체에 동일한 속성이 있으면 값이 적용되고 동일한 속성이 없으면 속성이 추가됩니다.)

 

target 객체에 showDay, showFullDayName, showToday를 설정하고 source 객체에 showToday만 설정합니다. 그리고 Object.assign() 메서드를 사용하여 처리합니다. 그러면 target 객체에 source 객체의 showToday의 설정이 값이 적용되는 것을 확인할 수 있습니다.

var target = {
	showDay : true,
	showFullDayName : false,
	showToday : true
};

var source = {
	showToday : false
};

var returnTarget = Object.assign(target, source);

console.log(target); --> {showDay: true, showFullDayName: false, showToday: false}
console.log(returnTarget); --> {showDay: true, showFullDayName: false, showToday: false}

 

target 객체에 showToday 속성이 없으면 source 객체의 showToday 속성이 추가됩니다.

var target = {
	showDay : true,
	showFullDayName : false
};

var source = {
	showToday : false
};

var returnTarget = Object.assign(target, source);

console.log(target); --> {showDay: true, showFullDayName: false, showToday: false}
console.log(returnTarget); --> {showDay: true, showFullDayName: false, showToday: false}

 

 

함수에 Object.assign() 메서드를 사용하여 기본값이 처리되게 적용하겠습니다.

function calendarHTML(date, options) {
	// 데이터 검증
	if (date == undefined || date == null || typeof date != "object" || !date instanceof Date) {
		return "";
	}
	
	// 기본 설정
	var settings = {
		showDay : true,
		showFullDayName : false,
		showToday : true
	};
	
	if (options != undefined && options != null) {
		Object.assign(settings, options);
	}
	
	// 요일
	var days = ["일", "월", "화", "수", "목", "금", "토"];
	
	// 달력 연도
	var calendarYear = date.getFullYear();
	// 달력 월
	var calendarMonth = date.getMonth() + 1;
	// 달력 일
	var calendarToday = date.getDate();
	
	var monthLastDate = new Date(calendarYear, calendarMonth, 0);
	// 달력 월의 마지막 일
	var calendarMonthLastDate = monthLastDate.getDate();
	
	var monthStartDay = new Date(calendarYear, date.getMonth(), 1);
	// 달력 월의 시작 요일
	var calendarMonthStartDay = monthStartDay.getDay();
	
	// 주 카운트
	var calendarWeekCount = Math.ceil((calendarMonthStartDay + calendarMonthLastDate) / 7);
	
	// 오늘
	var today = new Date();
	
	var html = "";
	html += "<table>";
	if (settings.showDay) {
		html += "<thead><tr>";
		for (var index = 0; index < days.length; index++) {
			html += "<th";
			if (index == 0) {
				html += " class=\"sunday\"";
			} else if (index == 6) {
				html += " class=\"saturday\"";
			}
			html += ">" + days[index];
			if (settings.showFullDayName) {
				html += "요일";
			}
			html += "</th>";
		}
		html += "</tr></thead>";
	}
	html += "<tbody>";
	// 위치
	var calendarPos = 0;
	// 날짜
	var calendarDay = 0;
	for (var index1 = 0; index1 < calendarWeekCount; index1++) {
		html += "<tr>";
		for (var index2 = 0; index2 < 7; index2++) {
			html += "<td>";
			if (calendarMonthStartDay <= calendarPos && calendarDay < calendarMonthLastDate) {
				calendarDay++;
				html += "<span";
				if (settings.showToday && calendarYear == today.getFullYear() && calendarMonth == today.getMonth() + 1
					&& calendarDay == today.getDate()) {
					html += " class=\"today\"";
				} else {
					if (index2 == 0) {
						html += " class=\"sunday\"";
					} else if (index2 == 6) {
						html += " class=\"saturday\"";
					}
				}
				html += ">" + calendarDay + "</span>";
			}
			html += "</td>";
			calendarPos++;
		}
		html += "</tr>";
	}
	html += "</tbody>";
	html += "</table>";
	return html;
}

 

함수의 코딩이 간결해졌습니다.

그렇지만 전달되는 객체에 대한 검증 없이 처리되기 때문에 다른 타입의 값이 적용되는 문제점이 있을 수 있습니다.

현재는 boolean 형만 사용하고 있어 boolean 형 대신 다른 타입이 적용되어도 조건문에서 true로 처리되기 때문 문제는 없습니다. (number 형으로 전달되면 조건문에서 0은 false, 0 이상은 true로 처리됩니다.)

함수를 사용하는 쪽에서 정확하게 속성들을 적용하여 처리한다면 사용에는 문제가 없습니다.

728x90
반응형