【问题标题】:Function defined in setTimeout has access to the outer variables in JavaScriptsetTimeout 中定义的函数可以访问 JavaScript 中的外部变量
【发布时间】:2024-01-02 13:18:01
【问题描述】:

我知道this 关键字总是指当前作用域的this,只要你在function() { ... } 中包装一些东西,它就会改变。我的问题是,为什么我可以在setTimeout函数内部的函数中访问外部作用域变量x

var x = 45;

function getRecipe(recipe) {
  x = 35;
  return {
    displayRecipe: function(a) {
      //here we have access to x=35
      setTimeout(function() {
        //why do we have access to x=35 and to recipe here?
        console.log(this.x + a + recipe);
      }, 1500)
    }
  }
}

getRecipe("noodles").displayRecipe(2);

【问题讨论】:

    标签: javascript scope this settimeout


    【解决方案1】:

    当不在strict mode 中,并且调用未设置this 时,this 内部函数将默认为global object(浏览器中为window)。

    function f1() {
      return this;
    }
    
    console.log(f1() === window); // true

    同样在非严格模式下的浏览器中,使用var 声明的全局变量(在global scope 中声明的变量)也被创建为全局对象的成员。

    var foo = "foobar";
    console.log(foo === window.foo);

    因为您的x 被声明为全局变量,所以它也被添加为window 对象的成员。因为您的setTimeout 回调没有显式设置this 范围,所以它也默认为全局对象,因此您可以通过this 访问x

    如果x 没有在全局范围内声明(或者在严格模式下或使用let/const 语句声明),您将无法访问它:

    (function() {
      var x = 45;
    
      function getRecipe(recipe) {
        x = 35;
        return {
          displayRecipe: function(a) {
            //here we have access to x=35
            setTimeout(function() {
              //why do we have access to x=35 and to recipe here?
              console.log(this.x, a, recipe);
            }, 1500)
          }
        }
    
      }
    
      getRecipe("noodles").displayRecipe(2);
    })();

    【讨论】:

    • 所以 x=35 是在全局范围内声明的?
    • var x = 45; 在全局范围内声明,因此是一个全局变量。在getRecipe 函数中将此全局变量的值更改为35。 (但改变值并不会改变变量的范围。)
    【解决方案2】:

    你应该把 let 放在 x=35 之前

    var x=45;
    function getRecipe(recipe){
          let x=35;
          return{
             displayRecipe: function(a){
             //here we have access to x=35
                setTimeout(function(){
                    //why do we have access to x=35 and to recipe here?
                    console.log(this.x + a + recipe );
                },1500)
             }
          }
    
    }
    
    getRecipe("noodles").displayRecipe(2);
    
    

    【讨论】:

      最近更新 更多