“这个”行为的理由是什么? JavaScript 中的关键字?
我是从语言设计的角度来问这个问题的。 所以我试图找出
this
行为的基本原理是什么?this
的行为在多大程度上是错误的,或者可以改进?
为了澄清为什么我对 this
感到不安,请考虑以下示例:
var a = {};
a.f = function(){ return this; }
var f = a.f;
// f() != a.f()
注意 f()
所属的对象是多么容易丢失:与 a
分离code>,this
成为全局对象(浏览器的 window
)。
现在考虑一下:
var newA = function(){
var self = {};
self.f = function(){ return self; }
return self;
}
var a = newA();
var f = a.f;
// f() == a.f() !
根本不使用 this
,无论在何处或如何使用该方法,我们都能够建立和维护对象上下文。 我不禁想到,凭借闭包提供的力量,this
变得多余,甚至可能有点危险......
我并没有对 this
怀恨在心。 code>,或者想要开始争论; 我只是想更好地理解它。 我确实很欣赏“这个”很有用,但认识到 它也可能令人困惑...当然会让初学者感到困惑,也许在足够晦涩的情况下也会让专家感到困惑。
然而,在该语言的其他核心方面似乎可以公平回避的时候(即 Crockford 和 with
或 新)。 那么我错过了什么,使得
this
不可或缺?
I am asking this from a language design point of view. So I am trying to find out
- What is the rationale for the behavior of
this
? - To what degree the behavior of
this
was a mistake, or could be improved upon?
To clarify why I'm uneasy about this
, consider this example:
var a = {};
a.f = function(){ return this; }
var f = a.f;
// f() != a.f()
Note how easily the object to which f()
belong is lost: separated from a
, this
becomes the global object (window
for browsers).
Now consider:
var newA = function(){
var self = {};
self.f = function(){ return self; }
return self;
}
var a = newA();
var f = a.f;
// f() == a.f() !
Without using this
at all, we are able to establish and maintain the object context regardless of where or how the method is used. I can't help but think that, with the power that closures provide, this
becomes superfluous, and perhaps even a little dangerous...
I'm not on some vendetta against this
, or looking to start an argument; I'm merely trying to better understand it. I do appreciate that 'this' can be useful, but recognize that it can be confusing as well... Certainly confusing to beginners, and perhaps to experts as well in sufficiently obscure cases.
And yet, it remains a heavily-used and seemingly well-respected part of the language, in a time when other core aspects of the language seem fair game for shunning (i.e., Crockford and with
or new
). What am I missing then, that makes this
indispensable?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
您似乎期望 this 的行为与某些面向对象语言中的行为相同,其中它始终引用方法所属的对象。
但在 JavaScript 中,一个函数可以附加到多个对象,或者根本不附加到任何对象。 在您的示例中,您编写了一个旨在在一个特定对象的上下文中使用的函数...但是没有什么可以阻止我获取该函数并将其附加到任何其他对象。 这就是语言的本质 - 函数是一流的,对象成员资格是可选的。
因此,this指的是调用函数的上下文。 现在,它可以是任意对象(通过
.
、.apply
或.call()
指定)或全局对象。 在该语言的未来版本中,它将引用定义函数的上下文:全局函数的全局对象,内部函数的外部this
; 您可以将此视为对设计缺陷的修正,因为在实践中能够使用它引用全局对象并不是特别有用。You seem to be expecting this to behave as it does in certain OO languages, where it always refers to the object a method belongs to.
But in JavaScript, a function can be attached to multiple objects, or no object at all. In your example, you've written a function intended to be used in the context of one specific object... But nothing prevents me from taking that function and attaching it to any other object. That's just the nature of the language - functions are first-class, object membership is optional.
Therefore, this refers to the context in which a function is called. Right now, that's either an arbitrary object (specified via
.
,.apply
, or.call()
) or the global object. In future versions of the language, it will refer to the context in which the function was defined: the global object for global functions, the outerthis
for inner functions; you can view this as a correction of a design flaw, as in practice being able to refer to the global object using this was not particularly useful.我不认为让“this”不受约束是一个错误。 有时一开始可能会令人困惑,但这是有充分理由的。 首先想到的是,由于 JavaScript 不是基于类的语言,函数不与任何特定的类关联,因此没有一致的方法来自动将“this”绑定到正确的对象实例。 例如,
“this”需要引用 Person 对象,但是分配给 Person.prototype.getName 的函数没有任何方法知道它将如何使用,因此“this”需要绑定到任何对象它被召唤。
当您有嵌套函数时,这会导致问题。
语法 将“this”绑定到特定对象非常容易:
artificialidiot 建议会很方便,但是使用 apply:或使用闭包的更“传统”方法
I don't think making "this" unbound was a mistake. It can sometimes be confusing at first, but there are good reasons for the way it is. The first one that comes to mind is that, since JavaScript is not a class based language, functions are not associated with any specific class, so there's not a consistent way to automatically bind "this" to the correct object instance. For example,
"this" needs to refer to a Person object, but the function assigned to Person.prototype.getName doesn't have any way of knowing how it's going to be used, so "this" needs to be bound to whatever object it is called on.
Where this causes a problem, is when you have nested functions.
The syntax artificialidiot suggested would be convenient, but it's pretty easy to bind "this" to a specific object using apply:
or the more "traditional" method using closures:
我认为未绑定的“这个”是一个错误。 否则它非常方便。 未绑定的“this”可能会误解浏览器事件处理中最明显的上下文。 此外,JavaScript 库对于事件处理和许多回调结构(如映射、过滤器)中的“this”应该指代的内容有不同的看法。
删除未绑定的“this”可能不会让事情变得更加困难。
编辑:我想一个替代语法示例将使我的立场更加清晰。
I think unbound "this" is a mistake. Otherwise it is quite handy. Unbound "this" opens the possibility of misinterpreting the context most prominently apparent in event handling of browsers. Also javascript libraries have different opinions of what "this" should refer to in event handling and many callback constructs (like map, filter).
Removing unbound "this" probably wouldn't make things any more difficult.
Edit: I guess an alternative syntax example will make my stance clearer.
我认为未绑定的“this”关键字是必要的,因为 JavaScript 是一种基于原型的语言。 消息灵通的人可能可以在这里填写详细信息。
但事实确实如此,这毫无帮助。 特别是如果您想将对象的方法传递给高阶函数,事情就会开始变得丑陋(以下示例在 MooTools 的帮助下):
将不起作用,因为 myObject.foo 中的“this”将引用myArray 而不是 myObject。 相反:
这对我来说看起来很丑陋。 这就是为什么我通常不在 JavaScript 中以面向对象的方式进行编程,而是严重依赖闭包。
I think the unbound 'this' keyword is necessary because JavaScript is a prototype-based language. Someone better informed can probably fill in the details here.
The fact that it is, is mightily unhelpful though. Especially if you want to pass the method of an object to a higher-order function, things start to get ugly (following examples with a little help from MooTools):
Will not work, because the 'this' in myObject.foo will refer to myArray instead of myObject. Instead:
Which seems very ugly to me. That's why I usually don't program in an object-oriented way in JavaScript, but I rely heavily on closures instead.
将习惯用法
af()
视为以下内容的简写:根据定义,它是使用范围
a
调用函数f
。如果
this
和a
不是同一个对象,f()
和af()
将使用不同的作用域,并且因此可能表现不同。 考虑其他语言中静态方法和类方法之间的区别:Consider the idiom
a.f()
as a shorthand for:It's by definition a call to the function
f
, using scopea
.If
this
anda
are not the same object,f()
anda.f()
will use different scopes and therefore may behave differently. Consider the distinction between static and class methods in other languages:抱歉,但我真的很喜欢 Python ;-)
Sorry, but I really like Python ;-)