【问题标题】:JS print 0 - 99 or 99 - 0 in orderJS 按顺序打印 0 - 99 或 99 - 0
【发布时间】:2021-07-09 02:25:25
【问题描述】:

全部。我是 JS 新手。在这里我遇到了一个JS问题,如下所示:

function print(n) {
    setTimeout(() => {
        console.log(n);
    }, Math.floor(Math.random() * 1000));
}
for (var i = 0; i < 100; i++) {
    print(i);
}

要求是:

  1. 您需要更改程序,使其按顺序打印0-99或99-0;
  2. 不能使用全局变量;
  3. 只能更改代码内部的setTimeout;
  4. 您不能修改Math.floor(Math.random() * 1000

在这里我得到了这个问题的一些解决方案,但是有些答案我不明白,所以我希望你们能帮助我为什么这可以工作。我理解第一个,第二个和最后一个的答案,但我不太清楚为什么其余的答案可以工作。尤其是第三个,如果我去掉return ()=&gt;{}的代码,代码还是可以的,但是会报错100Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src &lt;URL&gt; &lt;URL&gt; 'self' 'unsafe-inline' https:".

//1.
function print1(n) {
    setTimeout(() => {
        console.log(n);
    }, 1, Math.floor(Math.random() * 1000));
}

// 2. 
function print2(n) {
    setTimeout(() => {
        console.log(i--);
    }, Math.floor(Math.random() * 1000));
}

// 3.
function print3(n) {
    setTimeout((() => {
        console.log(n)
        return () => { }
    }).call(n, []), Math.floor(Math.random() * 1000));
}
for (var i = 0; i < 100; i++) {
    print(i);
}

//4.
function print4(n) {

    setTimeout(() => {

        setTimeout(() => {
            console.log(n);
        }, 1000 * n);

    }, Math.floor(Math.random() * 1000));
}

// 5. 
function print5(n) {
    setTimeout((() => {
        console.log(n);
    })(), Math.floor(Math.random() * 1000));
}

【问题讨论】:

  • 这是一个有趣的问题...从这篇文章中学到了很多

标签: javascript closures settimeout event-loop


【解决方案1】:

第三种方法本质上是在setTimeout 行运行后立即调用一个函数,在超时回调运行之前。因此,当调用print(i); 时,会在下一次循环开始之前立即记录该数字。

从功能上来说,类似这样:

function print3(n) {
    console.log(n);
    setTimeout(<unimporant>);
}

之所以有效,是因为超时内的函数会立即使用.call 调用:

setTimeout((() => {
    console.log(n)
    return () => { }
}).call(n, []),

简化为

setTimeout((() => {
    console.log(n)
    return () => { }
})(),

基本上就是这样

console.log(n)
setTimeout((() => {
    return () => { }
})(),

或者,替换从 IIFE 返回的函数:

console.log(n)
setTimeout(() => {},

传递给setTimeout 的回调没有任何作用。

如果我去掉代码return ()=>{},代码仍然有效但会报错

听起来您最后返回了一个字符串而不是函数,这将导致解释器尝试运行该字符串。虽然在某些环境中可能做这样的事情,但它与eval 基本相同。

setTimeout('console.log("never do this");');

这就是警告出现的原因。

【讨论】:

  • 只是为了好奇,是否可以在 OP 应用的所有条件下打印0-100
  • OP 在他们的问题中包含了许多可能的方法,这些方法(似乎暗示)满足要求。 print4 看起来是这里最好的方法,如果这是一项作业,我不确定评分者是否会在不要求澄清的情况下将 IIFE(如在其他方法中使用)视为允许的(print2 依赖在全局上,print1 需要在中间插入一个附加参数)
【解决方案2】:

您可以使用 Array(num) 创建一个长度为 num 的空数组。 然后你可以使用 .fill(n),用 n 填充所有数组索引。 然后您可以使用 .map() 循环遍历数组并返回新值来替换我们在 .fill() 中使用的值。

function range(start, end) {
    // checks that the end number is bigger than the start number.
    // this is because it should decrement instead of increment if the end is smaller.
    if(end > start){
        return Array(end - start).fill(0).map((_, i) => start + i)
    } else {
        return Array(start - end).fill(0).map((_, i) => start - i)
    }
}

您可以使用我制作的部分功能来做您想做的事。要打印所有值,只需执行 console.log(...arrayName),或使用 .forEach() 循环并打印它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-11
    • 2016-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多