【问题标题】:JavaScript - this of thisJavaScript - 这个这个
【发布时间】:2011-04-21 23:59:58
【问题描述】:
String.prototype.foo = {};
String.prototype.foo.bar = function() {
    //How can you reference the "grandparent" string?
    console.log(this.parent.parent); //obviously, doesn't exist
}

"Hello, Nurse!".foo.bar() 会记录“你好,护士!”。

如果对 foo 有控制权,会有什么不同吗?

编辑:那里,foo 被定义了。

Edit2:很好,而不是this.this.thisthis.parent.parent。当然 parent 不存在,但希望现在语义不会妨碍。

Edit3:没有具体案例。提供的详细信息几乎就是我得到的所有信息:有一个对象 foo,它是原型的一部分。 foo.barfoo 的一个方法,应该访问它的祖父母。而已。没有其他的。这就是我掌握的所有信息。

Edit4:已解决。根据提供的答案(以及 Douglas Crockford 提供的一些二手帮助):

String.prototype.foo = function() {
    var that = this;
    return {
        bar : function() {
            console.log(that.valueOf());
        }
    }
}
//Called:
"Hello, Nurse!".foo().bar();

【问题讨论】:

  • 同样的效果,this.this.this不起作用。
  • this仍然自己,而不是父母。
  • @Zirak:我曾经在国外进过一家店,不知道“西红柿”这个词。所以我只是耸了耸肩,转而要草莓,希望店主知道我的意思。它并没有真正起作用。
  • @Zirak:如果你知道这里什么是相关的,什么是不相关的,那么你应该能够自己回答这个问题,嗯? :)
  • 顺便说一下,这并不总是 self,它是函数执行的上下文。如果您使用 call 和 apply 调用函数,则可以将其设置为任何值。

标签: javascript oop


【解决方案1】:

可以做到这一点的唯一方法是将foo() 变成一个函数。将其视为为特定字符串初始化 foo 命名空间:

String.prototype.foo = function () {
    var str = String(this);
    var o = Object(this)
    o.bar = function () {
         console.log(str);
    };
    return o;
};

那么你可以使用:

"foobar".foo().bar(); // logs "foobar"

或者,如果我们将 foobar 重命名为更令人兴奋的名称:

"Hello!".console().log(); // logs "Hello!"

为什么这么复杂?

每个函数都使用一个特定的context 来调用,该context 是一个对象。无论是用a.b() 还是a.b.c.d() 调用都无关紧要 - 函数调用的 left 立即将对象作为其上下文。所以a.b() 的上下文是aa.b.c.d() 的上下文是c。关键字this 引用上下文。因为c 只是一个对象(不是运行函数),它没有上下文,也没有this 的概念,所以this.this 没有意义。

因此,一般无法访问所谓的“父级”。胡安的回答给出了一个很好的概念性解释。但是,如果您想要实现的是原型函数中的命名空间,那么您可以通过从foo 返回一个增强对象来做到这一点。

请注意,我还必须将this 转换为上面的Object。这是因为您不能将属性附加到字符串等原始值。 var str = "foo"; str.bar = 1 会起作用,但这只是因为 JS 会自动将 "foo" 转换为对象。但是,由于str 引用的是原语,而不是自动创建的对象,因此该对象会立即被丢弃,而我们会丢失bar

【讨论】:

  • 这如何让您以通用方式访问 parent 对象?
  • @Juan,str 在这种情况下就是所谓的 parent 对象。
  • 嗯,它是硬编码的,任何人都可以这样做,你也可以直接使用String
  • @Box9:我显然已经看过这个例子了!除了按照我告诉你的方式之外,无法理解它。请解释如何使用它来一般地访问对象的父对象。
  • @Juan 我从未声称一般访问对象的父对象。也许我会在那里添加一个声明来查看您的答案,因为我没有对此提出异议!我只是想解决原型上的命名空间函数问题。
【解决方案2】:

对象无法知道它是哪个对象的属性。同一个对象(在您的情况下是一个函数)可以附加到多个对象。这是一个例子:

var myObj = {};
var objA = {prop: myObj};
var objB = {nother: myObj}

如果给出对 myObj 的引用,您怎么可能知道您指的是哪个父对象?在一种情况下,它什么都不是,另一种情况是 objA,最后一种情况是 objB 的“子”对象。如果您解释您为什么喜欢这种行为,我们可以帮助您解决手头的问题。但问题的答案是您不能这样做。

【讨论】:

  • 知道foo 始终是String 的方法,而bar 始终是foo 的方法是否有帮助?
  • 重点是你不知道。任何人都可以做var b = String.prototype.foo.bar。这就是这种动态语言的本质。
  • 当然,如果我这样做Object.toString = "hi".toLowerCase,你的方法也可以。但它会出错,所以我假设最好的情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-04
相关资源
最近更新 更多