여러 함수 호출보다 JavaScript에서 여러 인수 세트를 배열로 전달하는 것이 더 빠릅니까?

StackOverflow https://stackoverflow.com/questions/1413230

문제

동일한 함수를 여러 매개변수로 여러 번 호출하는 것이 약간 불편해진 후(아래 코드의 dom 준비 섹션 참조) 대신 배열을 반복하여 이 함수에 대한 매개변수 전달을 테스트하기로 결정했습니다(그림 참조). mouse_function_two).놀랍게도 나는 그것을 발견했다. mouse_function_two 훨씬 더 빨리 달렸다.

내 질문은, 그럴 것이다. mouse_function_two 것보다 더 나은 JavaScript 관행으로 간주됩니다 mouse_function_one?

메모:Firebugs console.time 유틸리티를 올바르게 사용하지 않을 수도 있다는 점이 약간 걱정됩니다!

초기 시도

function mouse_function_one (hover_selector, class_name, add_link) {

  hover_item = $(hover_selector)

  hover_item.each(function(){
    $(this).hover(
      function () {
        $(this).addClass(class_name);
        if ( add_link == true ) {
          $(this).click(function(){
            var href = $(this).find('a').attr('href');
            window.location.href = href;
          });

        }
        else return false;
      },
      function () {
        $(this).removeClass(class_name);
    });
  });
}

두 번째(더 빠른) 시도:

function mouse_function_two (args) {

  for (var i=0; i < args.length; i++) {

    hover_selector = $(args[i][0]);
    class_name = args[i][1];
    add_link = args[i][2];

    hover_item = $(hover_selector)

    hover_selector.each(function(){
      $(this).hover(
        function () {
          $(this).addClass(class_name);
          if ( add_link == true ) {
            $(this).click(function(){
              var href = $(this).find('a').attr('href');
              window.location.href = href;
            });

          }
          else return false;
        },
        function () {
          $(this).removeClass(class_name);
        });
    });

  }
}

클라이언트 코드:

// on dom ready
$(function(){

  console.time('f1');
  mouse_function_one('#newsletter .right', 'hovered', true);
  mouse_function_one('.block-couple div.right', 'hovered', false);
  mouse_function_one('.bulletin', 'selected', true);
  console.timeEnd('f1'); //speed is calculated as 104ms

  args = [];
  args[0] = ['#newsletter .right', 'hovered', true]; 
  args[1] = ['.block-couple div.right', 'hovered', false]; 
  args[2] = ['.bulletin', 'selected', true]; 

  console.time('f2');
  mouse_function_two(args);
  console.timeEnd('f2'); //speed is calculated as 10ms

});
도움이 되었습니까?

해결책

두 번째 루틴이 더 빠르면 아마도해야 할 일을하지 않기 때문일 수 있습니다. 이 스 니펫을 살펴보십시오.

  for (var i=0; i < args.length; i++) {

    hover_selector = $(args[i][0]);
    class_name = args[i][1];
    add_link = args[i][2];

    hover_item = $(hover_selector)

    hover_selector.each(function(){
      $(this).hover(
        function () {

여기에 두 가지 문제가 있습니다.

  1. 암시 적 글로벌 변수를 사용하고 있습니다.
  2. JavaScript의 블록은 새로운 범위를 소개하지 않습니다.

이들 중 하나는 동일한 버그를 유발할 수 있습니다. 함께 함께 발생할 것이라고 확신합니다. hover() 이벤트 핸들러 기능에는 최종 루프 반복의 값 만 포함됩니다. 이 핸들러가 마침내 호출되면 class_name 언제 까지나 그럴거야 "selected", 그리고 add_link 언제 까지나 그럴거야 true. 대조적으로, 원래 함수는 매번 다른 매개 변수 세트로 호출되며, 이는 이벤트 핸들러가 함수의 범위에 캡처되며 결과적으로 예상대로 작동합니다.


스타일은 ... 지저분합니다. 전체 기능 본문을 루프에 넣고 설명적인 인수를 제거하고 기능의 호출을 크게 복잡하게했습니다.

다행히도 위에서 지적한 문제를 해결하고 기능을 단순화하고 그리고 한 번에 모든 것을 호출하는 방법을 단순화하십시오.

// For starters, I've eliminated explicit parameters completely.
// args wasn't descriptive, and all JavaScript functions have an implicit
// arguments array already - so let's just use that.
function mouse_function_three () {

  // use jQuery's array iteration routine:
  // this takes a function as an argument, thereby introducing scope and
  // avoiding the problem identified previously
  $.each(arguments, function() {
    var class_name = this.class_name;
    var add_link = this.add_link;
    var selected = $(this.hover_selector);

    // no need to use selected.each() - jQuery event binding routines
    // always bind to all selected elements
    selected.hover(function() {
      $(this).addClass(class_name);
    },
    function() {
      $(this).removeClass(class_name);
    });

    // bring this out of the hover handler to avoid re-binding
    if ( add_link ) {
      $(selected).click(function(){
        var href = $(this).find('a').attr('href');
        window.location.href = href;
      });

    }
  }); // each set of arguments
}

그런 다음이 새로운 루틴이라고 부릅니다.

console.time('f3');
mouse_function_three( 
 {hover_selector: '#newsletter .right', class_name: 'hovered', add_link: true},
 {hover_selector: '.block-couple div.right', class_name: 'hovered', add_link: false},
 {hover_selector: '.bulletin', class_name: 'selected', add_link: true}
);
console.timeEnd('f3');

코드가 효과적으로 동일한 작업을 수행하지만 포장의 추가 단계를 통해 매개 변수를 추출하기 때문에 이러한 변경 사항은 초기 시도와 속도 차이를 잘 제거 할 수 있습니다.

다른 팁

병목 현상이 발생하는 코드 조각인가요?배열을 인수로 사용하면 명명된 매개변수가 사용자를 보호하는 전체 버그 범주에 접근할 수 있습니다.두 번째 코드는 읽기가 매우 좋지 않으며 아직 그렇지 않은 경우 시간이 주어지면 디버깅하기에 완벽한 엉덩이임이 입증될 것입니다.따라서 중요한 경우가 아니라면 제정신을 유지하세요.정말 문제가 있는 코드인 경우에만 속도를 약간 높이기 위해 합리적인 언어 기능을 버리기 시작해야 합니다.

편집하다:코드를 더 많이 볼수록 벤치마크의 균형이 덜 잡힌 것 같습니다.단일 호출에 대한 반복적인 메서드 호출 비용, 두 번째 경우에는 배열 채우기 등이 벤치마킹되지 않는 등 다른 결론을 내릴 수 있는 고려하지 않은 여러 가지 사항이 있습니다.

귀하의 경우 JSON 객체를 전달하는 것을 고려할 것입니다. ExtJS 및 JQuery와 같은 프레임 워크는 이러한 수행을 수행하면 많은 유연성을 제공하기 때문에 (API가 진화함에 따라) 단일 객체에 많은 데이터를 포장 할 수 있습니다.

function mouse_function_three (args) { ... }

Args가 어떻게 생겼는지 ...

[{'hover_selector': ... , 'class_name': ... , 'add_link': ...}, {'hover_selector': ... , 'class_name': ... , 'add_link': ...}, ... ]

각 객체의 속성에 대한 기본 속성을 지정할 수있는 기능을 포함하여이를 확장 할 수도 있습니다.

{
'default_hover_selector': 'asdf',
'default_class': 'asdf',
'add_link: false,
'items': [{'hover_selector': ... , 'class_name': ... , 'add_link': ...}, {'hover_selector': ... , 'class_name': ... , 'add_link': ...}, ... ]
}

이 솔루션은 당신이 원하는 성능과 직관성 (심지어 단어)을 제공 할 것이라고 생각합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top