首页 > 解决方案 > JavaScript 如何访问在它使用的函数之外声明的变量?

问题描述

假设我们在 for 循环中有一个简单的 print 语句,例如

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

两个问题。

setTimeout 是一种浏览器 API 方法,但它是如何访问的i呢?在for循环中声明,即使没有通过,i我也在i方法内部访问,如何?setTimeouti

为什么打印 2,2 而不是 0,1?

标签: javascript

解决方案


setTimeout 是一种浏览器 API 方法,但它是如何访问 i 的呢?i 在 for 循环中声明,我在 setTimeout 方法中访问 i 即使 i 没有通过,如何?

在 javascript 中,嵌套函数可以访问更高阶的变量和函数。

//global context - any variable declared here will be availabe within any nested function
var someVariable = 0;
var someSecondVariable = 1;

const someFunc = () => {
  //someVariable and someSecondVariable are accessible here
  console.log("someFunc", someVariable, someSecondVariable);
  
  var someThirdVariable = 2;
  for(let i = 0; i < 5; i++){
    
    const temp = i;
    
    //all higher order variables are still accessible
    setTimeout(()=>{
      //all higher order variableds are still accessible
      console.log("settimeout", i, temp);
    }, 4000);
  }
  
}

const someFunc2 = () => {
  //cant access someThirdVariable
  try {
    console.log("someFunc2", someThirdVariable);
  }catch(e){
    console.warn(e.message);
  }
}

someFunc();
someFunc2();

为什么打印 2,2 而不是 0,1?

setTimeout 是一种异步方法,不会立即被调用。循环在第一个超时事件开始之前结束。这意味着,在调用 setTimeout 回调时,i 已经等于 2。

  1. i = 0 -> 继续循环
  2. i = 1 -> 继续循环
  3. i = 2 -> 停止循环,因为 2 < 2 = false

然后调用您的 setTimeout 回调

console.log(i) //where i = 2
console.log(i) //where i = 2

在这里你可以有 0,1

for (var i = 0; i < 2; i++){
    //temp won't get increased in the next iteration
    const temp = i;
    setTimeout(() => console.log(temp));
}


例如,与相比,这是不同的,我们必须明确告诉它使用更高阶的变量才能在函数范围内访问它。

<?php

  $i = 0;
  $func = function() use ($i){
    echo $i;
  };
  $func();

推荐阅读