【问题标题】:call() a function within its own context在自己的上下文中调用()一个函数
【发布时间】:2019-09-24 06:02:02
【问题描述】:

var f = function() {
  this.x = 5;
  (function() {
    this.x = 3;
  })();
  console.log(this.x);
};

f.call(f);

f();

f.call();

运行var f 作为f.call(f) 输出5。当以f()f.call() 运行时,输出3

每种情况会发生什么?内部函数的this是指什么?

【问题讨论】:

  • 不要混淆这两个引用。而是尝试查看有两个不同的堆栈帧。每个帧都有一个 this 引用。这要么是默认值,要么是由 call() 设置的。无法设置内部函数。它始终是默认值。我认为这是默认的窗口,但这取决于是否有模块加载器。我应该知道,但我不记得了。
  • 如果你想添加一些其他的作用域/上下文,使用.bind(context)方法。
  • 这就是为什么你总是应该使用严格模式...
  • 这也是为什么你应该使用 lambdas 而不是匿名函数

标签: javascript this


【解决方案1】:

第一种情况:

首先,您正在调用该函数。在函数内部,函数本身即f被设置为this。所以在第一个示例中,this.x = 5; 在函数上设置了属性x

当调用内部函数时,this 引用了window 对象,所以this.x = 3; 改变了窗口对象的x 属性。

当它在此处记录console.log(this.x); 时,将记录设置为函数属性的相同属性x

第二种情况:

在第二个示例中,外部函数内部的this 引用window,因此当评估this.x = 3; 时,window.x 变为3。由于this 在外部函数中引用window,所以console.log(this.x); 记录window.x3

结论:

整个讨论的结论是,如果没有参数传递给call(),那么window 对象会自动绑定。根据MDN

thisArg

可选的。为调用函数提供的 this 的值。请注意,这可能不是方法看到的实际值:如果方法是非严格模式下的函数,null 和 undefined 将被替换为全局对象,原始值将转换为对象。

请参阅下面的 sn-p。

function foo(){
  console.log(this);
}
foo.call(foo); //foo function
foo.call(); //window object

【讨论】:

    【解决方案2】:

    如果没有特定的上下文,this 将是 window。你的内部函数总是在没有上下文的情况下运行,所以它将window.x设置为3。如果你调用f(),它也会以this作为window运行,因此记录3。

    如果你这样做 f.call(f)this 将是 f 函数对象,它的 x 属性将设置为 5。

      f.call(f)
      console.log(
        f.x, // 5
        window.x // 3
      );
    

    如果还不清楚,我建议使用 debugger 逐步完成。

    【讨论】:

      【解决方案3】:

      当您调用 f 并引用自身时,它会将函数上的 x 属性设置为 5,并且内部匿名函数的 this 引用窗口,因此它将 window.x 设置为 3 . 在匿名函数之外,this 仍然是指函数f,所以console.log(this.x) 输出5。

      当您使用 f()f.call() 调用 f 时,函数 f 和其中的匿名函数将 this 引用设置为 window(默认值),因此更改内部 this.x 的值或在匿名函数之外影响输出结果。

      如果你控制台记录this 在函数 f 内部和内部匿名函数内部的值,你可以清楚地看到这一点。

      var f = function() {
      	console.log("This inside function f:", this.toString());
        this.x = 5;
        (function() {
      	  console.log("This inside anonymous inner function:", this.toString());
          this.x = 3;
        })();
        console.log(this.x);
      };
      console.log("calling function x with this set to itself");
      f.call(f);
      console.log("---------------")
      console.log("invoking function x with brackets ()")
      f();
      console.log("---------------")
      console.log("calling function x without setting this context")
      f.call();
      console.log("---------------")

      【讨论】:

        【解决方案4】:

        除其他答案外,如果您想要可预测的行为,您至少有 2 种方法可供您使用。

        方法一:(关闭)

        var f = function() {
          this.x = 5;
          var that = this;
          (function() {
            that.x = 3;
          })();
          console.log(this.x);
        };
        
        f.call(f); // 3
        
        f(); // 3
        
        f.call(); // 3
        

        方法二:(箭头函数)

        var f = () => {
          this.x = 5;
          (function() {
            this.x = 3;
          })();
          console.log(this.x);
        };
        
        f.call(f); // 3
        
        f(); // 3
        
        f.call(); // 3
        

        【讨论】:

          【解决方案5】:

          'this'关键字指的是当前代码正在其中执行的上下文对象。在任何函数之外,this指的是全局对象。

          通过使用call()apply() 函数,this 的值可以从一个上下文传递到另一个上下文。

          • 所以在第一种情况下 [f.call(f)] 通过调用 call 函数和 将第一个参数设为fthis.x 指的是 5。所以答案是 打印为 5。
          • 第二种情况 [f()] 它正在调用函数而不使用 call 功能。所以它将this的执行上下文引用为3。所以它 打印为 3。
          • 第三种情况[f.call()],调用函数内部没有 论据被提及。所以它引用全局对象并打印3 作为输出。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-08-03
            • 2020-03-27
            • 2015-05-29
            • 1970-01-01
            • 1970-01-01
            • 2022-06-10
            • 1970-01-01
            • 2012-06-28
            相关资源
            最近更新 更多