2016년 10월 30일 일요일

[javascript patterns] 스터디 09


즉시 실행 함수

즉시 실행 함수 패턴: 함수 선언 직후 바로 실행되는 문법.
(function() {
  alert('바로 실행');
})();
이 패턴은 함수 표현식을 생성한 직후 실행시킨다. 일반 함수에 두개의 괄호가 붙었다. 붙은 위치를 보고 '아! 저렇게 하면 즉시 실행되는 구나!' 하고 느끼기 바란다. 사실 비슷하지만 다르게도 즉시실행을 할 수 있다.
(function() {
  alert('바로 실행');
}());
별 차이는 없다. 하지만 JSLint는 이놈을 더 좋아한다고 한다. 이것을 언제 쓸까? 페이지 로드가 완료 되었을 때, 기본적으로 이벤트 핸들러를 연결하는 등의 초기 설정 작업을 한다. 이런 것들을 사용할 때 이름을 하나하나 전역에 붙였다가는 더러워질 수 있을 것이다.(재사용할 것이 아니기 때문)
(function () {
  var days = ['일요일', '월요일', '화요일', '수요일', '목요일', '불금세일', '토요일'],
      today = new Date(),
      msg = 'Today is ' + days[today.getDay()] + [, ] + today.getDate();
  alert(msg);
}()); 

즉시 실행 함수의 매개변수

(function (who, when) {
  alert(when + ' ' + who + '와 약속이 있습니다.');
}('아무개씨', new Date()));
일반적으로 전역 객체가 즉시 실행 함수의 인자로 전달된다. 즉 window를 쓰지 않고 전역 객체에 접근할 수 있다. 이런 방법으로 브라우저 외에서도 코드를 사용할 수 있다. 잘보라
(function (global) {
  // 전역 객체르 'global'로 참조 하는데 브라우저 상에서는 window였지만 다른 곳에서는 아닐 수도 있는 법
  console.log(global); // Window 객체가 뜰 것이다.
}(this));
다음 글에 이어서 하도록 하자.

2016년 10월 29일 토요일

[Mathematics for Computer Science] 스터디 05

Axioms

Axiom은 공리, 자명한 이치이다.
An axiom is a proposition that is assumed to be true, because you believe it is somehow reasonable.
Axiom 1. If a = b and b = c, then a = c. 우리가 아주 잘 아는 Axiom이다. A가 B이고 B가 C라면, A = C 이다.

2016년 10월 22일 토요일

[Mathematics for Computer Science] 스터디 04

지난 시간에 이어서 truth table에 대해서 알아보도록 하자.
다른 함의(implication)의 예시를 보자.
만약 개가 날 수 있다면, 당신은 토익을 만점 받을 거야.
장난스럽지만 이건 참이다. 설사 지금 당신이 토익이 뭔지 모른다 하여도! 왜냐하면? 만약 개가 날 수 있다면 이 거짓이기 때문에!! 자 truth table을 한 번 보라. P⇒Q 일때 P가 FALSE 이면 Q는 항상 TRUE 라는 것을!(P⇒Q is always true when P is false.)
truth table이 마음에 들지 않을 수도 있겠다. 우리가 실제로 생각하는 if-then statements는 다른 것일 텐데 말이다. 그런데 실제 수학에서는 많이 쓰이는 듯 하다.

실망하지 말자 우리가 생각하는 가정문이 곧 나온다.

Proposition 8. ∀n ∈ ℤ (n≥2) ⇔ (n2≥4)
A proposition of the form P ⇔ Q is read "P if and only if Q". (Sometimes "if and only if" is abbreviated "iff".) This proposition is true provided P ⇒ Q and Q ⇒ P are both true. Here is a truth table that compares all these kinds of implication:
"iff"라고 불리는 이것이 당신들이 찾던 그것이다. 이것은 P ⇒ Q, Q ⇒ P 둘 다 true일 때 true이다.

2016년 10월 19일 수요일

[javascript patterns] 스터디 08

자기 자신을 정의하는 함수

함수는 동적으로 정의할 수 있고 변수에 할당할 수 있다. 새로운 함수를 만들어 이미 다른 함수를 가지고 있는 변수에 할당한다면, 새로운 함수가 이전 함수를 덮어쓰게 된다. (그러니까 이미 존재하는 함수가 있어도 덮어쓴다는 말)
어떻게 보면 함수 포인터를 재사용하는 것이다. 자기 자신을 정의하는 함수은 자기 자신을 덮어써서 재정의(재사용)하는 것이다.
var run = function() {
  alert("run!");
  run = function() {
    alert("run faster! ");
  }
}

// 자기 자신을 정의하는 함수를 사용
run(); // run!
run(); // run faster!
이 패턴은 함수가 어떤 초기화 준비 작업을 단 한 번만 수행할 경우에 유용하다(한 번쓰고 바로 덮어씌어지기 때문에). 단점은 자기 자신을 재정의한 후, 원본 함수에 추가했던 프로퍼티들을 모두 찾을 수 없다. 또한 객체의 매서드로 사용되면 처음 실행할 때 처음 것이 실행될 수도 있다.(다른 변수에 할당 되었을 시에도 동일)
이 함수를 일급 객체로 사용하는 예를 살펴보자.
// 새로운 프로퍼티 추가
var run = function() {
  alert("run!");
  run = function() {
    alert("run faster! ");
  }
}
run.property = '일급객체로 사용한다.';

// 1. 다른 이름으로 할당한다.
var go1 = run;

// 2. 메서드로 사용한다.
var go2 = {
  a : run
};

// 새로운 이름으로 호출
go1(); //"run"
go1(); //"run"
console.log(go1.property); // '일급객체로 사용한다.'

// 메서드로 호출
go2.a(); // "run"
go2.a(); // "run"
console.log(go2.a.property); // '일급객체로 사용한다.'

// 자기 자신을 재정의한 함수
run();
run();
console.log(run.property); // undefined
함수가 새로운 변수에 할당되면 예상과 달리 자기 자신을 정의하지 않는다. 이 호출들은 계속해서 전역 run() 포인터를 덮어 쓴다. 따라서 마지막에 전역 run()가 호출되었을 때 비로소, 변화된 것이 갱신된다.

[javascript patterns][타임아웃] 스터디 07

또 다른 콜백 패턴의 예제는 window객체의 setTimeout(), setInterval()이다.
예시
var delay = function() {
  console.log('500ms later...');
};
setTimeout(delay, 500);

delay가 괄호없이 변수로 전달된 점에 주의하자. 곧바로 실행하지 않고 포인터만을 전달하는 것이다. 함수포인터 대신 문자열 "delay()"를 전달하는 것은 eval()과 비슷한 안티패턴이다.

2016년 10월 18일 화요일

[javascript patterns][비동기 이벤트 리스터]스터디 06

콜백 패턴은 이미 일상적으로 사용되고 있다. 예를 들어 페이지의 엘리먼트에 이벤트리스터를 붙이는 것, 실제로는 이벤트가 발생했을 때 호출된 콜백 함수의 포인터를 전달하는 것이다.
예시
document.addEventListener("click", console.log, false);

대부분의 클라이언트는 event-driven 방식이다. 페이지 로딩이 끝나면 load 이벤트를 발생시킨다. 사용자는 click, keypress와 같은 이벤트들을 발생시킨다.
자바스크립트가 이런 프로그래밍에 잘 맞는 것은 콜백패턴 때문이다.(비동기적으로 그때그때 동작하는 것이 달라질 것)

2016년 10월 16일 일요일

[javascript patterns][콜백과 유효범위]스터디 05

한번 단순하게 사용해보자.
  1. 첫번째 리스트
  2. 두번째 리스트
  3. 세번째 리스트
  4. 네번째 리스트

여담인데 혹여 절대로 이 코딩을 따라하지는 않길...

2016년 10월 12일 수요일

[javascript patterns][콜백과 유효범위]스터디 04

이전의 예에서, 콜백은 이런 식으로 실행했다.
var a = function() {
  callback(parameters);
}
이 코드는 간단하고 대부분의 경우 훌륭하게 작동한다. 그러나 콜백이 일회성의 익명 함수나 전역 함수가 아니고 객체의 메서드인 경우도 많다.
var a = function() {
var myapp = {};
myapp.color = 'green';
myapp.paint = function (node) {
  node.style.color = this.color;
};

var findNodes = function(callback) {
  //...
  if (typeof callback === 'function') {
    callback(found);
  }
//...
};
findNodes(myapp.paint);

이러면 작동하지 않는다. findNodes(myapp.paint)를 호출하면 this.color가 정의되지 않아 예상대로 동작하지 않는다.
findNodes()가 전역 함수이기 때문에 객체 this는 전역 객체를 참조한다. findNodes()가 (dom.findNodes()처럼) dom이라는 객체의 메서드라면, 콜백 내부의 this는 예상과는 달리 myapp이 아닌 dom을 참조하게 된다.(this에 대해 자세히 공부를 해야함)

이 문제를 해결하려면, 콜백 함수와 콜백이 속해 있는 객체를 함.께. 전달하면 된다.

findNodes(myapp.paint, maapp);
var findNodes = function (callback, callback_obj) {
  //...
  if (typeof callback === 'function') {
    callback.call(callback_obj, found);
  }
  //...
};

이것을 바인딩(binding)이라고 하는데 저 위에 사용해본 call(), apply() 가 바인딩을 위해 사용되는 것인데, 나중에 더 공부해보도록 하자.

콜백으로 사용될 메서드와 바인딩할 객체를 전달할 때, 메소드를 문자열로 전달 할 수도 있다. (이렇게 하면 객체를 두 번 반복하지 않아도 된다. 무슨말이냐면!

findNodes(myapp.paint, myapp);
여기서
findNodes("paint", myapp);
이렇게 바꿀 수 있는데, 이 두 방법에 모두 대응하는 findNodes()를 만드려면?!
var findNodes = function (callback, callback_obj) {
  if (typeof callback === 'string') {
    callback = callback_obj[callback];
  }
  //...
  if (typeof callback === 'function') {
    callback.call(callback_ovj, found);
  }

[javascript patterns][콜백함수]스터디 03


  • First List
  • Second List
  • Third List
  • Fourth List

[javascript patterns][콜백함수]스터디 02

노드를 숨기는 로직의 실행을 콜백 함수에 위임하고 이 함수를 findNodes()에 전달한다.
b(a)
// findNodes()가 콜백을 받도록 리팩터링한다.
var findNodes = function (callback) {
  var i = 10000,
      nodes = [];

  // 콜백 함수를 호출할 수 있는지 확인한다.
  if (typeof callback !== "function") {
    callback = false;
  }

  while(i) {
    i -= 1;
    // 이곳에 복잡한 로직을 구현한다.예를들어
    nodes[i]=i;

    // 여기서 콜백을 실핸한다.
    if (callback) {
     nodes[i] = callback(nodes[i]);
    }
    nodes.push(nodes[i]);
  }
  return nodes;
};
이 구현 방법은 직관적이다.
findNodes()에는, 콜백 함수가 추가되었는지 확인하고, 있으면 실행하는 작업 하나만 추가되었다. 콜백은 생략할 수 있기 때문에 리팩터링된 findNodes()는 여전히 이전과 동일하게 사용할 수 있고, 기존 API에 의존하는 코드를 망가뜨리지 않는다.
루프를 돌 필요가 없어진 hide()를 보라.
//콜백 함수
var hide = function (node) {
  node = "none";
};

//노드를 찾아서 바로 숨긴다.
findNodes(hide);

//또는 익명 함수를 바로 사용할 수 있다.
findNodes(function (node) {
  node = "none";
});
다음 글에는 실제로 콜백을 DOM에 써보자.

[javascript patterns][콜백함수]스터디 01


함수

자바스크립트의 함수를 특별하게 만드는 두 가지 중요한 특징이 있다.
1. 함수는 일급(first-class) 객체다.
2. 함수는 유효범위(scope)를 제공한다.
 - 런타임, 즉 실행 중에 동적으로 생성할 수 있다.
 - 변수에 할당, 참조,확장가능하고, 몇몇 특별한 경우를 제외하면 삭제할 수 있다.
 - 자기 자신의 프로퍼티와 메소드를 가질 수 있다.

콜백 패턴

함수는 객체다. 즉 함수를 다른 함수에 인자로 전달 할 수 있다.

var a = function() {
return 1+1;
}
var b = function getSquare(a) {
  return a()*a();
}
b(a)
4
예제를 한 번 살펴보자. 처음에는 콜백 없이 시작하여 리팩터링 하는 것과 비교를 할 것이다. 복잡한 작업을 수행한 후 그 결과로 대용량 데이터셋을 반환하는 범용함수가 있다고 하자.

var findNodes = function() {
  var i = 100000,
          nodes = [],
          found;
  while (i) {
    i -= 1;
    // 복잡한 작업이 있다 가정
    nodes.push(found);
  }
  return nodes;
};
범용함수니까 아무 작업도 하지 않고 DOM 노드의 배열을 반환하기만 하도록 하자. 로직은 다른 곳에 두어서 로직에만 신경쓸 수 있도록. hide()라는 함수로 해당 배열을 죄다 숨겨보자. 그리고 여기는 예시이기 때문에 값이 변화한 것인지 아닌지 확인 차 리턴을 해보자.

var hide = function (nodes) {
  var i = 0, max = nodes.length;
  for (; i < max; i += 1) {
    nodes[i] = "none";
  }
  return nodes;
};
var res = hide(findNodes());
res[0];
"none"
res[1];
"none"
  이것은 findNodes()에서 반환된 노드의 배열에 대해 hide()가 다시 루프를 돌아야 하기 때문에 비효율적이다. findNodes()에서 노드를 선택하고 바로 숨긴다면 재차 루프를 돌지 않아 더 효율적일 것이다. 그런데 그렇게 하면 분리를 한 의미가 사라진다. 이럴때 콜백함수가 사용된다. 콜백함수는 다음 페이지에 적겠다.

2016년 10월 11일 화요일

[누구나 쉽게 배우는 클로저] 스터디 3

맵 : 그냥 해시맵이라 생각하자 하지만 clojure 세미나에서 보니 clojure의 해시맵은 꽤나 많은 고민을 하여 알고리즘을 선정하여 구현했다고 한다.

맵을 한 번 만들어 보자.
{}
끝. 이게 맵이다.

{:a "aaa" :b "bbb"}
여기서 :a는 키워드라고 하는데 키워드는 말그대로 키워드다.
{:더하기 +}
이러면 :더하기 라는 키워드(문자열아님)에 + 함수를 연결한 것이다.
{:a {:aa "숨겨진 값"}}
컬렉션 안에 컬렉션이 들어있는 느낌으로 감을 익혀라. (map안에 map이 있는 것)

map에서 값을 꺼내보자
(get {:A 1 :B 2} :A)
;=1
(get {:A 1 :B {:C "맵안에 맵!"}} :B)
;={:C "맵안에 맵!"}

감이 오는가? 많은 것을 배우려고 하지말자. 어떤 느낌인지 감을 느껴라. 리듬을 타라. 고개를 끄덕이며 '아 이런 느낌이군!' 감만 익혀라. 그러면 어떤 책이든 잡고 공부할 수 있다. (하지만 나도 공부하는 중이니 내 말은 듣지말도록...)

만약 값이 없다면?? (감이 있는 사람은 뭐가 나올지 알겠지.)
(get {:a "ㅎㅎㅎ"} :b)
;=nil

(get {:a "ㅎㅎㅎ"} :b "디폴트값 값이 없으면 이놈이 나오지")
;="디폴트값 값이 없으면 이놈이 나오지"

잠깐 그런게 맵.안.의.맵.의.값. 은 어떻게 가져오지?

(get (get {:A 1 :B {:C "날 뽑아낼 수 있을까?"}} :B) :C)

이걸 보는 순간 이제 리스프형의 프로그래밍이 어떻게 되는지 알 것이다. 반환하는 것을 감싸고 감싸고 감싸고.... 또 감싸다보면 상상하는 모든 일들이 벌어지는 것이다. 하지만 일단 코딩을 하기 전에 검색을 하는 버릇을 가지자. 저렇게 계속 get을 두번 사용하는 것보다 더욱 아름다워 보이는 방법이 있다.

(get-in {:A 1 :B {:C "날 뽑아낼 수 있을까?"}} [:B :C])

그리고 get이 없이 할 수도 있다.

(:C (:B {:A 1 :B {:C "날 뽑아낼 수 있을까?"}}))

왜 그런진 잘 모름. 키워드도 함수처럼 사용되는 느낌? 좀 더 내공이 쌓이면 완벽하게 이해를 할 수 있을지도...? 없을지도...

[javascript patterns][콜백함수]스터디 03


  • First List
  • Second List
  • Third List
  • Fourth List