顺序函数调用的执行上下文-这将更改为窗口

Execution context of sequential function calls - this changes to window

本文关键字:窗口 函数调用 执行 上下文 顺序      更新时间:2023-09-26

很抱歉问这样一个基本的问题,但尽管在过去几个月里阅读了大量关于javascript的文章,特别是关于这个问题,但我对它的执行上下文和"this"没有什么了解。因此,我希望使用我的具体场景进行解释会有所帮助。我有一个构造函数,其中有一些本地函数和一些公开函数(模仿公共/私有方法)。

function blog() {
    if (!(this instanceof blog))
        return new blog();
    function internal(){
        alert(this);
    }
    this.external = function(){
        alert(this);
        internal();
    }
}
var b = new blog();
b.external();

external中,"this"是b,正如我所期望的那样,是博客的一个实例。我错误地认为这在internal内部也是正确的,但它实际上是全局窗口对象。作为一个实验,我尝试将external的调用更改为this.internal(),这会导致this.internal不是函数的错误。就在这时,我意识到我真的不了解它的工作原理。好的,我还没有定义一个名为internal的博客属性,但如果internal不是在我的博客实例上定义的函数,它是什么,它在哪里定义?也许我把这个结构搞错了。

请在此处查看xdazz的答案:https://stackoverflow.com/a/12241726/2469255

然而,为了解决您的问题,您需要定义this对该函数的意义。

调用内部调用时没有提供this上下文,因此它绑定到全局对象,而不像this.external那样将其作用域设置为博客对象。按照以下方式重写代码将解决此问题:

function blog() {
    if (!(this instanceof blog))
        return new blog();
    function internal(){
        console.log(this);
    }
    this.external = function(){
       console.log(this);
       internal.bind(this);
       internal.call(this); // this in internal will be the object blog.
    }
}
var b = new blog();
b.external(); //blog {external: function} blog {external: function}

或者,很多人更喜欢var self = this,以确保不会出现这样的问题,并且你确切地知道设置了什么,在哪里。关于这个特定的想法有很多争论,所以YMMV

让我试着解释一下。

只有在没有new关键字的情况下简单调用blog(),才能访问下面的这段代码。

if (!(this instanceof blog))
    return new blog();

但是,这不是推荐的做法,因为它会影响代码的清晰度。

因为这个:

var realObj = new Blog();

是实例化对象的正确代码,下面的代码是:

var obj = blog();

不够清楚,可能会导致错误。

JavaScript最初有一个原型继承,Douglas Crockford对此有更好的解释。

internal()external没有相同引用的主要原因是,内部有一个指向全局的作用域,而当您创建博客实例时,外部作用域指向对象博客。

真的很困惑,因为博客声明中的this都指向全局,那么为什么当你实例化博客this时会改变呢?

当浏览器开始读取您的代码时,它会将发现的内容放在内存中,并通过作用域进行引用。记住,作用域是由{}控制的,所以当他找到你的声明this.external时,他会关联到作用域,当你使用new声明时,this会成为对象的作用域,所以this不再引用全局作用域。

在jsbin.com 上查看此代码