【问题标题】:Hoisting in a self-calling function in JavaScript在 JavaScript 中提升自调用函数
【发布时间】:2017-09-11 18:15:05
【问题描述】:

我知道提升的一般规则,变量和函数在编译阶段被提升。

所以写成下面这样

var foo = 'global';

将被编译为,

var foo; // Undefined
foo = 'global'; // Declared

但这是我无法理解的


var foo = 'global';
var myObject = {
    foo: 'local',
    func: function(){
        console.log(this.foo); // Local
        (function(){
            console.log(this.foo); // Global
        })();
    }
}
myObject.func();

为什么myObject里面的自调用函数打印全局的foo/取window的上下文?

总的来说,我想了解的是它在哪里被吊起。

【问题讨论】:

  • 因为 IIFE 中的 thiswindow。调用它的执行上下文是全局上下文。这是因为函数没有在obj.func()这样的对象上调用,所以this默认引用window
  • 不应该只在声明obj.func()时才执行自调用函数。
  • @patz 它与提升无关。你对context的理解不适合js...

标签: javascript


【解决方案1】:

Window 是一个全局上下文,一切都在其中执行(通常)。

无论您在函数之外(或在没有var 的函数中)声明的内容都被视为全局对象的属性(方法)。

例如,当您调用setTimeout(foo, 1000)setInterval(foo, 1000) 时,它会相应地被视为window.setTimeout(foo, 1000)window.setInterval(foo, 1000)

这部分:

func: function(){
  console.log(this.foo); // local
  (function(){ 
     console.log(this.foo); // global
  })();

当您调用第一个console.log 时,它是在作为对象方法的函数内部调用的。下一个 console.loganother 函数内部调用,该函数与 func 不在“同一级别”,因此默认情况下它的调用上下文是全局对象。

当然,您可以通过以下行来存储对对象本身的引用:

var self = this

所以代码如下所示:

func: function(){
  console.log(this.foo); // local
  var self = this;
  (function(){ 
     console.log(self.foo); // now it's local
  })();

2.

问题更多是关于自调用功能。是在 myObject 顶部外部/上方悬挂的自调用函数。

在您的特定情况下

提升是关于函数内部的变量声明

对象声明不是一回事。 func 只是一个对象的属性。在函数定义中可以满足提升:

foo = "global";
var test = function(){
    var foo;
    // Declared but not defined
    console.log(foo);
    foo = 'local';
    // Now it's defined. Thanking to functional scope, the function "sees" local variable
    console.log(foo);
}

甚至更好:

foo = 'global';
var test = function(){
    console.log(foo); // undefined, but declared
    var foo;

    foo = 'local';
    console.log(foo);
}

【讨论】:

    【解决方案2】:

    在调用console.log(this.foo) 之前添加console.log(this);,您将看到this 本质上只是window。这就是为什么你会得到全局 foo

    函数中this的默认值是直接调用时的“全局对象”;在浏览器中,全局对象是window。在这种情况下,您也会看到 window

    function foo() {
        console.log(this);
    }
    foo();
    

    由于您已经定义了一个函数表达式并立即调用它,它本质上是直接调用该函数(类似于您直接调用常规函数的方式)。

    【讨论】:

    • 但也许可以解释一下为什么是window...?
    • @AndrewLi 刚刚添加了一行解释原因。
    • 问题更多是关于自调用功能。是在 myObject 顶部外部/上方悬挂的自调用函数。
    • @patz IIFE 涉及一个函数表达式,所以它没有被提升。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多