很抱歉问这样一个基本的问题,但尽管在过去几个月里阅读了大量关于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 上查看此代码