该';这';JavaScript中的关键字?
我是从语言设计的角度提出这个问题的。所以我想弄清楚该';这';JavaScript中的关键字?,javascript,language-design,Javascript,Language Design,我是从语言设计的角度提出这个问题的。所以我想弄清楚 此行为的基本原理是什么 的行为在多大程度上是一个错误,或者可以改进 为了澄清为什么我对 < 感到不安,请考虑这个例子: var a = {}; a.f = function(){ return this; } var f = a.f; // f() != a.f() 注意f()所属的对象是多么容易丢失:从a中分离出来,此成为全局对象(浏览器的窗口) 现在考虑: var newA = function(){ var self = {}
的行为在多大程度上是一个错误,或者可以改进
为了澄清为什么我对<代码> < <代码>感到不安,请考虑这个例子:
var a = {};
a.f = function(){ return this; }
var f = a.f;
// f() != a.f()
注意f()
所属的对象是多么容易丢失:从a
中分离出来,此
成为全局对象(浏览器的窗口
)
现在考虑:
var newA = function(){
var self = {};
self.f = function(){ return self; }
return self;
}
var a = newA();
var f = a.f;
// f() == a.f() !
根本不需要使用这个
,我们就能够建立和维护对象上下文,而不管方法在何处或如何使用。我忍不住想,有了闭包提供的强大功能,这个
变得多余,甚至有点危险
我不是对这件事有什么仇视,也不是想开始争论;我只是想更好地理解它。我很感激“这”是有用的,但也要认识到。。。对于初学者来说,这无疑是令人困惑的,对于那些非常模糊的案例,专家们也许也是如此
然而,在语言的其他核心方面似乎可以避免的时候(例如,Crockford和with
或new
),它仍然是语言中被大量使用且似乎备受尊重的一部分。那么,我遗漏了什么,这使得不可或缺?
- 不是
- 很多面向对象的东西
- 就这样很好
- 它应该被称为“自我”
- 引用当前对象状态的任何内容
- 通过选择“self”作为“this”的名称,并将其显式(作为第一个参数)传递给所有方法。通过这种方式,您可以很容易地区分实例方法和静态方法或函数
对不起,我真的很喜欢Python;-) 我认为未绑定的“this”是一个错误。否则就很方便了。未绑定的“this”可能会误解浏览器事件处理中最明显的上下文。javascript库对事件处理中的“this”应该指什么以及许多回调构造(如map、filter)也有不同的看法
删除未绑定的“this”可能不会让事情变得更困难
编辑:我想另一个语法示例会让我的立场更清晰
function Foo()
{
//both this refer to the Foo instance
this.blah=this.function(){this.bar;};
//second this refers to baz
this.blah=baz.function(){this.bar;};
//second this refers to anonymous function itself
this.blah=function(){this.bar;};
}
我不认为解开“这个”是个错误。一开始它有时会让人困惑,但这种情况有很好的理由。首先想到的是,由于JavaScript不是基于类的语言,函数与任何特定类都没有关联,因此没有一致的方法自动将“this”绑定到正确的对象实例。比如说,
function Person(first, last, age) {
this.firstName = first;
this.lastName = last;
this.age = age;
}
Person.prototype.getFullName = function() {
return this.firstName + " " + this.lastName;
};
“this”需要引用Person对象,但分配给Person.prototype.getName的函数无法知道如何使用它,因此“this”需要绑定到调用它的任何对象
这导致问题的地方是当您有嵌套函数时
// This is a really contrived example, but I can't think of anything better
Person.prototype.getInfo = function() {
// get name as "Last, First"
function getNameLastFirst() {
// oops. "this" is the global object, *not* the Person
return this.lastName + ", " + this.firstName;
}
// expect something like "Crumley, Matthew: Age 25",
// but you get "undefined, undefined: Age 25"
return getNameLastFirst() + ": Age " + this.age;
};
建议的语法会很方便,但使用apply将“this”绑定到特定对象非常容易:
function bind(func, obj) {
return function() {
return func.apply(obj, arguments);
};
}
Person.prototype.getInfo = function() {
// get name as "Last, First"
var getNameLastFirst = bind(function () {
return this.lastName + ", " + this.firstName;
}, this);
return getNameLastFirst() + ": Age " + this.age;
};
或者使用闭包的更“传统”的方法:
Person.prototype.getInfo = function() {
var self = this;
// get name as "Last, First"
function getNameLastFirst() {
return self.lastName + ", " + self.firstName;
}
return getNameLastFirst() + ": Age " + this.age;
};
我认为unbound'this'关键字是必要的,因为JavaScript是一种基于原型的语言。信息更灵通的人可能可以在这里填写详细信息
事实上,这是毫无帮助的。特别是如果你想把一个对象的方法传递给一个高阶函数,事情就会变得很糟糕(下面的例子有MooTools的一些帮助):
将不起作用,因为myObject.foo中的“this”将引用myArray而不是myObject。相反:
myArray.each(myObject.foo.bind(myObject))
这对我来说很难看。这就是为什么我通常不使用JavaScript以面向对象的方式编程,但我严重依赖闭包。将成语a.f()
a.f.call(a);
根据定义,它是使用scopea
调用函数f
var f = a.f;
f(); // f.call(this);
a.f(); // f.call(a);
如果this
和a
不是同一个对象,f()
和a.f()
将使用不同的作用域,因此可能会有不同的行为。考虑其他语言中静态和类方法之间的区别:
class Foo {
public:
static void a(Foo *scope) {
// do something with given scope
};
void b() {
a(this); // do something with the scope of this object
};
};
Foo foo;
Foo bar;
foo.a(&bar) != foo.b(); // just like f() != a.f()
foo.a(&foo) == foo.b(); // just like f.call(a) == a.f()
您似乎期望它在某些OO语言中的行为,在这些语言中它总是引用方法所属的对象
但是在JavaScript中,一个函数可以附加到多个对象,或者根本没有对象。在您的示例中,您编写了一个函数,用于一个特定对象的上下文中。。。但是没有什么能阻止我接受这个函数并将它附加到任何其他对象上。这就是语言的本质——函数是一流的,对象成员资格是可选的
因此,这是指调用函数的上下文。现在,这是一个任意对象(通过
、.apply
或.call()
指定)或全局对象。在该语言的未来版本中,它将引用定义函数的上下文:全局函数的全局对象,内部函数的外部this
;您可以将此视为对设计缺陷的纠正,因为在实践中,使用它引用全局对象并不是特别有用。是什么让您觉得“这”是一个错误?@Gamecat:您从未尝试过设计类似于javascript的语言,是吗?我仍然认为这是一个有争议的问题。该语言暗示了一个问题,cf“this(如果它是惊人的)”这不是关于js本身的问题。许多人认为这是一个挑战,即如何在js中解决“this”的缺点,或者抱怨js的设计有多么糟糕。我建议人们不要回答,除非他们从一个角度考虑
class Foo {
public:
static void a(Foo *scope) {
// do something with given scope
};
void b() {
a(this); // do something with the scope of this object
};
};
Foo foo;
Foo bar;
foo.a(&bar) != foo.b(); // just like f() != a.f()
foo.a(&foo) == foo.b(); // just like f.call(a) == a.f()