JavaScript - this of this

后端 未结 2 2128
甜味超标
甜味超标 2021-02-20 01:27
String.prototype.foo = {};
String.prototype.foo.bar = function() {
    //How can you reference the \"grandparent\" string?
    console.log(this.parent.parent); //obvious         


        
相关标签:
2条回答
  • 2021-02-20 02:23

    There is no way for an object to know what object it's a property of. The same object (in your case a function) could be attached to multiple objects. Here's an example:

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

    If given a reference to myObj, how could you possibly know which parent object you're referring to? In one case, it's nothing, another case, it's objA, the last case, it's a 'child' object of objB. If you explain why you'd like this behavior, we can help you solve the problem at hand. But the answer to the question is that you CAN'T do it.

    0 讨论(0)
  • 2021-02-20 02:27

    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!"
    

    Why is it so complicated?

    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.

    0 讨论(0)
提交回复
热议问题