JavaScript - это из этого - PullRequest
       11

JavaScript - это из этого

11 голосов
/ 22 апреля 2011
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: Fine вместо this.this.this, this.parent.parent. Конечно, parent не существует, но, надеюсь, теперь семантика не помешает.

Edit3: особого случая нет. Предоставленные детали - это почти все, что я получил: есть объект foo, часть прототипа. foo.bar - это метод foo, и предполагается, что он обращается к своему деду. Вот и все. Ничего больше. Вот и вся информация, которая у меня есть.

Редактировать 4: Решено. На основании предоставленного ответа (и некоторой подержанной помощи от Дугласа Крокфорда):

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

Ответы [ 2 ]

7 голосов
/ 22 апреля 2011

Единственный способ сделать это - превратить 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"

Или, если мы переименуем foo и bar в нечто более захватывающее:

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

Почему это так сложно?

Каждая функция вызывается с определенным контекстом , который является отдельным объектом. Независимо от того, вызывается ли он с помощью a.b() или a.b.c.d(), он немедленно передается объекту в слева вызова функции в качестве контекста. Таким образом, контекст для a.b() будет a, а контекст для a.b.c.d() - c. Ключевое слово this ссылается на контекст. Поскольку c является просто объектом (не работающей функцией), у него нет контекста, и у него нет понятия this, поэтому this.this не имеет смысла.

Следовательно, невозможно получить общий доступ к так называемому «родителю». Ответ Хуана дает хорошее концептуальное объяснение почему. Однако, если вы хотите достичь пространства имен в функциях-прототипах, то вы можете сделать это, возвращая расширенный объект из foo.

Обратите внимание, мне также пришлось конвертировать this в Object выше. Это потому, что вы не можете прикрепить свойства к примитивным значениям, таким как строки. var str = "foo"; str.bar = 1 будет работать, но только потому, что JS автоматически преобразует "foo" в объект. Однако, поскольку str ссылается на примитив, а не на автоматически созданный объект, этот объект немедленно удаляется, и мы теряем bar.

3 голосов
/ 22 апреля 2011

У объекта нет способа узнать, к какому объекту он относится.Один и тот же объект (в вашем случае функция) может быть присоединен к нескольким объектам.Вот пример:

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

Если дать ссылку на myObj, как вы могли бы узнать, на какой родительский объект вы ссылаетесь?В одном случае это ничто, другой случай, это objA, последний случай, это «дочерний» объект objB.Если вы объясните, почему вам нужно такое поведение, мы поможем вам решить возникшую проблему.Но ответ на вопрос в том, что вы НЕ МОЖЕТЕ сделать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...