2012년 1월 27일 금요일

Array function - Iteration

이것만은 꼭 알고 이해하고 손에 익숙해두자.

forEach : 배열의 갯수만큼 반복
map : return 값을 인자로 배열을 반환
reduce : return 값과 배열을 인자로 연산
some : return 이 하나라도 참이면 참을 반환
every : return 이 모두 참이면 참을 반환
sort : return 이 참인 기준의 순방향 정렬
filter : return 이 참인 것들의 배열을 반환

배열을 만들고 직접 돌려보고 느껴보자.
reduce 로 sum, min, max를 한다던가
every 로 transaction처리를 한다던가 하는 걸 예로 들면 사고의 폭이 좁아질 수도 있으니
돌려보면서 현상을 관찰하는게 좋다.

기타 함수
concat : 배열들을 연결
indexOf : 인자의 위치를 반환
join : 인자로 배열들을 연결
slice : from<to 범위의 배열을 반환
splice : from에서 n개만큼 배열을 잘라내고 그 부분을 반환
push, pop : 배열의 뒷쪽에 넣고 빼기
unshift, shift : 배열의 앞쪽에서 넣고 빼기


2012년 1월 25일 수요일

requery 를 피하는 법

객체를 생성 후 생성한 객체를 다시 참조하는 패턴으로

$('div#mainContext').append('<div class="header"/>');
$('div.header').click(function() {
  // do something
});

이런 식으로 흔히들 쓰는데 $('div.header') 를 도는 비용이 많이 드니

$('<div class="header"/>').appendTo('div#mainContext').click(function() {
  // do something
});

으로 순서를 바꿔서 객체를 chaining으로 활용하자.

object-literal을 이용한 패턴

Object-literal은 아래처럼 new Object() 대신

var car = new Object();
car.goes = "far";

심플하게 JSON인

var car = {goes: "far"};
를 사용하는 패턴인데

$().ready(function() {
  $('#submit').click(function() {
    $('.container').slideUp(function() {
      // do something
    });
  });
  $('#navBar').bind('swipeleft', function() {
     // do something
  });
});

무기명 함수를 사용할 경우 흔히 발생하는 콜백 패크맨 형태를 정리하는데 사용할 수 있다.
사용 방법은 간단하다.
var app = {
  onReady: function() {
    $('#submit').click(app.onSubmit);
    $('#navBar').bind('swipeleft', app.onSwipeLeft);
  },
  onSubmit: function() {
    $('.container').slideUp(app.afterSlideUp);
  },
  afterSlideUp: function() {
    // do something
  },
  onSwipeLeft: function() {
    // do something
  }
};
$().ready(app.onReady);

콘솔 테스트나 유닛 테스트를 하기에도 편하고 가독성도 낫다.

2012년 1월 20일 금요일

Dijkstra's algorithm을 이용한 최단 경로 찾기를 javascript 로 구현해보았다.

여기가 위키.

언제나처럼 소스는 http://jsbin.com/acatav/3/edit#javascript
"최단경로 그까이꺼 대충 트리로 펼친 담에 올 합산한 비용이 젤 적은 놈 뽑아내면 되는거 아니야?"
라고 생각했다가 역시 검색이 최고. 나보다 멍청한 놈은 좀처럼 없다는 것이 진리.
알고리즘은 심플하다.
'자신과 인접한 노드와 이제까지 탐색한 노드 중 가까운 놈만 남기고 다 지운다.'의 반복.
node 에서 해보려면 맨 마지막 $('p')부분을 지워주시면 되겠다.
사용예는 다음과 같다.
computePath(vertices, vertices[0]);
vertices 중 0번째부터 출발하는 최단 경로를 계산해서 각 vertex별 previous 와 minDistance를 넣어준다.
node.js 에서 바로 돌려볼 수 있는 소스는 다음과 같다.

var vertex = function(param){
  var name = '';
  var edge = [];
  var minDistance = 99999;
  var previous = null;
  name = name || param.name;
  edge = edge || param.edge;
  minDistance = minDistance || param.minDistance;
  previous = previous || param.previous;
  return {
    "name" : name,
    "edge" : edge,
    "minDistance" : minDistance,
    "previous" : previous
  };
};
var vertices = [];
vertices.push(new vertex({"name" : 'Harrisburg'})); // Baltimore,Allentown
vertices.push(new vertex({"name" : 'Baltimore'})); // Harrisburg
vertices.push(new vertex({"name" : 'Washington'})); // Baltimore
vertices.push(new vertex({"name" : 'Philadelphia'})); // Baltimore,Allentown,New York
vertices.push(new vertex({"name" : 'Binghamton'})); // Allentown
vertices.push(new vertex({"name" : 'Allentown'})); // Harrisburg,Philadelphia,Binghamton,New York
vertices.push(new vertex({"name" : 'New York'})); // Philadelphia,Allentown
vertices[0].edge = [{
      "id" : vertices[1],
      "distance" : 79.83
    },{
      "id" : vertices[5],
      "distance" : 81.15
    }];
vertices[1].edge = [{
      "id" : vertices[0],
      "distance" : 79.75
    },{
      "id" : vertices[2],
      "distance" : 39.42
    },{
      "id" : vertices[3],
      "distance" : 103.00
    }];
vertices[2].edge = [{
      "id" : vertices[1],
      "distance" : 38.65
    }];
vertices[3].edge = [{
      "id" : vertices[1],
      "distance" : 102.53
    },{
      "id" : vertices[5],
      "distance" : 61.44
    },{
      "id" : vertices[6],
      "distance" : 96.79
    }];
vertices[4].edge = [{
      "id" : vertices[5],
      "distance" : 133.04
    }];
vertices[5].edge = [{
      "id" : vertices[0],
      "distance" : 102.53
    },{
      "id" : vertices[3],
      "distance" : 62.05
    },{
      "id" : vertices[4],
      "distance" : 134.47
    },{
      "id" : vertices[6],
      "distance" : 91.63
    }];
vertices[6].edge = [{
      "id" : vertices[3],
      "distance" : 97.24
    },{
      "id" : vertices[5],
      "distance" : 87.94
    }];
var computePath=function(vertices, source) {
  source.minDistance = 0;
  var vertexQueue = [source];
  while (vertexQueue.length) {
    var u = vertexQueue.shift(0);
    console.log('-----');
    console.log(u.name);
    u.edge.forEach(function(v,k) {
      var distanceThroughU = u.minDistance + v.distance;
      console.log('    ', v.id.name + ':'+distanceThroughU+'<'+v.id.minDistance + 
                  (distanceThroughU < v.id.minDistance ? '' : '(out)' ));
      if(distanceThroughU < v.id.minDistance) {
        v.id.minDistance = distanceThroughU;
        v.id.previous = u;
        vertexQueue.push(v.id);
      }
    });
  }
};
computePath(vertices, vertices[0]);
vertices.forEach(function(v) {
  var path = [];
  var current = v.previous;
  while(!!current) {
    path.push(current);
    current = current.previous;
  }
  var result = v.name+':'+path.map(function(w) {
    return w.name;
  }).reverse().join('->')+'=>'+v.name+'('+v.minDistance+')';
  console.log(result);
});

2012년 1월 9일 월요일

jQuery vs Native

http://sharedfil.es/js-48hIfQE4XK.html 내용.
맘에 들어서 퍼옴.
포인트는 querySelector 같은게 IE 에서 되면 뭐다러 jQuery selector를 쓰냐
forEach가 먹으면 뭐하러 귀찮게 $.each를 쓰냐.
이게 다 IE 때문이다. 그래서 jQuery 를 쓴다.
jQueryJavaScript
$(document).ready(function() {  // code…});
document.addEventListener("DOMContentLoaded", function() {  // code…});
var divs = $("div");
var divs = document.querySelectorAll("div");
var newDiv = $("<div/>");
var newDiv = document.createElement("div");
newDiv.addClass("foo");
newDiv.classList.add("foo");
newDiv.toggleClass("foo");
newDiv.classList.toggle("foo");
$("a").click(function() {  // code…})
[].forEach.call(document.querySelectorAll("a"), function(el) {  el.addEventListener("click", function() {    // code…  });});
$("body").append($("<p/>"));
document.body.appendChild(document.createElement("p"));
$("img").filter(":first").attr("alt", "My image");
document.querySelector("img").setAttribute("alt", "My image");
var parent = $("#about").parent();
var parent = document.getElementById("about").parentNode;
var clonedElement = $("#about").clone();
var clonedElement = document.getElementById("about").cloneNode(true);
$("#wrap").empty();
var wrap = document.getElementById("wrap");while(wrap.firstChild) wrap.removeChild(wrap.firstChild);
if($("#wrap").is(":empty"))
if(!document.getElementById("wrap").hasChildNodes())
var nextElement = $("#wrap").next();
var nextElement = document.getElementById("wrap").nextSibling;