Github毎日1題——7.17学習記録

3454 ワード

前言
テーマはDaily-Interview-Question木易楊からstarを歓迎して、討論に参加します
本文は自分のテーマに対する解決方法と総合大神たちの見方を記録した.
タイトル
1、以下の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)
}

答え:
0~99、または99~0のprint関数を変更します.
この問題は出力順序を乱し,根本的な解決策はタイマ内の関数を同じタスクキューで実行させることである.settimeout関数と閉包に対する理解を考察する.
答え1:
momodiyはまず解法を与えた
function print(n){
  setTimeout((() => {
    console.log(n)
    return ()=>{}
  }).call(n,[]), Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}

この方法は当分理解できなかった
答え2:
ryanZieglerはsettimeout関数のパラメータ値を利用して答えを与えた.
文章の末尾にsettimeout関数の紹介があります.
function print(n){
  setTimeout(() => {
    console.log(n);
  }, 1, Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}

答え3:
dorseysenとdefyproは直ちに実行関数でこの問題を解決した.
function print(n){
   setTimeout( (() => {
        console.log(n);
        return ()=>{};
  })(), Math.floor(Math.random() * 1000));
}

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

答え4:
dorseysenは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)
}

答え5:
dreamskは式を直接利用して答えを出した.
function print(n){
  setTimeout(console.log(n), Math.floor(Math.random() * 1000));
}

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

答え6:
ByeWordはvarで定義した変数iを利用する
for文ブロックvarは変数が外部の役割ドメインに存在することを宣言し、settimeoutのコールバックは変数iを直接参照することができる.
function print (n) {
  setTimeout(() => {
    console.log(i--)
  }, Math.floor(Math.random() * 1000))
}
for(var i = 0; i < 100; i++){
  print(i)
}

答え7:
zhangxiangliang注釈法
function print(n){
  // setTimeout(() => {
    console.log(n);
  //}, Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}

拡張:
前に閉包について書いたことがあります.
JSでは,閉パケットが存在する意味で,関数内部の変数に間接的にアクセスできるようにする.
タイトル:
for (var i = 1; i <= 5; i++) {
  setTimeout(function timer() {
    console.log(i)
  }, i * 1000)
}

この問題の出力は5個6個です.
まずsettimeoutは非同期関数なので、まずループをすべて実行し、このときiは6になるので、6の山を出力します.
正しい順序の結果を出力するには、次の手順に従います.
解決方法1:閉パッケージ
for (var i = 1; i <= 5; i++) {
  (function(j) {
    setTimeout(function timer() {
      console.log(j)
    }, j * 1000)
  })(i)
}

上記のコードでは,まず即時実行関数を用いてiを関数内部に伝達し,このとき値はパラメータjに固定されて変化せず,次回timerという閉パケットを実行すると外部関数の変数jを用いて目的を達成することができる.
解決方法2:setTimeoutの3番目のパラメータを使用する
for (var i = 1; i <= 5; i++) {
  setTimeout(
    function timer(i) {
      console.log(i)
    },i * 1000, i
  )
}

解決方法3:letを使用してiを定義する
for (let i = 1; i <= 5; i++) {
  setTimeout(function timer() {
    console.log(i)
  }, i * 1000)
}

settimeout関数説明リンクsettimeout MDN