Advanced-Frontend / Daily-Interview-Question

我是依扬(木易杨),公众号「高级前端进阶」作者,每天搞定一道前端大厂面试题,祝大家天天进步,一年后会看到不一样的自己。

Home Page:https://muyiy.cn/question/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

第 101 题:修改以下 print 函数,使之输出 0 到 99,或者 99 到 0

yygmind opened this issue · comments

要求:

1、只能修改 setTimeoutMath.floor(Math.random() * 1000 的代码

2、不能修改 Math.floor(Math.random() * 1000

3、不能使用全局变量

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

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

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

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

第一种解法:

function print(n) {

    setTimeout( (() => {

        console.log(n);
    
    })(), Math.floor(Math.random() * 1000));
}


for(var i = 0; i < 100; i++){
    print(i);
}

另一种解法则是根据setTimeout的时间戳,只要让它按照时间戳顺序打印即可。但这样的时间耗时相当长。

function print(n){

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

    }, Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
    print(i);
}
commented

楼上匿名函数自执行是一种解法,直接利用表达式也是一种解法!

function print(n){
  setTimeout(console.log(n), Math.floor(Math.random() * 1000));
}

for(var i = 0; i < 100; i++) {
  print(i);
}

99到0,就是 99 - n

function print(n){
  setTimeout(console.log(99 - n), Math.floor(Math.random() * 1000));
}

for(var i = 0; i < 100; i++) {
  print(i);
}

综合上面各位大佬的答案,使用立即执行函数如果没有return值的话相当于

setTimeout(undefined, Math.floor(Math.random() * 1000));

浏览器会报错,所以还是需要加入返回值的

 setTimeout( (() => {
        console.log(n);
    	return ()=>{};
  })(), Math.floor(Math.random() * 1000));
  1. 依次打印出 0-99
function print(n){
  setTimeout(() => {
    setTimeout(()=>{
       console.log(n);
    },1000*n)
  }, Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}
  1. 依次打印出99-0
function print(n){
  setTimeout(() => {
    setTimeout(()=>{
       console.log(99-n);
    },1000*n)
  }, Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}
function print(n){
  print.n === undefined ? (print.n = 0) : (n !== 0 && print.n + 1 !== n) ? (setTimeout(() => {print(n)}, 1000)) : (setTimeout(() => {
    console.log(n);
    print.n += 1
  }, Math.floor(Math.random() * 1000)))
}
for(var i = 0; i < 100; i++){
  print(i);
}
commented

综合上面大佬给出的答案,感觉这题就是打乱了输出顺序,根本解决办法无外乎就是让定时器里的函数在同一任务队列里去执行,立即执行函数可以实现,或者给任意只要相同的时间间隔也可以实现。

commented

1、闭包,匿名函数自执行 ,即使创建它的上下文已经销毁,变量仍然存在,
2、是随机输出 0 到 99,或者 99 到 0?

两种解法:

  1. 利用settimeout 接受多个参数的方向,将Math.floor(Math.random() * 1000)作为第三个参数,第二参数可以设置为任意值。
    function print(n){
    setTimeout(() => {
    console.log(n);
    }, 1, Math.floor(Math.random() * 1000));
    }
    for(var i = 0; i < 100; i++){
    print(i);
    }
    2.可以利用settimeout 第一个参数可以是function是立即执行或者一个执行函数。

综合上面各位大佬的答案,使用立即执行函数如果没有return值的话相当于

setTimeout(undefined, Math.floor(Math.random() * 1000));

浏览器会报错,所以还是需要加入返回值的

 setTimeout( (() => {
        console.log(n);
    	return ()=>{};
  })(), Math.floor(Math.random() * 1000));

没有报错啊

忽略Math.floor(Math.random() * 1000) 影响(不过打印的太慢了吧(#`O′))

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

综合上面各位大佬的答案,使用立即执行函数如果没有return值的话相当于

setTimeout(undefined, Math.floor(Math.random() * 1000));

浏览器会报错,所以还是需要加入返回值的

 setTimeout( (() => {
        console.log(n);
    	return ()=>{};
  })(), Math.floor(Math.random() * 1000));
window.setTimeout = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. >*/) {
var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2);
return __nativeST__(vCallback instanceof Function ? function () {
vCallback.apply(oThis, aArgs);
} : vCallback, nDelay);
};`

只是判断是不是function类型

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

// 方法1 利用for的变量i  输出99-0
function print(n){
  setTimeout(() => {
    console.log(--i);
  }, Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}

//方法2 将setTimeout 的时间改为 0*Math.floor(Math.random() * 1000) .. 取巧了一下
// 输出0-99
function print(n){
  setTimeout(() => {
    console.log(n);
  }, 0*Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}
  1. 0-99
function print(n){
  setTimeout(() => {
    console.log(n);
  }, 1, Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}
  1. 99-0
function print(n){
  setTimeout(() => {
    console.log(99 - n);
  }, 1, Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}

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

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

把Math.random挤掉就好了。

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

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

emm,楼主不给答案讲解得嘛

emm,楼主不给答案讲解得嘛

我理解的讲一下,2种方法
1.立即执行函数
2.定时器第二位重新赋固定的值

题目解析:向setTimeout() 传递一个函数时,该函数中的this指向跟你的期望可能不同,当前这些代码中包含的 this 关键字在非严格模式会指向window对象,严格模式下为undefined。此时可以借助call或apply去改变this指向,即可顺序打印出0到99(或倒序99到0)

function print(n){
  setTimeout((() => {
    // console.log(this.i); // 如果不借助call会打印出100次全局变量i,值都为100
    console.log(n); // 顺序打印出0~99(100个)
    console.log(99-n); // 倒序打印出99~0(100个)
  }).call(null, n), Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++) {
  // console.log(i) // 0~99
  print(i); 
}
console.log(i) // 注意:此时i在全局window里可访问到,值为100

function print(n) {
setTimeout(async ()=>{
await new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve(n)
},n*1000)
});
console.log(n)
},Math.floor(Math.random()*100))
}

for(var i=0;i<100;i++){
print(i)
}

利用异步函数也可以,这个简单直接

commented
// 方法1 利用for的变量i  输出99-0
function print(n){
  setTimeout(() => {
    console.log(--i);
  }, Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}

//方法2 将setTimeout 的时间改为 0*Math.floor(Math.random() * 1000) .. 取巧了一下
// 输出0-99
function print(n){
  setTimeout(() => {
    console.log(n);
  }, 0*Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}

请问第二个方法不是异步的吗,最后为什么不是都打印99呢?

function print(n) {
setTimeout(() => {
console.log(n);
}, n * 1001 + Math.floor(Math.random() * 1000));
}
for (var i = 0; i < 100; i++) {
print(i);
}
不知道这样违规没有 🌚

// 方法1 利用for的变量i  输出99-0
function print(n){
  setTimeout(() => {
    console.log(--i);
  }, Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}

//方法2 将setTimeout 的时间改为 0*Math.floor(Math.random() * 1000) .. 取巧了一下
// 输出0-99
function print(n){
  setTimeout(() => {
    console.log(n);
  }, 0*Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}

请问第二个方法不是异步的吗,最后为什么不是都打印99呢?

这是当做参数传到print方法的,正真执行print方法的时候i参数就是当时的i的值

commented
// 方法1 利用for的变量i  输出99-0
function print(n){
  setTimeout(() => {
    console.log(--i);
  }, Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}

//方法2 将setTimeout 的时间改为 0*Math.floor(Math.random() * 1000) .. 取巧了一下
// 输出0-99
function print(n){
  setTimeout(() => {
    console.log(n);
  }, 0*Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}

请问第二个方法不是异步的吗,最后为什么不是都打印99呢?

这是当做参数传到print方法的,正真执行print方法的时候i参数就是当时的i的值

每次跑循环的时候,setTimeout里的n都已经确定为对应的数字了,之后真正执行的时候,没有作用域查找n这个过程了。这样子吗?

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

每次跑循环的时候,setTimeout里的n都已经确定为对应的数字了,之后真正执行的时候,没有作用域查找n这个过程了。这样子吗?

你理解的偏太远了,timer方法作用域内没有找到n,于是去上一级作用域链print方法内找,找到了n,就是一个值,结束。和外面的for没一点关系了,你自己先想想。

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

这样好像也可以~

commented
function print(n){
  setTimeout(() => {
    console.log(n)
  }, Math.floor(Math.random() * 1000) + n * 1000)
}

for(var i = 0; i < 100; i++){
  print(i)
}
commented

每次跑循环的时候,setTimeout里的n都已经确定为对应的数字了,之后真正执行的时候,没有作用域查找n这个过程了。这样子吗?

你理解的偏太远了,timer方法作用域内没有找到n,于是去上一级作用域链print方法内找,找到了n,就是一个值,结束。和外面的for没一点关系了,你自己先想想。

既然只有一个n,那么每一个timer对于n的查找,最后找到的都会是值为99的n,所以我才问是不是n在循环的时候就确定了,因为如果在循环的时候确定了,那么每一个timer就会有正确的对应数字,不会都输出99。

function print(n){
setTimeout(console.log(n), Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
print(i);
}
感觉就是考setTimeout的参数的详细用法,和闭包,匿名函数自执行,啥关系没有。

function print(n) {
  setTimeout(() => {
    console.log(n);
  }, Math.floor(Math.random() * 1000) +  n * 1000);
}
function print(n) {
  setTimeout(() => {
    console.log(n);
  }, Math.floor(Math.random() * 1000) + (100 - n) * 1000);
}

我这种算不算违反了第二条规则?

来个奇葩的
function print(n){
setTimeout(() => {
if(n===0){
for(i=0;i<100;i++){console.log(i)}}
}, Math.floor(Math.random() * 1000));
}

利用var修饰的变量皮一下下
function print(n){
setTimeout(() => {
console.log(i--);
}, Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
print(i);
}

这题我懂,就是考注释怎么用!
第一种

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

第二种

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

function print(n) {
	setTimeout(() => {
		console.log(n);
	}, 0, Math.floor(Math.random() * 1000)); //不延时,立即执行
}
for(var i = 0; i < 100; i++) {
	print(i);
}

function print(n) {
	setTimeout(((n) => {
		console.log(n)
	}).bind(this)(n), Math.floor(Math.random() * 1000)); //立即执行
}
for(var i = 0; i < 100; i++) {
	print(i);
}
commented

分析输出:

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

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

两者区别:在 print 函数中 n 为局部变量,setTimeout 回调依然引用 变量 n,因此形成闭包,虽然 变量 n 从 0-99 变化,可是 delay 为随机数,较小者的 n 先输出。

完成要求:
总结以上大家的答案分析:
1、setTimeout 第一个参数传递 code,即代码语句,此时相当于同步代码执行
2、for 语句块 var 声明变量存在于外部作用域中,setTimeout 的回调可直接引用 变量 i
3、叠加定时器,使得非顺序输出变成顺序输出。

感觉立即执行的话,失去了settimeout的意义,这个函数本身的目的是希望数字既能依次输出,但是又不会太过均匀,给人一种错层的感觉,类似于过度效果不会太过均匀一样的道理

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

不知道算不算偷鸡

总结

function print0(n){
  setTimeout(() => {
    console.log(n);
  }, 0, Math.floor(Math.random() * 1000));//关闭延迟
}

function print1(n) {
	setTimeout(
		(() => {
			console.log(n)
		})(),
		Math.floor(Math.random() * 1000), //自执行
	)
}
function print2(n) {
	setTimeout(() => {
		console.log(--i)
	}, Math.floor(Math.random() * 1000)) //全局i
}
function print3(n) {
	// setTimeout(() => {
	console.log(n)
	//}, Math.floor(Math.random() * 1000)); //注释
}
function print4(n) {
	setTimeout(() => {
		if (n === 0) {
			for (i = 0; i < 100; i++) {
				console.log(i)
			}
		}
	}, Math.floor(Math.random() * 1000)) //条件
}
function print5(n) {
	setTimeout(() => {
		setTimeout(() => {
			log(n)
		}, n * 1000)
	}, Math.floor(Math.random() * 1000)) //延迟
}

自己的方法, 但利用事件循环解决

function print(n) {
	setTimeout(() => {
		print.p.then(() => {
			setTimeout(() => {
				console.log(n)
				debugs(n)
			}, n * 4) //3 开始新的事件循环, 间隔扩大为4(setTimeout精度为4), 但有几率debug的结果会为false, 不解, 可能精度还是低
		})
	}, Math.floor(Math.random() * 1000))
}
for (var i = 0; i < 100; i++) {
	print(i)
}

print.p = new Promise(r => (print.r = r)) // 1 为了不使用全局变量, 值挂载在函数上
setTimeout(() => {
	print.r()
}, 1000) //2 等所有原始setTimeout事件就绪后resolve promise



function debugs(n) {
	if (n == 0) arr = []
	arr.push(n)
	if (n == 99) {
		console.log(arr.join() == [...arr].sort((q, w) => q - w).join())
		console.log(arr)
	}
}

就直接让第二个参数变成自己定义的就OK了吧

0-99

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

99-0

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

思路: 利用闭包创建上下文环境存储正确的 n 值。遇到 0 就升序循环输出或者遇 99 就降序循环输出。

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

这个就是考察闭包
function print(n){
setTimeout(
(function(n){
console.log(n)
})(n)
,100)
}

for(var i=0;i<100;i++){
print(i)
}

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

瞎搞一手

function print(n){
setTimeout((n) => {
console.log(n);
},1,99-n, Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
print(i);
}
输出99到0,你们有啥好办法么?

commented

这题不是考闭包的,别往闭包上想

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

function print(n){
setTimeout((() => {
console.log(n)
})(), Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
print(i);
}
将setTimeout的第一个参数改为自执行就可以了

思路很清晰,把setTimeout的第二个参数改为n

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

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

@Chenxinan 你这个只要把Math.floor(Math.random() * 1000)改成Math.floor(Math.random() * 10000)就不会按顺序输出0-99。

@Hunterang 恩恩,感觉这题是想考核面试者在不用promise.all()的情况下,在并发100次请求后,如何把浏览器在不同时间点获取到的数据按原先的数据逻辑顺序输出。

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

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

第二种,去掉setTimeout

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

理是?没看懂

我去脑筋急转弯的题

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

看了各位的解法我觉得自己的解法跟闹着玩似的…… 在每一次执行前重写了 Math.random…………

function print(n){
  setTimeout((function(){
    Math.random = function(){
      return 0.1 * n;
    }
    return (() => {
    console.log(n);
  })})(), Math.floor(Math.random() * 1000));
}
commented
        //  方法一
        function print(n) {
          setTimeout(() => {
            // console.log(n);
            let i = n
            setTimeout(() => {
              console.log(i, 'ddd')
            }, n * 1000)
          },
            Math.floor(Math.random() * 1000)
          );
        }
        for (var i = 0; i < 100; i++) {
          print(i);
        }

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



        // 方法三  立即执行函数,相当于同步代码
        function print(n){
          setTimeout((()=>{
            console.log(n)
            return ()=>{}
          })(), Math.floor(Math.random() * 1000));
        }
        for(var i = 0; i < 100; i++){
          print(i);
        }

换一种思路

function print(n){
  setTimeout(() => {
    if (!print.cache) {
      print.cache = [];
      print.id = null;
    };
    print.cache.push(n);
    clearTimeout(print.id);
    print.id = setTimeout(() => {
      print.cache.sort((a, b) => a - b);
    	for (let num of print.cache) {
      	console.log(num);
      }
      delete print.id;
      delete print.cache;
      // 最长不过1000ms
    }, 1000);
  }, Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
	print(i);
}

感觉无论是立即执行函数、表达式,还是用n去替代Math.random,脱离了题目本身的意义。所以考的是脑筋急转弯?

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

commented

image

支持原题中间隔随机时间 print 的版本

(() => {
  function print(n) {
    setTimeout(
        (() => {
        // const prev = i.__proto__.prev;
        const prev = print.prev;
        let resolver = () => {};
        // i.__proto__.prev = new Promise(resolve => {
        print.prev = new Promise(resolve => {
          resolver = resolve;
        });
        const exec = (delay) => {
          setTimeout(() => {
            console.log(n);
            resolver();
          }, delay);
        };

        return prev
          ? (delay) => {
            prev
              .then(exec.bind(null, delay))
              .then(() => {
                // if (i.__proto__.prev) {
                if (print.prev) {
                  // delete i.__proto__.prev;
                  delete print.prev;
                }
              });
          }
          : exec;
      })(),
      0,
      Math.floor(Math.random() * 1000)
    );
  }
  for (var i = 0; i < 100; i++){
    print(i);
  }
})()
commented

不知道这燕子算不算满足要求

function print(n) {
	setTimeout(() => {
		if (!print.index && print.index !== 0) {
			print.index = 99
		} else {
			print.index--
		}
		console.log(print.index)
	}, Math.floor(Math.random() * 1000))
}
for (var i = 0; i < 100; i++) {
	print(i)
}

还可以利用逗号表达式 :-)

但我实在搞不懂这题的目的是啥?

function print(n){
  setTimeout((console.log(n), () => null), Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}
function print(n) {
    setTimeout(() => {
      if (!print.list) print.list = []
      if (!print.timer)
        print.timer = setTimeout(() => {
          print.list.forEach(fn => fn())
        }, 1000)
      print.list[n] = () => console.log(n)
    }, Math.floor(Math.random() * 1000))
  }

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

`function print(n) {
setTimeout(() => {
console.log(100 - i--);
}, Math.floor(Math.random() * 1000));
}

for (var i = 0; i < 100; i++) {
print(i);
}`

词法环境与闭包的联系:
静态作用域
动态作用域

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

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

0~99

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

99~0

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

利用 settimeout 的第一个参数 可以传 表达式 的原理,绕过了 随机的定时器执行

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

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