问题描述
|
警告:错误的JavaScript代码优先!
// 1: buggy counter
// -----------------
// problem: \'this\' can be \"broken\"
var Counter1 = function() {
this.count = 0;
this.increment = function() {
function increment_helper(){
++this.count; // this refers to window (global),not to the object that Counter1 was called with
}
increment_helper();
}
this.reset = function() { this.count = 0; }
this.get_count = function() { return this.count; }
}
var counter1 = new Counter1();
counter1.increment();
document.writeln(\"<p> 1: \" + counter1.get_count() + \"</p>\");
可以看出,increment_helper
中的this
而是指全局作用域(或者,如果我理解正确的话,是指window
范围),而不是指封闭的闭包。这样,输出将是:
0
代替
1个
我将列出更好的解决方案(仍不完美,但还可以),然后提出主要问题。因此,解决方案(IMHO)可以像这样进行分类:
// 2: better counter
// -----------------
// solved: \'that\' can\'t be \"broken\"
var Counter2 = function() {
var that = this;
that.count = 0;
that.increment = function() {
function increment_helper(){
++that.count; // that refers right to the object the Counter1 was called with
}
increment_helper();
}
that.reset = function() { that.count = 0; }
that.get_count = function() { return that.count; }
}
var counter2 = new Counter2();
counter2.increment();
document.writeln(\"<p> 2: \" + counter2.get_count() + \"</p>\");
因此,主要问题是:为什么this
在JavaScript中与众不同?为什么只有ѭ1,又是什么目的?
非常感谢!
更新:在下面@Jordan的评论(他解释了相对变量(如this
)和范围变量(如常规变量)之间的区别)后,我改了一下我的问题:
答:相对变量背后的一般原理是什么?
B:为什么ѭ1是JavaScript中唯一的相对变量?为什么相对/范围概念可以(专门)应用于每个变量有任何理由?
解决方法
答:在JavaScript中,与其他类似C的OO语言不同,函数是一流的对象。您可以复制函数,将它们传递给其他函数,从函数中返回它们,创建新函数。函数与永久固定在类声明中的Java或C#中的方法不同。这意味着
this
必须相对于函数本身及其调用方式。否则,这没有任何意义。
举个愚蠢的例子:
var o = {
name: \"My name is o\",foo: function () { alert(this.name); }
};
var p = {
name: \"My name is p\",};
p.foo = o.foo;
p.foo(); // \"My name is p\"
使用其他OO C类型语言无法做到这一点,但是可以使用JavaScript。因此ѭ1必须是相对的。是的,这会引起问题,但是这种语言会令人难以置信地表现出来。
B.arguments
也是相对的。
, 本文将使您对\“ this \”在javascript中的工作方式有深入的了解。
, JavaScript仅在表面上类似于Java。当您浏览语法时,会发现对象模型完全不同(没有类),并且它比面向对象的更像是一种功能语言。由于市场营销的原因,Netscape希望JavaScript看起来像Java。为此,它获得了一些您可能不会想到的功能,例如按位运算符(使用没有整数数据类型的脚本语言)。
this
是这些功能之一。
从历史上看,之所以用“ 1”来定义它,是因为与设计人员在模仿Java中的含义一样近。
另外,请考虑当您用Java编写最接近的等效代码时会发生什么:
class Foo {
int count = 0;
IncrementHelper helper = new IncrementHelper() {
public void increment() {
++this.count; // doesn\'t compile
}
}
public void increment() { helper.increment(); }
public void reset() { this.count = 0; }
public int getCount() { return this.count; }
}
指示的行甚至没有编译(必须说++Foo.this.count
),因为在内部类中,this
不是Foo的实例。