JavaScript - this of this

后端 未结 2 2141
甜味超标
甜味超标 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: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.

提交回复
热议问题