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