期望 JavaScript 对象中有正确的调用上下文 (this)
考虑一下:
window.onload = function () {
myObj.init();
};
var myObj = {
init: function () {
console.log("init: Let's call the callMe method...");
//callMe is not defined...
callMe();
//Works fine!
this.callMe();
},
callMe: function () {
console.log('callMe');
}
};
由于 init 函数是这样调用的 (myObj.init),所以我希望 this
是 init 函数中的 myObj。如果是这样的话,为什么 callMe
函数会失败?我该如何在不使用 init 主体中的 this 上下文的情况下调用 callMe
函数? (实际上,通过函数一遍又一遍地使用 this
调用对象方法太烦人了。那么拥有单个对象有什么意义呢?)
我想知道如何解决这个问题callMe 方法是使用上面代码中的第一次调用来调用的吗?
Consider this:
window.onload = function () {
myObj.init();
};
var myObj = {
init: function () {
console.log("init: Let's call the callMe method...");
//callMe is not defined...
callMe();
//Works fine!
this.callMe();
},
callMe: function () {
console.log('callMe');
}
};
Since the init function gets called this way (myObj.init), I expect this
to be myObj in the init function. And if that is the case, why the callMe
function fails? How am I supposed to call the callMe
function without using the this context in the init body? (Actually, it's too annoying to call the object methods using this
over and over again through the functions. So what's the point of having a single object?)
I would like to know how can I fix this so that the callMe method gets called using the first invocation in the code above?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
this
在 JavaScript 中永远不会像在其他一些语言中那样是隐式的。尽管有多种方法可以做到这一点,例如使用with
语句:...这通常是一个坏主意。道格拉斯·克罗克福德 (Douglas Crockford) 可能写了一篇关于为什么这是一个坏主意的更好的描述,您可以找到它此处。基本上,使用
with
几乎不可能知道代码将要做什么(如果您在该with
中执行任何其他操作,并且会减慢代码的速度) code> 语句不是来自this
对象)。这并不是 JavaScript 的
this
与其他一些语言不同的唯一原因。在 JavaScript 中,this
完全由如何调用函数来定义,而不是定义函数的位置。当您执行this.callMe()
(或等效的this["callMe"]()
,或者当然foo.callMe()
等),发生了两件事:从属性中检索函数引用,并以特殊方式调用该函数以将this
设置为该属性的对象来自。如果您不以这种方式通过属性调用函数,则调用不会设置任何特定的this
值,并且您将获得默认值(即全局对象;window 在浏览器上)。调用的行为决定了
this
的含义。我在我的博客上的几篇文章中深入探讨了这一点,此处 和此处。如果您查看 JavaScript 的
call
和apply
函数(所有函数对象都可用),这一点(没有双关语)会更清楚。如果我这样做:...它将使用空白对象 (
{}
) 作为this
调用callMe
函数。所以基本上,只要习惯输入
this
即可。 :-) 即使没有隐式this
的语法便利(和混乱!),拥有与对象关联的属性和方法仍然很有用。this
is never implicit in JavaScript as it is in some other languages. Although there are ways to do it, like this using thewith
statement:...it's generally a bad idea. Douglas Crockford probably wrote one of the better descriptions of why it's a bad idea, which you can find here. Basically, using
with
makes it nearly impossible to tell what the code's going to do (and slows the code down, if you do anything else in thatwith
statement that doesn't come from thethis
object).This isn't the only way that JavaScript's
this
is not the same as it is in some other languages. In JavaScript,this
is defined entirely by how a function is called, not where the function is defined. When you dothis.callMe()
(or the equivalentthis["callMe"]()
, or of coursefoo.callMe()
, etc.), two things happen: The function reference is retrieved from the property, and the function is called in a special way to setthis
to be the object that property came from. If you don't call a function through a property that way, the call doesn't set any particularthis
value and you get the default (which is the global object;window
on browsers). It's the act of making the call that sets whatthis
is. I've explored this in depth in a couple of articles on my blog, here and here.This (no pun) can be made even clearer if you look at JavaScript's
call
andapply
functions, which are available on all function objects. If I do this:...it'll call the
callMe
function with a blank object ({}
) asthis
.So basically, just get used to typing
this
. :-) It's still useful to have properties and methods associated with an object, even without the syntactic convenience (and confusion!) of an implicitthis
.您还可以使用模块模式,它捕获闭包内的所有私有变量,因此您可以在没有
this
的情况下自由使用它们,因为它们位于同一范围。然后,您选择要公开的方法/变量:现在:
You can also use the module pattern, which captures all private variables inside a closure, so you are free to use them without
this
, as they're in the same scope. You then pick and choose which methods/variables you want to make public:Now: