String.prototype.foo = {};
String.prototype.foo.bar = function() {
//How can you reference the \"grandparent\" string?
console.log(this.parent.parent); //obvious
The only way this can be done, is to turn foo()
into a function. Think of it as initialising the foo
namespace for a particular string:
String.prototype.foo = function () {
var str = String(this);
var o = Object(this)
o.bar = function () {
console.log(str);
};
return o;
};
Then you can use:
"foobar".foo().bar(); // logs "foobar"
Or if we rename foo
and bar
into something more exciting:
"Hello!".console().log(); // logs "Hello!"
Each function is called with a particular context that is a single object. Whether it is called with a.b()
or a.b.c.d()
doesn't matter - it is given the object immediately to the left of the function call as its context. So the context for a.b()
would be a
, and the context for a.b.c.d()
is c
. The keyword this
references the context. Because c
is just an object (not a running function) it has no context, and it has no concept of this
, so this.this
makes no sense.
Therefore, it is not possible to generically access the so-called "parent". Juan's answer gives a good conceptual explanation why. However, if what you want to achieve is namespacing in prototype functions, then you can do this by returning an augmented object from foo
.
Notice I also had to convert this
into an Object
above. This is because you can't attach properties to primitive values like strings. var str = "foo"; str.bar = 1
will work, but only because JS automatically converts "foo"
into an object. However, since str
references the primitive, not the automatically created object, the object is then immediately discarded, and we lose bar
.