Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
482 views
in Technique[技术] by (71.8m points)

javascript - Using 'this' within nested Prototype sub-objects

I have a class, and have given its prototype several sub-objects to facilitate namespacing. These sub-objects have methods. I can't figure out how to use this inside those methods to access the properties set with the constructor.

I have a feeling bind, call, and apply are involved somehow, but I'm having a good deal of trouble understanding what those do, and how all this OOP-ness works in general. There are plenty of resources, but they're all either too low-level, or so high-level I don't understand them. Thank you!

function Object(
    argument1,
    argument2
){
    this.property1  = argument1;
    this.property2  = argument2;
}

Object.prototype    = {
    subObject1  : {
        method1 : function(){
            return this.property1;
        }
    },
    subObject2  : {
        method1 : function(){
            return this.property2;
        }
    }
}

var foo = new Object(11, 22);
var bar = new Object(33, 44);

console.log(foo.subObject1.method1()); //I'd like this to return 11
console.log(foo.subObject2.method1()); //I'd like this to return 22

console.log(bar.subObject1.method1()); //I'd like this to return 33
console.log(bar.subObject2.method1()); //I'd like this to return 44
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Whenever you have a call of the form foo.bar(), this inside bar will refer to foo. Unless you bind the the function to a specific value with .bind, or use the new "arrow" functions in ES6.

So one solution could be to bind the methods to the specific instance. However, the instance doesn't exist until you call the constructor function. That means you have to create subObjectX inside the constructor:

function MyObject(argument1, argument2) {
    this.property1  = argument1;
    this.property2  = argument2;

    this.subObject1 = {
        method1: function(){
             return this.property1;
        }.bind(this)
    };

    this.subObject2 = {
        method1: function(){
            return this.property2;
        }.bind(this)
    };
}

Or using the new ES6 arrow functions; these take this from the context in which they're created (unlike normal functions):

// ES6 only!
function MyObject(argument1, argument2) {
    this.property1  = argument1;
    this.property2  = argument2;

    this.subObject1 = {
        method1: () => {
             return this.property1;
        }
    };

    this.subObject2 = {
        method1: () => {
            return this.property2;
        }
    };
}

That means that every instance has it's own copy of the sub-object.

If you want to define the methods on the prototype though, you always have to pass the receiver via .call or .apply:

foo.subObject1.method1.call(foo);

in which case there is not much benefit of assigning it to the prototype at all, and you could just have a simple function that accept the object (method1(foo)).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...