Code Monkey home page Code Monkey logo

Comments (1)

qappleh avatar qappleh commented on May 19, 2024

解决办法汇总

原理:

利用 setTimeout 函数的第三个参数,会作为回调函数的第一个参数传入
利用 bind 函数部分执行的特性
代码 1:

for (var i = 0; i < 10; i++) {
  setTimeout(i => {
    console.log(i);
  }, 1000, i)
}  

代码 2:

for (var i = 0; i < 10; i++) {
  setTimeout(console.log, 1000, i)
}  

代码 3:

for (var i = 0; i < 10; i++) {
  setTimeout(console.log.bind(Object.create(null), i), 1000)
}  

方法二

原理:

利用 let 变量的特性 — 在每一次 for 循环的过程中,let 声明的变量会在当前的块级作用域里面(for 循环的 body 体,也即两个花括号之间的内容区域)创建一个文法环境(Lexical Environment),该环境里面包括了当前 for 循环过程中的 i,具体链接
代码 1:

for (let i = 0; i < 10; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000)
}  

等价于

for (let i = 0; i < 10; i++) {
  let _i = i;// const _i = i;
  setTimeout(() => {
    console.log(_i);
  }, 1000)
}  

方法三

原理:

利用函数自执行的方式,把当前 for 循环过程中的 i 传递进去,构建出块级作用域。IIFE 其实并不属于闭包的范畴。参考链接如下:
difference-between-closures-and-iifes-in-javascript
IIFE 是闭包?
利用其它方式构建出块级作用域
代码 1:

for (var i = 0; i < 10; i++) {
  (i => {
    setTimeout(() => {
      console.log(i);
    }, 1000)
  })(i)
}  

代码 2:

for (var i = 0; i < 10; i++) {
  try {
    throw new Error(i);
  } catch ({
    message: i
  }) {
    setTimeout(() => {
      console.log(i);
    }, 1000)
  }
}  

方法四

原理:

很多其它的方案只是把 console.log(i) 放到一个函数里面,因为 setTimeout 函数的第一个参数只接受函数以及字符串,如果是 js 语句的话,js 引擎应该会自动在该语句外面包裹一层函数
代码 1:

for (var i = 0; i < 10; i++) {
  setTimeout(console.log(i), 1000)
}  

代码 2:

for (var i = 0; i < 10; i++) {
  setTimeout((() => {
    console.log(i);
  })(), 1000)
}  

代码 3:

for (var i = 0; i < 10; i++) {
  setTimeout((i => {
    console.log(i);
  })(i), 1000)
}  

代码 4:

for (var i = 0; i < 10; i++) {
  setTimeout((i => {
    console.log(i);
  }).call(Object.create(null), i), 1000)
}  

代码 5:

for (var i = 0; i < 10; i++) {
  setTimeout((i => {
    console.log(i);
  }).apply(Object.create(null), [i]), 1000)
}  

代码 6:

for (var i = 0; i < 10; i++) {
  setTimeout((i => {
    console.log(i);
  }).apply(Object.create(null), { length: 1, '0': i }), 1000)
}  

方法五

原理:

利用 eval 或者 new Function 执行字符串,然后执行过程同方法四
代码 1:

for (var i = 0; i < 10; i++) {
  setTimeout(eval('console.log(i)'), 1000)
}  

代码 2:

for (var i = 0; i < 10; i++) {
  setTimeout(new Function('i', 'console.log(i)')(i), 1000)
}  

代码 3:

for (var i = 0; i < 10; i++) {
  setTimeout(new Function('console.log(i)')(), 1000)
}  

from interview.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.