let Rollover = {}
$(function(){
Rollover.fdno = null
Rollover.bskno = null
Rollover.currst = null
injectObj(Rollover,{
callBskMstByFdidAndCurrst,
callPositionList,
callRollover,
clearSelectedBsk
})
})
→ 전역변수로 객체를 선언해서, injectObj(객체할당 커스터마이징한것)로 function과 변수를 핸들링했다
→ 해당 이미지처럼, 브라우저 개발도구로 손쉽게 데이터 변질이 가능하다
Closure를 알기 전에 lexical scope 를 먼저 이해하자,
: lexical scope란, 어휘적 범위 지정을 의미하는데 변수가 어디에서 사용 가능한지 알기 위해 소스 코드 내에 어디서 선언되었는지 고려하는 것을 의미
→ 간략히, 변수의 life cycle을 고려하는 것을 의미(내 주장)
function init() {
var name = "blockjjam"; // name is a local variable created by init
function displayName() { // displayName() is the inner function, a closure
alert (name); // displayName() uses variable declared in the parent function
}
displayName();
}
init();
// init()의 name의 scope는 init함수 안에서만 생존
그럼 Closure란?
: 어떤 데이터와 그 데이터를 조작하는 함수를 연관시키기에 유용한 기술이다.
: 함수와 함수가 선언된 어휘적 환경의 조합으로 데이터를 컨트롤한다
function makeFunc() {
var name = "blockjjam"; (3)
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc(); // (1)
//myFunc변수에 displayName을 리턴함
//유효범위의 어휘적 환경을 유지
myFunc(); // (2)
//리턴된 displayName 함수를 실행(name 변수에 접근)
→ 예시를 보면,
(1) myFunc은 makeFunc()으로 displayName함수가 리턴되어 클로져를 형성한다
(2) myFunc()을 할 때마다, makeFunc()의 scope에 접근하여, displayName함수가 실행된다
→ displayName은 makeFunc 함수의 name을 참조만 한다!(클로저가 형성된 시점에 name만을 참조)
(3) myFunc.name 으로 makeFunc()의 name 변수를 수정할 수 있을까??
→ 실행 불가! makeFunc() scope안에 리턴된 displayName함수 외에는 접근할 수 없다(정보 은닉)
var counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
};
})();
console.log(counter.value()); // logs 0
counter.increment();
counter.increment();
console.log(counter.value()); // logs 2
counter.decrement();
console.log(counter.value()); // logs 1
→ 위 예제에서, counter를 이용해서 privateCounter 변수에 직접 접근이 불가능하기 때문에, return된 value함수를 통해서 privateCounter값을 확인할 수 있다
Closure 예제 환경
바로 예제 Closure 코드를 확인해보자
var tmp_bskMst = null;
var Rollover = (function(){
let fdno = null
let bskno = null
let currst = null
let bskMstList = null
/** Async Process **/
function callBskMstByFdidAndCurrst(){
clearSelectedBsk()
setCurrst($("#sel_currst").val())
//...
}
function callPositionList(idx){
setFdno(bskMstList[idx].fdno)
setBskno(bskMstList[idx].bskno)
let url = '/order/rollover/list'
let params = createAsyncJsonParam({fdno, bskno, state: currst})
//...
}
function callRollover(){
let url = '/order/rollover/toflask' // 명명법 수정 필요
let params = createAsyncJsonParam({fdno, bskno, state:currst})
//...
}
/** End Async Process **/
/** Util **/
function clearSelectedBsk(){
setFdno(null)
setBskno(null)
setCurrst(null)
setBskMstList(null)
}
const setFdno = (input_fdno)=>{
fdno = input_fdno === null? null : parseInt(input_fdno)
}
const setBskno = (input_bskno)=>{
bskno = input_bskno === null? null : parseInt(input_bskno)
}
const setCurrst = (input_currst)=>{
currst= input_currst === null? null : input_currst;
}
const setBskMstList = (input_bskMstList)=>{
bskMstList = input_bskMstList === null? null : input_bskMstList.slice();
}
/** End Util **/
return {
callBskMstByFdidAndCurrst: callBskMstByFdidAndCurrst,
callPositionList: callPositionList,
callRollover: callRollover,
clearSelectedBsk: clearSelectedBsk
}
})();
let OrderHistory = {}
$(function (){
OrderHistory.fdno = null;
OrderHistory.bskno = null;
OrderHistory.date = null;
// 선언한 객체에 함수 객체를 주입해서 사용
injectObj(OrderHistory, {callFindBskInfo})
injectObj(OrderHistory, {setOneBskInfo})
injectObj(OrderHistory, {callFindBskInfo})
// 페이지 로드 시 Order History에 필요한 설정 정보 clear
OrderHistory.clearSelectedBskInfo()
})
fdno, date, bskno 모두 접근이 가능하다 실제로 데이터를 수정하면
단순히, 외부에서도 객체에 접근하여 데이터를 핸들링할 수 있다, 실제로 API서버로 전송까지 될까?
개발자도구로 핸들링한 그대로 데이터가 API서버로 전송된 것을 확인할 수 있다
접근 가능한 property가 여기도 있는데?? 라고 할 수 있지만
callBskMstByFdidAndCurrst, callPositionList, CallRollover, clearSelection → 이 프로퍼티는 Closure에서 노출해도 되는 함수들이다
var tmp_bskMst = null;
var Rollover = (function(){
//...
return {
callBskMstByFdidAndCurrst: callBskMstByFdidAndCurrst,
callPositionList: callPositionList,
callRollover: callRollover,
clearSelectedBsk: clearSelectedBsk
}
})();
위 코드를 보면, Rollover 클로져 안에서 노출 가능한 변수만 return 하여 외부에서 접근 가능한 속성들만 제공한다
위 이미지를 보면,
첫번째로 Rollover의 bskno, fdno, currst 와 같은 변수에 접근이 되지 않는것,
두번째로 강제로 Rollover의 프로퍼티에 값을 넣는 시도와 외부로 노출된 함수를 실행해보았다
위 결과 이미지를 보면,
일단 API서버에 들어오지도 않기 때문에 디버그 화면은 캡쳐하지도 않았고,
(전체화면 공개는 못하지만) 스크립트안에서 제대로 값 정보가 들어가지 않았음을 알 수 있다