简体   繁体   中英

How to access attribute of an inner object in javascript object

Here is my code:

function TaskRepository () {

    var self = this;

    var entity = {
        'startTime': 900,
        'endTime': 1830
    };

    this.setStartTime = function(sTime){
        self.entity.startTime = sTime;
    };

    this.getStartTime = function(){
        return self.entity.startTime;
    };
}

But the following code is not working

var x= new TaskRepository();
x.setStartTime(6);

What's wrong here? What I'm missing? I've also tried to access the attribute via self.entity['startTime'] but this also is not working.

Since you're using the function as a constructor, you have to set the entity as a property, not as a pseudo-private variable. If you plan to make alot of these taskRepos, you can move the two methods to the prototype.

function TaskRepository () {
    this.entity = {
        'startTime': 900,
        'endTime': 1830
    };
    this.setStartTime = function(sTime){
        this.entity.startTime = sTime;
    };
    this.getStartTime = function(){
        return this.entity.startTime;
    };
}

OR

function TaskRepository () {
    this.entity = {
        'startTime': 900,
        'endTime': 1830
    };
}
TaskRepository.prototype = {
    'setStartTime' : function(sTime) {
        this.entity.startTime = sTime;
    },
    'getStartTime' : function(){
        return this.entity.startTime;
    }
};

Description of the problem:

var x= new TaskRepository();

X is an instance of TaskRepository.

var self = this;

Self is a local variable within X (the instance of TaskRepository) referencing the instance.

var entity = {
        'startTime': 900,
        'endTime': 1830
    };

entity is a local variable within the instance that has nothing to do with the instance and thus you can not access it using the instance.. as seen here.

self.entity.startTime

Solution:

Either remove self ( => entity.startTime )or do this:

this.entity = {
        'startTime': 900,
        'endTime': 1830
    };

Edit for better comprehension:

function TaskRepository () {
    //THIS refers to the instance of TaskRepository that we named X

    //We don't need SELF since we are already within the instance and it's easy to access THIS

    //Entity is now part of any TaskRepository instances
    this.entity = {
        'startTime': 900,
        'endTime': 1830
    };

    this.setStartTime = function(sTime){
        //THIS refers to the instance of TaskRepository because we are in a method that is part of the instance (Hint it has THIS.setStartTime)
        //To access entity you use the context this
        this.entity.startTime = sTime;
    };

    this.getStartTime = function(){
        return this.entity.startTime;
    };
}

entity is not a property of the object you're creating with new TaskRepository , it's a local variable held by the context of the call to new TaskRepository . Since the functions you're creating during that call continue to exist after the call completes, that context is kept alive and you can continue to access it from those functions (they're closures over the context, and so they keep the context alive).

Since entity isn't a property, you don't access it via the instance. It's a variable your functions close over, you just use it directly:

function TaskRepository () {

    var self = this;  // <=== Unless you use this for something you haven't shown,
                      //      you can remove it

    var entity = {
        'startTime': 900,
        'endTime': 1830
    };

    this.setStartTime = function(sTime){
        entity.startTime = sTime;
    //  ^---------- no 'self'
    };

    this.getStartTime = function(){
        return entity.startTime;
    //         ^---------- no 'self'
    };
}

Each call to new TaskRepository creates a new context, and so each has its own copy of entity , and so it ends up being specific to the object even though it's not a property on the object.

This is the classic way to create "private" properties for instances.


Side note: The single quotes on your property names in the object initializer where you create entity are unnecessary. Harmless, but unnecessary.

@Shilly's answer works fine, but it would make the entity variable public. In case you wanted to keep it private, just use your code but removing the references to entity via self :

function TaskRepository () {

    var entity = {
        'startTime': 900,
        'endTime': 1830
    };

    this.setStartTime = function(sTime){
        entity.startTime = sTime;
    };

    this.getStartTime = function(){
        return entity.startTime;
    };
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM