为什么“这个”? JavaScript 中的解析有这么特别吗?

发布于 2024-11-15 12:47:56 字数 1857 浏览 1 评论 0原文

警告:首先是有问题的 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 范围,如果我有是的)而不是引用封闭闭包的 this 。这样,输出将是:

0

代替

1

我将列出更好的(仍然不完美,但还可以)解决方案,然后提出主要问题。所以,解决方案(恕我直言)可以这样整理:

// 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 中的其他人不同?为什么只是这个以及目的是什么?

多谢!

更新:遵循下面@Jordan的评论(他解释了相对变量(如this)和作用域变量(如常规的),重新表述我的问题:

A:相对变量背后的一般原理是什么?

B:为什么this是JavaScript中唯一的相对变量?关于为什么相对/范围概念可以(排他地)应用于每个变量的任何理由?

Warning: Buggy JavaScript code first!

// 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>");

As it can be seen, the this in increment_helper rather refers to the global scope (or to window scope to be precise IF I've got it right) instead of referring to the this of the enclosing closure. So that, the output will be:

0

instead of

1

I'll list the better (still not perfect, but okay) solution and then will ask the main question. So, the solution (IMHO) can be sorted out like this:

// 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>");

So, the main question is: why this is special like noone else in JavaScript? Why it's only this and for what purpose?

Thanks a lot!

Update: Following @Jordan's comment below (where he explained the difference between relative variables like this and scoped variables like regular ones), rephrasing my questions:

A: what is the general rationale behind relative variables?

B: why this is the only relative variable in JavaScript? Any rationale on why the relative/scoped concept can be (exclusively) applied to every variable?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

悲念泪 2024-11-22 12:47:56

答:在 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 可以。因此 this 必须是相对的。是的,它会引起问题,但是语言变得令人难以置信具有表达力。

B. arguments 也是相对的。

A. In JavaScript, unlike in other C-like OO languages, functions are first class objects. You can copy functions around, pass them into other functions, return them from functions, create new ones. Functions are not like methods in Java or C# that are permanently affixed to the class declaration. This means that this has to be relative to the function itself and how it was called. It doesn't make sense otherwise.

So as a silly example:

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"

That can't be done in other OO C-type languages, but it can in JavaScript. Hence this has to be relative. Yes, it causes problems, but the language becomes incredibly expressive with it.

B. arguments is also relative.

酷到爆炸 2024-11-22 12:47:56

JavaScript 与 Java 只是表面上相似。当您查看语法时,您会发现对象模型完全不同(没有类),并且它更像是一种函数式语言,而不是面向对象的语言。出于营销原因,Netscape 希望 JavaScript 看起来像 Java。为此,它采用了一些您可能意想不到的功能,例如按位运算符(在没有整数数据类型的脚本语言中)。
this 就是这些功能之一。

从历史上看,this 之所以这样定义,是因为设计者可以尽可能地模仿它在 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),因为在内部类中,< code>this 不是 Foo 的实例。

JavaScript has only superficial resemblance to Java. When you look past the syntax you notice the object model is totally different (no classes) and it is more of a functional language than an object-oriented one. Netscape wanted JavaScript to look like Java for marketing reasons. To that end it picked up several features you might not otherwise expect, such as bitwise operators (in a scripting language with no integer data type.)
this is one of those features.

Historically, the reason this is defined the way it is, is because that's as close as the designers could get to mimicking the meaning it has in Java.

Also, consider what happens when you write the nearest equivalent code in 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; }
}

The indicated line doesn't even compile (you have to say ++Foo.this.count) because within the inner class, this isn't an instance of Foo.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文