增加函数参数的最简洁的解决方法

时间:2016-12-04 23:15:31

标签: javascript jquery function

我正在尝试创建一个函数,每次运行时都会增加其参数。你总是可以手动重写函数,但我将多次运行这个函数,并希望能够方便地重用代码。

$("div").each(function() {

    function rangeF(firstValue, increment) {

      var first = firstValue + "-"; //Set the first value and put a hypen after it
      firstValue += increment; //Increment it by the increment
      var second = firstValue; //Set the second value
      firstValue++; //Increment by one to avoid duplicates

      return first + second; //return both values (e.g. 1-2 or x-y)
    }

    range = rangeF(5 , 10); //5 is the value to start on, 10 + 1 is the increment (need to access both 5 + 10 & 5 + 11)
    range2 = rangeF(2, 2); //2 is the value to start on, 2 + 1 is the increment (need to access both 2 + 2 & 2 + 3)

    $(this)
    .append('<div>' + range + '</div>')
    .append('<div>' + range2 + '</div>');
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

#1 range: <div></div>
<br />
#2 range: <div></div>
<br />
#3 range: <div></div>

现在,它显示:

#1 range:
P 5-15
P 2-4

#2 range:
P 5-15
P 2-4

#3 range:
P 5-15
P 2-4

我想展示:

#1 range:
P 5-15
P 2-4

#2 range:
P 16-26
P 5-7

#3 range:
P 27-37
P 8-10

以最干净,可重复使用的方式。

提前致谢。

更新对于这种混乱感到抱歉,但我的意思是我不想重复使用全局变量来解决问题...再次感谢您的所有贡献。

3 个答案:

答案 0 :(得分:2)

我建议用工厂解决这个问题:

&#13;
&#13;
// jQuery plugin named rangify
$.fn.rangify = function rangify(ranges) {
  // factory to generate auto-incrementers
  function rangeFactory(value, increment) {
    // scoped variables `value` and `increment`
    // re-used by inner function
    
    // this is essentially the same
    // function as in original question
    return function range() {
      var first = value;

      value += increment;

      var second = value;

      value++;

      return 'P ' + first + '-' + second;
    }
  }

  // when jQuery plugin is called
  // this initializes scoped auto-incrementers
  // with arguments supplied from array of tuples
  var calls = ranges.map(function map(args) {
    return rangeFactory(args[0], args[1]);
  });
  
  // iterate through context of jQuery selector
  return this.each(function each() {
    // reference to single element in jQuery selector
    var $this = $(this);

    // for each auto-incrementer
    calls.forEach(function (call) {
      // append the generated range
      $this.append('<div>' + call() + '</div>');
    });
  });
};

// tell plugin to generate
// 1. sequential ranges of 10 starting at 5
// 2. sequential ranges of 2 starting at 2
$("div").rangify([[5, 10], [2, 2]]);
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

#1 range: <div></div>
<br />
#2 range: <div></div>
<br />
#3 range: <div></div>
&#13;
&#13;
&#13;

我为你写了一个jQuery插件,它使用工厂存储范围变量来代替你试图避免的全局变量。

更新

我刚刚创建了一个更通用的插件,您可以在其中指定给定参数返回的内容,以及每次如何增加参数:

&#13;
&#13;
// jQuery plugin named rangify
$.fn.rangify = function rangify(getter, increment, tuples) {
  // decorator to transform getter into auto-incrementing getter
  function decorator(tuple) {
    // scoped variable `tuple`
    // re-used by decorated function
    return function decorated() {
      // get content from getter
      var content = getter.apply(undefined, tuple);

      // increment the arguments for the getter
      tuple = increment.apply(undefined, tuple);
      
      // return the content
      return content;
    }
  }

  // when jQuery plugin is called
  // this initializes scoped auto-incrementers
  // with arguments supplied from array of tuples
  var calls = tuples.map(decorator);
  
  // iterate through context of jQuery selector
  return this.each(function each() {
    // reference to single element in jQuery selector
    var $this = $(this);

    // for each auto-incrementer
    calls.forEach(function (call) {
      // append the generated content
      $this.append(call());
    });
  });
};

// you supply the following functions to the plugin

// return content
function content(value, increment) {
  var first = value;
  var second = value + increment;

  return '<div>P ' + first + '-' + second + '</div>';
}

// return incremented arguments
function increment(value, increment) {
  value += increment + 1;
  
  return arguments;
}

// tell plugin to generate content
$("div").rangify(content, increment, [[5, 10], [2, 2]]);
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

#1 range: <div></div>
<br />
#2 range: <div></div>
<br />
#3 range: <div></div>
&#13;
&#13;
&#13;

要说明这是通用的原因,请考虑以下示例:

&#13;
&#13;
// jQuery plugin named rangify
$.fn.rangify = function rangify(getter, increment, tuples) {
  // decorator to transform getter into auto-incrementing getter
  function decorator(tuple) {
    // scoped variable `tuple`
    // re-used by decorated function
    return function decorated() {
      // get content from getter
      var content = getter.apply(undefined, tuple);

      // increment the arguments for the getter
      tuple = increment.apply(undefined, tuple);
      
      // return the content
      return content;
    }
  }

  // when jQuery plugin is called
  // this initializes scoped auto-incrementers
  // with arguments supplied from array of tuples
  var calls = tuples.map(decorator);
  
  // iterate through context of jQuery selector
  return this.each(function each() {
    // reference to single element in jQuery selector
    var $this = $(this);

    // for each auto-incrementer
    calls.forEach(function (call) {
      // append the generated content
      $this.append(call());
    });
  });
};

// you supply the following functions to the plugin

// return content
function content(className, chapter, section) {
  return '<div class="' + className + '">Chapter ' + chapter + ' - Section ' + section + '</div>';
}

// return incremented arguments
function increment(className, chapter, section) {
  if (section === 'C') {
    section = 'A';
    chapter++;
  } else {
    var nextCode = section.charCodeAt(0) + 1;
    section = String.fromCharCode(nextCode);
  }
  
  return arguments;
}

// tell plugin to generate content
$("div").rangify(content, increment, [['red', 1, 'A'], ['green', 4, 'A']]);
&#13;
div:not([class]) {
  display: inline-block;
  border: 1px solid black;
  padding: 5px;
  margin-bottom: 5px;
}

.red {
  color: red;
}

.green {
  color: green;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

不确定这是否是你所追求的问题是不明确的,但是这会将参数注入到装饰函数中,这将增加装饰函数的每次调用。

计数器在incrementRangeDecorator函数的关闭中保留,因此它不会暴露于全局范围。

&#13;
&#13;
// function decorator that will inject two argements into the 
// decorated function that will be incremented each call
const incrementRangeDecorator = function(start, increment, fn) {
  return function(...args) {
    const ret = fn(start, start += increment, ...args)
    start = start + 1
    return ret
  }
}

// function to decorate
function rangeF(start, current, extraArg) {
  console.log('called rangeF()', `${start}-${current}`, extraArg)
}

// decorate rangeF with the incrementRangeDecorator
const incrementBy2 = incrementRangeDecorator(2, 2, rangeF)
const incrementBy5 = incrementRangeDecorator(5, 10, rangeF)


incrementBy2('you')
incrementBy2('can')
incrementBy2('pass')

incrementBy5('extra')
incrementBy5('arguments')
incrementBy5()
&#13;
&#13;
&#13;

答案 2 :(得分:0)

使用

$(function() {

});

将等待执行,直到DOM准备就绪。 (这相当于.ready()函数,甚至建议使用而不是.ready()...)

里面的变量不是'全局',它们属于那个函数。

其余的解释了自己。

$(function() {
    var a = 5; var b = 10; var c = 2; var d = 2;
    $("div").each(function() {	
        function rangeF(firstValue, increment) {			
            var first = firstValue + "-"; //Set the first value and put a hypen after it
            firstValue += increment; //Increment it by the increment
            var second = firstValue; //Set the second value
            firstValue++; //Increment by one to avoid duplicates
            return first + second; //return both values (e.g. 1-2 or x-y)
        }
		
        range = rangeF(a, b);
        range2 = rangeF(c, d);
		
        a = a+b+1;
        c = c+d+1;
		
        $(this)
        .append('<div>' + range + '</div>')
        .append('<div>' + range2 + '</div>');
    });
});
div {
    border:#999 1px solid;
    padding:1em;
    margin:1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="A">
</div>
<div id="B">
</div>
<div id="C">
</div>

希望它有所帮助。