var origin {member: 100};
var dup = origin;
dup.member = 200;
log(origin.member);
// 200
var origin = [1, 2, 3];
var dup = origin;
dup[1] = 200;
log(origin);
// [1, 200, 3]
var origin = {member: 100};
var dup = {};
for (var name in origin){
dup[name] = origin[name];
};
dup.member = 200;
log(origin.member);
log(dup.member);
// 100
// 200
Recursive Function
사용 사례
var book = {
member: {name: 100},
point: {value: 200}
};
function show(param){
for (var type in param){
typeof param[type] === "object" ? show(param[type]) : log(type + ":", param[type]);
}
};
show(book);
// name:100
// value:200
show(book);
for (var type in param){...}
typeof param[type] === "object" ? show(param[type]) : web.log(type + ":", param[type]);
param[type] 타입이 "object"이면
param[type] 타입이 "object"가 아니면
정리 시간
** 데이터 형태 **
var member = {
Jan : {item: {title: "JS북", amount: 100}, point: [10, 20, 30]},
Feb: {item: {title: "JS북", amout: 200}, point: [40, 50, 60]}
}
재귀 함수로 데이터를 출력하시오.
재귀 호출이 끝나면 누적한 값 출력하기
(function(){
log("JS북");
}());
// JS북
IIFE: Immediately Invoked Function Expression
(function(){...}()) 형태
var total = (1 + 2);
log(total);
// 3
var value = function(){
return 100;
};
log(value());
// 100
var value = function(){
return 100;
}();
log(value);
// 100
var value = (function(){
return 100;
}());
log(value);
// 100
그룹핑 연산자에서 반환된 값이 할당되는 변수를 작성하지 않은 형태
})()처럼 소괄호를 끝에 작성 가능
(function(){
log(100);
}());
// 100
/*
1. 그룹핑 연산자를 작성하지 않으면 함수 이름이 없으므로 문법 에러
2. 하지만, 그룹핑 연산자를 작성하면 표현식에 function을 작성한 것이므로 문법 에러가 발생하지 않음
즉, (1+2)에서 1+2 대신에 함수를 작성한 것
3. 표현식과 표현식 평가 결과는 평가 결과가 반환될 때까지 메모리에 저장하고 평가 결과를 반환하면 지워짐
4. (1+2)의 결과가 메모리에 저장된다면 매우 많은 메모리가 필요한 것
5. function(){}(); 코드로 만든 오브젝트도 메모리에 저장되지 않으며 실행 결과도 메모리에 저장되지 않음
6. 따라서 저장해야 할 것이 있다면 표현식 밖의 변수, 프로퍼티에 저장해야 함
7. 저장할 필요가 없는 1회성 코드이면서 엔진이 function 키워드를 만나는 시점에 즉시 실행해야 한다면
8. 그룹핑 연산자 안에 표현식으로 작성
9. 무명 함수는 그룹핑 연산자 안의 코드를 한 번만 사용할 때 사용. 주로 초기값을 설정할 때 사용
*/
Closure
[[Scope]]의 설정과 사용 방법을 이해하면 클로저는 단지 논리적인 설명
실행 콘텍스트: {
렉시컬 환경 컴포넌트: {
환경 레코드: {
선언적 환경 레코드: {}.
오브젝트 환경 레코드: {}
},
외부 렉시컬 환경 참조: {}
}
}
실행 중인 function 오브젝트에
[[Scope]]의 변수, 함수를
function book(){
var point = 100;
var getPoint = function(param){
point = point + param;
return point;
};
return getPoint;
};
var obj = book();
log(obj(200));
// 300
var obj = book();
실행 준비 단계
실행 콘텍스트(EC) 생성
3개의 컴포넌트 생성
function 오브젝트의 [[Scope]]를
<여기까지 모습>
실행 콘텍스트 = {
렉시컬 환경 컴포넌트 = {
환경 레코드: {
선언적 환경 레코드: {},
오브젝트 환경 레코드: {}
},
외부 렉시컬 환경 참조: {[[scope]]}
},
변수 환경 컴포넌트 = {Same}
this 바인딩 컴포넌트: {}
}
초기화 및 실행 단계
var point; var getPoint;
var point = 100;
var getPoint = function(param){코드};
getPoint 오브젝트 모습
렉시컬 환경 컴포넌트 = {
환경 레코드: {
선언적 환경 레코드: {}.
},
외부 렉시컬 환경 참조: {
point: 100
}
}
return getPoint;
var obj = book();
console.log(obj(200));
클로저와 관련된 부분
실행 콘텍스트(EC) 생성
<여기까지 모습>
렉시컬 환경 컴포넌트 = {
환경 레코드: {
선언적 환경 레코드: {
param: 200
},
},
외부 렉시컬 환경 참조: {
point: 100
}
}
함수 안의 코드 실행
point = point + param;
point를 선언적 환경 레코드에서 식별자 해결
param을 선언적 환경 레코드에서 식별자 해결
100과 200을 더해 외부 렉시컬 환경 참조의 point에 할당
15. 이것이 클로저 논리
무명 함수 안에 작성한 값, 함수는
클로저 활용
var book = (function(){
var point = 100;
function getPoint(param){
return point + param;
};
return getPoint;
}());
log(book(200));
// 300
function getPoint(param){...}
return getPoint;
console.log(book(200));
function getPoint(param){
return point + param;
};
함수에서 함수 밖의 변수 사용은
논리적 근거는
클로저는 이를 나타내는 용어