2012-12-05 4 views
0

이 조금 추상적 일 수 있지만 나는 다음과 같은 코드를 가지고 등 자바 스크립트 폐쇄의 둘레에 내 머리를 얻으려고 :이 자바 스크립트 클로저 생성을 피하는 것이 좋습니까?

function MyObj() { 
    var me = this; 

    this.foo = function(bar) { 
     // Do something with 'bar' 
    } 

    // Set up lots of local variables etc. 
    // .... 

    $(window).load(function() { 
     // Add a delegated click handler to specific <input> elements 
     $(document).on('click.myobj', 'input.special', function() { 
      // Do something with the <input> that triggered the click event 
      me.foo(this); 
     }); 
    }); 
} 

var myObj = new MyObj(); 

이가 클릭 이벤트에 바인딩에 전달 된 익명 함수는 클로저를 만듭니다 참조 번호 me.

$(window).load(function() { 
    // Add a delegated click handler to specific <input> elements 
    (function(localMe) { 
     $(document).on('click.myobj', 'input.special', function() { 
      // Do something with the <input> that triggered the click event 
      localMe.foo(this); 
     }); 
    })(me); 
}); 

이 더 나은 접근 방식인가, 아니면 폐쇄를 만드는 방법에 대해 지나치게 과민 오전 : 내가 알고 싶은이 (폐쇄을 피하기 위해) 대신 같은 것을 할 것이 낫다 여부? 또는 "세 번째 방법"이 있습니까?


또한 편집

, 이런 식으로 뭔가 할 더 나은 것 :

$(window).load(function() { 
    // Add a delegated click handler to specific <input> elements 
    $(document).on('click.myobj', 'input.special', {localMe : me}, function(event) { 
     // Do something with the <input> that triggered the click event 
     event.data.localMe.foo(this); 
    }); 
}); 
+0

그걸로 뭘 얻으려고합니까? – Philipp

+0

@Philipp, 나는 JavaScript closure를 만드는 것이 비쌀 수 있다는 인상하에있다. 추가 데이터가 범위 등을 추적하는 데 필요하기 때문이다.이 예에서 저축은 최소한 일지 모른다는 것을 인정하지만, 방법은 원칙적으로 * 더 좋습니다. – FixMaker

답변

1

후자는 (AFAIK)보다 효율적이지만, 엄격한 루프에서 사용하지 않으면 측정 할 수 없을 수도 있습니다.

이유는 모든 변수 역 참조가 범위 체인을 따라야하기 때문입니다. 후자의 경우 변수 localMe은 익명 함수의 매개 변수 목록에서 찾을 수 있습니다.

전자의 경우 변수는 그곳에 없지만 외부 범위에 있습니다. 스코프 체인을 가로 지르는이 추가 시간이 필요합니다. 대신 .apply 사용

var bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; }, 
    Object = (function() { 
     function Object() { 
      this.handler = bind(this.handler, this); 
      // Add a delegated click handler to specific <input> elements. 
      $(document).on("click.myobj", "input.special", this.handler); 
     } 

     Object.prototype.foo = function(bar) { 
      // Do something with "bar". 
     }; 

     Object.prototype.handler = function(event) { 
      // Do something with the <input> that triggered the click even. 
      return this.foo(event.currentTarget); 
     }; 

     return Object; 
    })(); 

var obj = new Object(); 

이 폐쇄 및 iifes의 사용을 건너 뜁니다 :

1

익명 기능은 대규모 이제 자바 스크립트 사용 (인수로와에 대한 즉각적인 기능 등을 범위/클로저). 성능 문제는 없습니다.

하지만 코드를 읽는 데 문제가있을 수 있습니다. 변수를 볼 때 변수의 출처를 확인해야하기 때문입니다. 그러나 큰 거래는 여기에 없다.

그리고 두 번째 예에서는 클로저가 여전히 "끊어짐"상태입니다. click의 익명 함수에서 localMe 변수를 사용하기 때문입니다. 그리고 localMe은 당신의 권위 밖의 명칭입니다.

// Here, 'me' is a direct local variable. 
$(window).load(function() { 
    // Here, we are in an anonymous fonction, so 'me' is not a direct variable anymore. But you still can access it. 

    // Add a delegated click handler to specific <input> elements 
    (function(localMe) { 
     // Here, 'localMe' is a direct local variable. 
     $(document).on('click.myobj', 'input.special', function() { 
      // We are in an anonymous function, so 'localMe' is not a direct variable anymore. 

      // Do something with the <input> that triggered the click event 
      localMe.foo(this); 
     }); 
    })(me); 
}); 

폐쇄 "차단"을 실제로 피하려면 개체에 함수를 바인딩해야합니다. 그러나 모든 브라우저가 기능에 대한 bind 메소드를 지원하지는 않습니다.

+0

아니요, 'localMe'는 내부 함수에 대한 매개 변수이므로 가장 가까운 가능한 범위에서 암시 적으로 사용할 수 있습니다. – Alnitak

+0

@Alnitak 그건 내가 본 것이 아니야. 내 편집을 봐. – Magus

+0

ah 예 - 내부 콜백 기능을 잊어 버렸습니다. 나는 익명의 기능 만보고 있었다. – Alnitak

0

은 아마 이런 식으로 할 것이다. 그것이 더 효율적인지 아닌지는 확실하지 않지만 또 다른 옵션입니다.

+0

'bind'는 이벤트 처리기에 좋은 옵션이 아닙니다. 왜냐하면'this'는 외부 적으로 바인딩 된 변수가 아니라 클릭 된 객체를 나타 내기 때문입니다. – Alnitak

1

항상은 생성자에서 이벤트를 바인딩 할 때 클로저를 만듭니다. 사실 인스턴스에 대한 참조를 유지하기 위해서는 클로저가 필요합니다. 당신은 당신의 생성자의 싱글 인스턴스를 만들 경우, 어쨌든 문제가되지 않습니다

function MyObj() { 
    this.foo = function(bar) { 
     // Do something with 'bar' 
    } 

    // Set up lots of local variables etc. 
    // .... 
} 

var myObj = new MyObj(); 
$(function() { 
    $(document).on('click.myobj', 'input.special', function() { 
     myObj.foo(this); 
    }); 
}); 

그러나, 당신은 이런 식으로 뭔가를 할 수 있습니다.

관련 문제