이력

  • 2022.03.25 5절까지 포스팅
  • 2022.03.26 7절 제외하고 11절까지 포스팅

​모든 내용을 상세히 담으려 하지 않았습니다.
제가 모르는 부분이나, “이런 것도 있었어?” 하는 부분, 중요하다고 생각되는 부분,
다시 한번 되새기고 싶은 부분만 기록했습니다.
와.. 드디어 마지막 장이네요. 긴 여정이 끝났습니다. 고생한 나 자신에게 박수~!
읽어주셔서 감사합니다.

29.1 재귀 함수

29.2 오브젝트 프로퍼티 이동

  • 아래의 코드는 할당한 오브젝트를 참조하기 때문에 값이 연동됩니다.
1
2
3
4
5
var soccer = {member: 11};
var sports = soccer;
sports.member = 789;
js.log(soccer.member);
// 789
  • 값의 연동을 원하지 않을 때는 오브젝트가 아닌 프로퍼티 단위로 할당해야 한다.
1
2
3
4
5
6
7
8
var sports = {member: 11};
var dup = {};
for (var name in sports) {
  dup{name] = sports[name]
}
dup.member = 'abc';
js.log(sports.member);
// 11

29.3 JSON과 재귀함수

  • 재귀 함수를 이용해 복잡한 오브젝트를 프로퍼티 단위로 간단하게 복사할 수 있습니다. ​

29.4 함수 즉시 실행

  • 함수는 호출해야 실행되지만 즉시 실행 시키는 형태가 있습니다. 익명 함수라고 부릅니다.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var value = function() {
  return 123;
}();
js.log('자동 실행: ' + value);
// 123

value = (function() {
  return 456;
}());
js.log(value);
// 456

(function() {
  js.log('abc');
}());
// abc
// 소괄호는 그룹핑 연산자입니다. 그룹핑 연산자의 소괄호 안의 표현식을 평가하고 평가 결과를 반환합니다.
// 소괄호가 없으면 함수 이름이 없으므로 함수 선언문도 아니고, 변수에 할당하고 있지도 않으므로 함수
// 표현식이 아니라 에러가 발생합니다.

(function(param) {
  js.log(param);
  js.log(arguments[0]);
}(789));
// 789
// 789
  • 표현식과 표현식의 결과는 메모리에 저장되지 않습니다. ​

29.5 클로저와 자바스크립트 엔진 처리

  • 클로저는 js의 특징 기능을 지칭한 것입니다. 특정 기능이란 함수를 생성할 때 Function 오브젝트의 [[Scope]]에 렉시컬 환경을 설정하고 함수가 호출되었을 때 [[Scope]]에 설정된 프로퍼티를 사용하는 것입니다.
1
2
3
4
5
6
7
LE: {
  ER: {
    DER: xxx,
    OER: yyy,
  },
  OLER: [[Scope]]에 설정된 프로퍼티를 참조합니다.
}
  • [[Scope]]에 설정된 프로퍼티는 1단계 밖의 함수와 변수입니다.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
function sports() {
  var value = 100;
  function setValue(param) {
    value = param;
  };
  var getValue = function(param) {
    value = value = param;
    return value;
  }
  return getValue;
}
var getObject = sports();
debugger;

js.log(getObject(123));
js.log(getObject(77));

// 223
// 300
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
실행 준비 단계
1. EC를 생성합니다.
2. 파라미터 값을 갖고 EC안으로 이동합니다.
  - 파라미터 값: 호출한 함수가 속한 오브젝트, 함수 코드, 호출한 함수의 파라미터 값
3. 세 개의 컴포넌트를 생성합니다.
4. 파라미터로 받은 호출한 함수가 속한 오브젝트의 프로퍼티를 TBC에 설정합니다.
5. LE를 생성합니다.
6. 호출한 함수의 오브젝트의 [[Scope]]를 OLER에 설정합니다.
7. LE를 LEC와 VEC에 설정합니다.

초기화 및 실행 단계
1. 파라미터 값을 매핑하고 결과를 DER에 설정합니다.
2. 함수 선언문을 Function 오브젝트로 생성합니다.
3. 함수 코드의 처음으로 올라가 변수를 초기화하여 DER에 바인딩합니다.
4. 함수 코드의 처음으로 올라가 js 코드를 실행합니다.
5. DER의 value 프로퍼티에 100을 설정합니다.
6. getValue Function 오브젝트를 생성합니다.
7. getValue Function 오브젝트를 반환합니다.

fig.1

  • 멈춘 시점에 getValue 함수 안을 해석하지 않았으므로 getValue 함수에서 value 변수 사용 여부를 알 수 없습니다. 표시하려면 value와 setValue 함수를 모두 표시해야 합니다.
  • 개발자 도구에서 Closure를 표시할 때 getValue의 [[Scope]]와 getValue 함수안의 코드를 분석하여 표시한 것으로 생각됩니다. getValue 안에 setValue 함수를 호출하면 Closure 안에 setValue도 표시됩니다.
1
2
3
4
5
6
getObject 함수 실행
1. EC를 생성합니다.
2. getObject 함수의 [[Scope]]에 설정된 프로퍼티를 OLER에 설정합니다.
  - value와 setValue 함수를 사용할 수 있게 됩니다.
3. 파라미터 값을 매핑하고 결과를 DER에 설정합니다.
4. 함수 안의 코드를 실행합니다
  • 호출된 함수의 파라미터 이름도 클로저로 사용하 수 있습니다.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
function sports(one) {
  var value = 50;
  var getValue = function(two) {
    value = value + one + two;
    return value;
  }
  return getValue;
}
var getObject = sports(10);
console.log(getObject(20));
// 80

29.6 클로저와 무명함수

  • 앞 절 예제에서 sports 함수 안에서 getValue 함수를 반환하여 함수로 사용하므로 sports 함수는 의미가 없으며 Function 오브젝트로 저장할 필요가 없습니다. 이때 익명함수를 사용하면 효율적입니다.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
var getObject = (function() {
  var value = 100;
  var getValue = function(param) {
    value = value + param;
    return value;
  }
  return getValue;
}());

console.log(getObject(123));
// 100
  • (function(){}()) 형태는 function을 표현식으로 처리하므로 메모리에 남지 않아 다시 호출할 수 없습니다. 하지만 return getValue; 문장으로 함수를 반환하여 변수에 저장하면 getValue 함수를 호출할 수 있으며 Function 오브젝트의 [[Scope]]에 설정된 value 변수값을 사용할 수 있습니다.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var sales = (function(){
  var value = 100;
  function setValue(param){
    value = value + param;
  }
  var getValue = function(){
    return value;
  }
  return {
    setValue: setValue,
    getValue: getValue,
    getAverage: function(param){
      return value / param;
    }
  }
}());

sales.setValue(260);
console.log(sales.getValue());
console.log(sales.getAverage(30));

// 360
// 12
  • 변수는 외부에서 직접 접근하거나 this로 접근할 수 없으므로 함수를 호출하여 접근해야 합니다. 이를 통해 정보를 보호할 수 있으며 숨길 수 있습니다. 브라우저 개발자 도구에서는 볼 수 있습니다. 웹에서 정보의 숨김과 보호는 의미가 크지 않으며 정보가 노출된다는 전제하에 개발해야 합니다.

29.7 클로저와 인스턴스

29.8 메소드 체인

  • 메소드 체인은 시나리오(Use case)의 흐름대로 처리할 수 있는 방법을 제공한다.

29.9 사용자 정의 이벤트

29.10 HTML5 템플릿

  • HTML의 엘리먼트 대신에 자바스크립트로 템플릿으 만들어 사용할 수 있습니다.

29.11 자바스크립트 템플릿

  • js로 다양한 형태의 템플릿을 만들어 사용할 수 있습니다.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var data = [
  {'textClass': 'dataClass', text: 'text-1'},
  {'textClass': 'dataClass', text: 'text-2'},
  {'textClass': 'dataClass', text: 'text-3'}
]
var template = function(format) {
  this.template = format;
};

template.prototype = {
  template: /\{([\w-]+)?\}/g,
  match: function(data){
    return this.template.replace(this.templateExp, function(src, key) {
      return data[key];
    });
  }
};
var templateObj = new template('<div class="{textClass}">{text}</div>');
var markupList = [];
data.forEach(function(obj){
  markupList.push(templateObj.match(obj));
}, this);
document.getElementById('first').innerHTML = markupList.join('');
1
2
3
4
시나리오
1. new template()로 템플릿 인스턴스를 생성합니다.
2. data에 작성된 데이터를 하나씩 읽어가면서 템플릿에 적용합니다.
3. div#first 엘리먼트를 생성하고 innerHtml 속성에 배열의 문자열을 연결하여 설정합니다.