我来自 Java 背景,具有基于类的继承模型,试图了解 Javascript 的基于原型的继承模型。让我失望的部分原因是,我牢牢记住了 Java 对“this”的含义——而 Javascript 的“this”是一个非常不同的野兽。我知道 Javascript 的“this”总是指函数的调用者,而不是定义函数的范围——我的意思是,我已经阅读了它并从表面上理解了它的含义。但我想更深入地了解,我认为给它取另一个名字会有所帮助。您如何看待 JS“这个”?每次遇到它时,您都会进行心理替代吗?如果是这样 - 你使用什么词或短语?
8 回答
this
可能会context
在 Javascript 中合理地重命名为。
它实际上是指当前范围的执行上下文,虽然该上下文可以是类的实例,但它当然不一定是 - 它可以是任何对象,并且可以在运行时修改.
证明无法保证 Javascript 中的“方法”在定义它的“类”的实例上运行:
function Cat(){
this.texture = 'fluffy';
this.greet = function(){
alert("Pet me, I'm " + this.texture);
}
}
var cat = new Cat();
// Default to using the cat instance as the this pointer
cat.greet(); // Alerts "Pet me, I'm fluffy"
// Manually set the value of the this pointer!
cat.greet.call({texture: 'scaly'}); // Alerts "Pet me, I'm scaly"
需要注意的是,对象的值this
完全独立于包含函数的定义位置。
一种可能的替代名称是owner
. 这将使您的想法转向所有者可以根据您正在执行的代码进行更改的方向。
这个例子来自quirksmode:
在 JavaScriptthis
中,总是指我们正在执行的函数的“所有者”,或者更确切地说,指的是函数作为方法的对象。当我们在页面中定义我们忠实的函数 doSomething() 时,它的所有者就是页面,或者更确切地说,是 JavaScript 的窗口对象(或全局对象)。但是,onclick 属性归其所属的 HTML 元素所有。
在下面的代码中,
function doSomething() {
this.style.color = '#cc0000';
}
和
element.onclick = doSomething;
,owner
指向执行时包含该方法的对象。
------------ window --------------------------------------
| / \ |
| | |
| this |
| ---------------- | |
| | HTML element | <-- this ----------------- |
| ---------------- | | doSomething() | |
| | | ----------------- |
| -------------------- |
| | onclick property | |
| -------------------- |
| |
----------------------------------------------------------
我认为 JavaScript比你想象this
的更接近 Java 。this
在 OOP 上下文中,this
表示“此实例”。我认为 JavaScript 的this
关键字可能令人困惑的是,它可能具有不同的含义,具体取决于上下文。
this
不是函数的调用者(尽管它可能是)或定义函数的范围(尽管它可能是) - 它是函数的context。
@Andrew Hare 所指的转换含义可能更接近您困惑的根源;由于 JS 的原型继承机制,function
关键字可能意味着,取决于它的使用方式,它class
比 Java 的方法定义更接近 Java。
假设在浏览器中执行:
var q = this.document; //this is window
var o = new (function pseudoconstructor(){
this.property = "something else" //the new keyword changed 'this' to mean 'the object I'm about to return'
})();
“JavaScript this”怎么样?它会让你直接与你正在做的事情联系在一起,并提醒你当前正在使用的“this”概念是 JavaScript 概念。
最终,我希望您不再将其称为“JavaScript this”,而是将其称为“this”,充分了解在您工作的上下文中这意味着什么。我希望这可能是您想要的无论如何,要到达。
我吸收了新颖的语法,并带有一些易于输入的心理模型,例如:
$(document).ready(function() {
function baffle() {
alert(this.b);
}
function what() {
this.b = "Hello";
baffle();
}
function huh() {
this.b = "World";
baffle();
}
what();
huh();
}
);
这很糟糕地翻译成草率的、想象中的 C++ 为:
template <class This>
function baffle() {
alert(This.b);
}
function what() {
b = "Hello";
baffle<what>();
}
function huh() {
b = "World";
baffle<huh>();
}
what();
huh();
我认为this
出于历史原因是最合适的。在 JavaScript中并没有一个千篇一律的短语this
,因为它不仅可以自动分配给非常不同的引用,例如,this
在过程函数的上下文或this
对象的上下文中,而且this
可以也由脚本编写者使用Function.apply
和分配Function.call
。
但是, 的含义this
只能调整,因为 JavaScript 和 DOM 以一些非常奇怪的方式工作。例如, 的主要用途Function.apply
是在事件调用中保留元素引用的上下文。您将在 Prototye 的Function.bind()
方法中看到这一点。
this
是执行函数的上下文的占位符,很难得到比这更具体的内容。然而,大多数使用this
使它成为语义上合适的关键字。在 的情况下bind()
,即使我们使用方法来任意更改this
函数内的含义,也应该使用它来this
比没有它时更合适。许多业余 JavaScript 程序员对this
事件处理程序的奇怪行为感到厌烦,并Function.apply
习惯于纠正这种“错误”。
自我参照逻辑(self 或 this)避免了悖论,从而有利于在 self(this)以外的地方工作。自我(this)是否应将所有内容保持为一,它也可以保持静态,没有实例,而是使用类方法(静态)。为了避免悖论,避免自我引用,逻辑保持所有真理可证明,反之亦然,所有可证明为真。