eval vs. Function

프로그래밍 2008. 1. 24. 00:06
구글그룹스의 jquery 포럼을 메일로 받아보는데  재미있는 질문이 올라왔다.

어떤 친구의 질문은  jquery을 보면서 공부하고 있는데  fn = eval("false||function(elem){return " + fn + "}");
이런 문법이 있다. 왜 n = Function('elem', 'return '+fn)  이렇게 하지 않고 위와 같이 했냐라는 질문이였다.

처음에 이 질문을 보고 갑자기 나도 왜 위와 같이 했을까 라는 고민을 했다.

eval("false||function(elem){return " + fn + "}"); 이 문장을 보며 의아해 했던 것은 두가지 인데
첫번째왜 Function을 사용하지 않았나?
두번째앞부분에 false||을 사용했는가? 이다.

그래서 jquery를 받아서 eval("false||function(elem){return " + fn + "}"); 이 부분을 찾아봤다.
솔직히 이해를 잘 못했다.(내공 부족)-_-;;
그러다 포럼의 John Resig을 비롯하여 다른 사람들이 올린 글을 보니  이해하기 쉬웠다.

결론은
첫번째Function으로 만들면 scope가 local scope가 아니라 global scope가 되기 때문이라고 한다.
즉 eval("false||function(elem){return " + fn + "}");는 함수 scope안에서 있는것들을 사용할수 있는데 Function은 global 변수를 사용해야 하기 때문이다.

두번째는 약간의 브라우져의 특성때문이다.
우리가 json을 string으로 받아서 보통 eval("("+json+")") 이렇게 처리하는 이유와 비슷하다. 그래서 처음에는 John Resig 위에 방법으로 하다가 ie,opera에서 안되서  어쩔수 없이 eval("false||function("+....+"}") 이와 같은 방법을 했다고한다.

하여간 오랫만에 건진 팁!





Posted by 전용우
,
난 dojo에 관심이 없어. 그냥 있었는데 오늘 보니 dojo에서 새로운 자바스크립트 압축기를 내놨다는 글을 봤다.
이건 일반적인 압축방법과 달라서 더 흥미롭게 봤다.

기존의 압축방식과 틀린 이유는 정규표현식으로 압축하지 않고 Rhino의 실제 파서를 이용하여 압축을 한다고 한다.

해당 페이지를 보면 압출률 또한 좋고 더욱 좋은것은 변수명을 변경해주므로서 보안상의 문제를 어느정도 해결한듯. 구글의 js를 보면 변수명이 변경되있는데 ShrinkSafe도 비슷한 효과를 내는것 같다.

음... 단점이자 장점일수 있는데 다른 압출툴과 달리 되돌릴 방법이 없다.

그리고 추후에는 Gzipping도 지원할것 같다.

그럼 배포의 최적화 조건인 Minifying, Obfuscating, Gzipping 이 3가지 조건이 다 만족하네.

다음은 압축된 모습 짤방.

사용자 삽입 이미지

짤방



Posted by 전용우
,
John Resig씨가 ecmascript4를 사용할수 있는 환경을 셋팅하고 간단한 사용법을 동영상으로 촬영을 했습니다.

아직까진 브라우져와 연결하여 사용할순 없고 (구현중 이랍니다.그래서 브라우져에서 지원하는 함수들은 사용할수 없습니다.)
일부 기능들 또한 사용할순 없지만 그래도 es4를 느끼기엔 충분한것 같습니다.

ecmascript4의 기능인 class, getter,setter, inheritance, interface, type annotation...등 을 직접 사용할수 있습니다.
그리고 아래 ppt을 보시면 좀더 자세한 es4의 내용들을 볼수 있습니다.
아래 ppt는 얼마전에 John Resig씨가 포스팅한 ECMAScript 4 Speaking Tour 중 하나입니다.아니면 이곳에 가셔서 es4의 스펙을 확인하고 연습하시면 재미있을 것 같습니다.^^;;


Posted by 전용우
,
JSSpec 토글링 기능 추가 됬으면 좋겠습니다.
필요해서 만들었는데 나중에 비슷한 기능 추가 해주세효.

ps. 아주 잘쓰고 있습니다.^^


javascript(onload시 추가)
document.getElementById('log').childNodes[1].onclick = function(e){
            var currentElement;
            if(e){
                currentElement = e.target;
            }else{
                e = window.event;
                currentElement = e.srcElement;
            }
            while(currentElement.nextSibling.nodeType!=1){
                currentElement = currentElement.nextSibling;
            }
            currentElement.nextSibling.style.display = (currentElement.nextSibling.style.display=="none")?"block":"none";
};

css
ul.specs li h3 {
    font-weight: bold;
    font-size: 0.75em;
    padding: 0.2em 1em;
    cursor:pointer;(추가)
}
Posted by 전용우
,

Bad smell

프로그래밍 2007. 9. 30. 23:44
  • 중복된 코드
  • 긴 메소드
  • 거대한 클래스
  • 긴 파라메터 리스트
  • 확산적 변경
  • 산탄총 수술
  • 기능에 대한 욕심
  • 데이터 덩어리
  • 기본 타입에 대한 강박관념
  • Switch 문
  • 평행 상속 구조
  • 게으른 클래스
  • 추측성 일반화
  • 임시 필드
  • 메시지 체인
  • 미들 맨
  • 부적절한 친밀
  • 다른 인터페이스를 가진 대체 클래스
  • 불완전한 라이브어리 클래스
  • 데이터 클래스
  • 거부된 유산
  • 주석


Posted by 전용우
,
오늘 Lazy Function Definition Pattern 이란 글을 읽었는데 도움이 될것 같아 정리해둔다.

Lazy Function Definition Pattern은 많은 언어도 있지만 늦은 초기화랑 비슷하다.
필요할때 생성하고 그 이후에는 재활용하는것을 말한다.

피터씨는  이와 같은 패턴을 Lazy Function Definition Pattern이라고 한다.
자바스크립트에서 이 기법을 구현하는데는 많은 방법이 있는데 여기에서는 4가지 방법을 소개하고 최적의 방법을 알려 준다.

문제는, foo라는 함수는 호출을 하면 data객체를 반납하는데 처음에 호출시에만 date를 생성하고 다음 호출에는 재활용해야한다. 이러한 foo함수를 만드는것 문제이다.

1.고전 적인 방법.


var t;
function foo(){
    if(t){
       return t;
    }
    t = new Date();
    return t;
}

이 방법에는 두가지 문제가 있다.
첫번째는 여분의 t라는 글로벌 변수를 사용해야 한다.
두번째는 실행시 코드가 최적화 되어있지 않다. 즉 매번 if문을 실행 해야한다.

2.묘듈 패턴.(The Module Pattern)

var foo = (function() {
    var t;
    return function() {
        if (t) {
            return t;
        }
        t = new Date();
        return t;
    }
})();

묘듈 패턴으로 첫번째 문제는 해결할수 있다.클로우져(closure) 이용하여 글로벌 변수 t를 숨기고  오직 foo에서만 사용할수 있게 했다.
하지만 이 패턴으로는 두번째 문제를 해결할수 없다. 좋은 패턴이긴 하지만 여기에서는 유용하지 않다.

3.함수는 오브젝트(Functions are Objects)
function foo() {
if (foo.t) {
return foo.t;
}
foo.t = new Date();
return foo.t;
}
자바스크립트에서는 모든 함수는 오브젝트이다. 그렇기 때문에 프로퍼트를 가질수 있고 위와 같은 방법을 사용할수 있다. 이 방법은 매우 깔끔하고 보기는 좋은나 여전히 두번째 문제는 조건절을 해결하지 못했다.
(이 방법은 원래 있던 프로퍼티를 있는 듯 사용하고 있어서 나중에 모르는 사람이 봤을때 많이 헤갈리는것 같았다. 개인적으로 비추.)

4. Lazy Function Definition
이글의 저자인 피터씨가 추천하는 방법이다.

var foo = function() {
    var t = new Date();
    foo = function() {
        return t;
    };
    return foo();
};

이 방법의 원리는 클로우져를 이용한 방법이다.
처음 foo를 실행했을때 처음 t에 Date가 할당되고 foo함수에 클로우져가 할당되고 Date를 반환한다. 그 다음 호출할때는 foo에 할당된 클로우져를 호출하여 바로 Date를 반환한다.
이 방법이 이해가 되지 않는다면 이글을 참조하면 될것 같고 하지만 이글과 다른게 이 방법은 의도적으로 사용했다는 점이다.
Posted by 전용우
,
얼마 전에 블로고스피어을 떠들석하게 했던 google gear~
Choosing an Offline Application Architecture에  흥미로운 것들이 있다.
어떻게 오프라인 어플리케이션을 구축할것인가?

UI개발자로서 너무나 흥미로운글. 전에 고민했던 내용들이 있다.
오프라인과 온라인 어플이 같아야할까? 싱크를 어떤식으로 맞추는것이 좋은 방법인가? 등등..
언제나 트레이드오프는 존재한다. 어떻게 효율적으로 오프라인을 구성해야하는가?

ps.음..UI개발은 아무리 생각해봐도 재미있는것 같다.
왜 UI개발을 천대받는지 모르지만 정말 재밌는 직군이다~
개발도 할줄 알아야하지, 디자인 감각도 있어야하지, 심리학,사회학 등등 할줄 알아야하는 만능 엔터테이너~
빨리 빨리 공부하자!!!!!
Posted by 전용우
,
스크립트을 쓰다보면 제일 난감한 것이 디버깅이다.
물론 firefox에서는 상당한 수준의 디버깅 툴인 firebug가 있기 때문에 다행이고 opera등 타 브라우져도 그럭저럭 괜찬은 수준의 디버깅툴을 지원하고 있다.하지만 제일 디버깅 하기가 난감한 브라우져는 ie....난감할때가 많다. 물론 ie developer tool을 제공하고 기타 visual studio와 연동되어 에러시 해당 부분을 알려주는 등 많이 편해지긴 했으나 아직은... 불편하다.

그러다 몇일전 우리 팀의 한분인 태곤씨에게서 ie pro를 추천받았다.
ie pro는 간단히 말하면 ff의 장점인 user script,plug in 등 기타 부가기능을 사용할수 있게 해주는 add on 프로그램이다.

이것 저것 살펴보다가 plugin 쪽에 firebug lite++를 확인했다.firebug lite++는 firebug lite를 확장한것 같았다. firebug lite는 간단히 ff뿐만이 아니라 타 브라우져에서도 firebug의 적은 기능을 사용할수 있게 하는 툴이다.
(물론 사용하기엔 아직 많이 부족하다.)

그러나 firebug lite++는 설명에 보면 괜찬을것 같아 한번 설치 해봤다.
  1. 먼저 ie pro을 설치하기(브라우져 닫고 다시 열어야함.)
  2. firebug lite++ user script 설치하기
  3. firebug user plug in 다운 받기.
    1. plug in을 다운 받은후 압축을 푼후에 나온 파일확장자를 다시 zip을 수정후 다시 압축을 풀어야한다.
  4. 플러그인 폴더(C:\Program Files\IE7Pro\plugins)에 폴더 만들고  안에 3개(js 1개,png 2개)을 넣고 브라우져를 닫고 다시 열면됨.
위와 같이 설치했다면 아래와 같이 firebug lite++단추와 ie pro단추가 보인다.
iepro&firebug lite++설치화면

그리고 초록색 버튼을 클릭하게 되면 아래와 같이 나온다.

주요기능으로는 dom tree를 확인할수 있고 기본기능인 console과 dom tree에서 원하는 엘리먼트를 클릭하면 해당 엘리먼트의 프로퍼티들을 확인할수 있다. 그외의 기능은 아직 굉장히 블안하고 사용할만 하지 않다.

firebug lite++ 사용화면


아직은 많이 불안하긴 하지만 기존의 디버깅하는 방법과 같이 사용한다면 그리 나쁠것 같지 않다.

ps.별다른 debugger없이도 다들 잘 개발하던데 난 아직 멀었나보다..;;
Posted by 전용우
,
요즘 canvas공부 중인데 왜 width와 height를 인라인이 아닌 css파일로 따로 정의하면 x축이 반으로 줄어든다.

추측결과 먼저 canvas에 대한 script가 실행되고 그이후에 외부 css가 먹는것 같다.
음..하여간...삽질중..
Posted by 전용우
,

38장.Multibutton Form


폼에 submit버튼이 여러개 일때 해당버튼을 구분하는방법.

폼에 submit버튼은 모두 create로 간다.
그렇기 때문에 만약에 두개의 submit버튼이 있을때 구분을 하려고 하는데 그방법을 설명한다.
일반적으로는 parameter에 hash타입으로 commit:버튼명으로 가는데
만약에 rhtml에 <%= submit_tag 'Preview',:name => 'preview_button'%>이라고하면
parameter에 hash타입으로 preview_button:Preview으로 간다. 이렇게  :name 심벌을 이용하여 수정할수 있다.

39장.Customize Field Error


레일즈에서 유효성체크에서 오류가 났을때 해당필드를 원하는 형태로 보여주는 방법을 설명하고 있음.


레일즈에서는 기본적으로 validation을 해주는 기능이 있다.
그래서 값을 않넣거나 그러면 기본적으로 테두리에 빨간div를 감싸게 되는데
그것이 맘에 안든다면 environment.rb에서
ActionView::Base.field_error_proc=Proc.new do|html_tag,instance|
  "<span class='field_error'>#{html_tag}</span>"
do
이렇게 수정하고 css를 수정하면 자신이 원하는 대로 보일수 있음.
html_tag는 유효성검증이 안된 html tag가 들어오고 instance에는 error객체가 있음.
참고:How to Change Validation Error Display


40장.Blocks in View


블록을 포함한 helper메소드를 만들어 본다.

굉장히 유용한 팁인것 같다.
sample
# rhtml
<% admin_area do %>
<%= link_to "Edit Task", edit_task_path(@task) %>
<% end %>
# application_helper
def admin_area(&block)
concat('<div class="admin">', block.binding)
block.call
concat("</div>", block.binding)
end

41장.Conditional Validations


일반적으로 모든 유효성체크는 매번 검사하게 되어있다.
하지만 매번검사하는것을 원치 않을때는 :if => :some_method이렇게
조건을 주어서 조건에 맞는경우만 유효성 검사를 할수 있게 할수 있다.
sample
validates_presence_of :password, :if => :should_validate_password?
def should_validate_password?
  updating_password || new_record?
end



42장.with_options


보통 많은 레일즈 메서드는 마지막에 해시를 받게된다.
그런데 만약에 여러개의 매소드중에 해시로 받는 부분이 겹친다면 with_options으로
좀더 간단히 표현할수 있다.

sample
routes.rb에서 아래와 같다면
map.login 'login',:controller => 'session',:action=>'new'
map.logout 'logout',:controller => 'session',:action=>'destory'
아래와 같이 수정할수 있다.
map.with_options :controller => 'session' do |sessions|
  sessions.login 'login',:action=>'new'
  sessions.logout 'logout',:action=>'destory'
do
Posted by 전용우
,