【问题标题】:Creating a function that can be invoked a given number of times and no more创建一个可以调用给定次数但不能再调用的函数
【发布时间】:2015-04-24 02:36:30
【问题描述】:

假设您有一个功能,您可以使用“嘿”输入警报,并且您希望允许它发生给定次数 - 例如 2 或 3 或任何您想要的 - 然后在给定次数之后发出警报负数或“不再”类型的字符串的相同次数。

所以你希望你的函数调用 n 次

var hey = funky(function(){alert("hey")},3);

hey();

你是怎么做到的?

【问题讨论】:

  • 带循环?我明白这个问题了吗?
  • 或者你的意思是一个函数在第 n 次被调用时有一个效果,但之后的效果不同(或没有)?

标签: javascript function higher-order-functions


【解决方案1】:

funky 需要是一个“高阶”函数,它将您的输入函数“转换”为只运行第一个 n 次的函数:

 function funky(fn, n) {
     return function() {
         return n-- > 0 ? fn.apply(this, arguments) : "No more";
     };
 }

在这里,我们使用fn.apply 允许用户通过this 和返回函数的参数,因此您可以执行以下操作:

var hey = funky(function(name){ alert("hey " + name); }, 3);

hey("Bob"); // alert("hey Bob")
hey("Joe"); // alert("hey Joe")
hey("Sam"); // alert("hey Sam")
hey("Don"); // no alert, returns "No more"

将参数传递给派生函数已经足够有用了,但是在什么情况下它会尊重this?显然,只有在涉及对象及其方法的情况下。考虑:

// Constructor to create new MyAlerter object, with magic number
var MyAlerter = function(magic) {
    this.magic = magic;
}

// Method on MyAlerter to put up alert with magic number
MyAlerter.prototype.alert = function(name) {
  alert("hey " + name + ", your magic number is " + this.magic);
};

现在我们要基于alert 方法创建一个函数/方法hey,它将调用次数限制为三个。我们已经有了 funky 函数来做到这一点:

MyAlerter.prototype.hey = funky(MyAlerter.prototype.alert, 3);

现在我们可以这样做了:

var alerter = new MyAlerter(42);

alerter.hey("Bob"); // alert("hey Bob, your magic number is 42")
alerter.hey("Joe"); // alert("hey Joe, your magic number is 42")
alerter.hey("Sam"); // alert("hey Sam, your magic number is 42")
alerter.hey("Don"); // no alert, returns "No more"

通过通过this 调用hey 到底层函数alert,通过funky 内部的fn.apply 完成,alert 接收正确的this 并能够访问幻数。

【讨论】:

  • 使用 apply 是没有意义的,因为没有在调用中设置 this 或提供参数的机制,因此该函数将始终被调用而不设置其this(因此它将默认为全局对象或在严格模式下保持 undefined)。不过,它确实暗示了有用的增强功能。 ;-)
  • 显然有一种方法可以提供参数,如hey("Bob")。 this 可以很容易地通过 hey.call(obj, "Bob") 传递,但我将构建一个更真实的场景。
  • 酷,您添加了增强功能。虽然不能再次投票给你。 :-)
【解决方案2】:

你的意思是像一个 for 循环?

function funky (fn, n) {
    for (var i = 0; i < n; i += 1) {
        fn();
    }
}

funky(function () {
    alert('ABC');
}, 3);

如果您不希望它立即运行,那么您可以这样做:

function funky(fn, n) {
    this.run = function() {
        for (var i = 0; i < n; i += 1) {
            fn();
        }
    }
}

var hey = new funky(function() {
    alert('ABC');
}, 3);

hey.run();//Alerts ABC 3 times

Fiddle

还有:

function funky(fn, n) {
    return function() {
        for (var i = 0; i < n; i += 1) {
            fn();
        }
    }
}

var hey = funky(function() {
    alert('ABC');
}, 3);

hey();//Alerts ABC 3 times

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-02
    • 1970-01-01
    相关资源
    最近更新 更多