fezaoduke / fe-practice-hard

晚练课
69 stars 6 forks source link

第 57 期(W3C 标准-ECMAScript-语法):setTimeout的其他参数 #60

Open wingmeng opened 5 years ago

wingmeng commented 5 years ago

看到一道今日头条的面试题:

修改以下 print 函数,使之输出 0 到 99 或 99 到 0

要求:
1. 只能修改 setTimeout 到 Math.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);
  }, 1, Math.floor(Math.random() * 1000));
}
for (var i = 0; i < 100; i++) {
  print(i);
}

这个回答巧妙地“钻了” setTimeout 参数次序的空子。原来 setTimeout 除了常见的前 2 个参数外,还有后续参数,这些后续参数会传递给执行函数(IE9及更早浏览不支持后续参数)。这个特性在某些情况下很有用,例如不使用箭头函数的情况下,如何将 this 指向传递到 setTimeout 的 function 中,伪代码如下:

function Fn() {
  this.foo = 1;
}

Fn.prototype.do = function() {
  // 传统实现方式是将 this 保存到一个变量
  var that = this;
  setTimeout(function() {
    that.foo = 2;
  }, 1000);

  // 其实可以将 this 作为 setTimeout 第 3 个参数传进去
  setTimeout(function(that) {
    that.foo = 2;
  }, 1000, this);
}