Javascript 而数字原型扩展中的循环调用函数一次,则错误未定义

Javascript 而数字原型扩展中的循环调用函数一次,则错误未定义,javascript,prototype-programming,Javascript,Prototype Programming,我正试图扩展JS数字原型,以包括一个Ruby风格的“.times”方法(这种追求的优点是另一个时代的问题) 这是我的密码: Number.prototype.times = function(doThis) { val = +this; while (val > 0 ) { doThis(); val--; } } 如果我尝试 5..次(console.log(1)) 我得到以下输出: foo TypeError: undefined is not a fun

我正试图扩展JS数字原型,以包括一个Ruby风格的“.times”方法(这种追求的优点是另一个时代的问题)

这是我的密码:

Number.prototype.times = function(doThis) {
  val = +this;
  while (val > 0 ) {
    doThis();
    val--;
  }
}
如果我尝试

5..次(console.log(1))

我得到以下输出:

foo
TypeError: undefined is not a function (evaluating 'doThis()')
为什么循环在第一次迭代中工作,而在第二次迭代中失败


(注意:我们的目标是使数字原型扩展具有高度的表达性、直观性,并且读起来更像自然语言,就像Ruby的方法一样。)

您的
Number.prototype.times
函数被写入以另一个函数作为参数(然后使用
doThis()调用)

但是,在调用
times
函数时,您并没有将另一个函数作为参数传递,而是返回
console.log(1)
的值,该值很可能是
未定义的
(然后您尝试将其作为函数调用,导致未定义的不是函数错误)

相反,传递一个调用
console.log(1)
的函数:

更改为:

Number.prototype.times = function(doThis) {
  val = +this;
  while (val > 0 ) {
    doThis();
    val--;
  }
}
5..times(function () {console.log(1)});

您的函数让我想起了像or这样的库,它们提供了许多函数,让您可以编写非常简洁的代码

下面是我如何使用lodash实现这一点,它提供了一个实用功能:

Number.prototype.times = function(cb) {
  return _.times(+this, cb);
}
您可以使用使其比显式的
function(){}
wrapper更具可读性:

5..times(_.partial(console.log,"blah"));
或者,如果您想将部分内容放入
times
函数中,它的可读性可能会更高一些:

Number.prototype.times = function () {
    return _.times(+this, _.partial.apply(this,arguments));
};

5..times(console.log,"blah");

// can still be used with an arbitrary function block:
5..times(function() { console.log("some other block"); });


这里是。

在“5”之后的“..”是必需的,因为解释器读取第一个点作为数值文本的一部分。我的目标是编写.times()函数,使调用它非常简洁。是否有方法更改.times()而不是它所需的参数?@meetalexjohnson
console.log(1)
返回未定义的,然后将其传递给该方法,而不提供值的来源信息。这是语言的一个基本特性,你不能改变它。@helmbert我想要一种非常简洁的方法来编写循环,当我确切地知道我想要循环运行多少次时。因此,如果我想记录5个“foo”,我可以使用'5..times(console.log(“foo”))“@meetalexjohnson:
(5).times(console.log.bind(console,1))
Number.prototype.times = function () {
    return _.times(+this, _.partial.apply(this,arguments));
};

5..times(console.log,"blah");

// can still be used with an arbitrary function block:
5..times(function() { console.log("some other block"); });