X
X
XpeH Petrovich2017-02-02 12:31:27
JavaScript
XpeH Petrovich, 2017-02-02 12:31:27

What is the correct way to access an outer object from an inner one in JavaScript?

There is the following code:

function mock() {
  this.val = 'val';
  this.log = {
    start: function() {
      this.timer = setInterval(function() {
        console.log(this.val);
      }.bind(this), 1000);
    }.bind(this),
    stop: function() {
      clearInterval(this.timer);
      delete this.timer;
    }.bind(this)
  };
}

Subsequently, in the line console.log(this.val); it assumes access to an external object (i.e. a mock). I have now used bind(this) to pass context to nested functions. How would it be correct to write something like this in the JS paradigm so that in a line like console.log(this.val) I can get normal access to the external (mock) object, and at the same time that the interval is attached exactly to the nested log object (and is available via this in log'e) and not to mock? As far as I understand, either you need to pass something through the argument to start () or somehow make a closure (but what exactly to close ???). But I still don’t understand how a person who has been programming in JS for more than one year and who knows how to think in this language would do it) plz tell me, javascript ninja
PS: I just climbed from puff to JS under Nodu. I don’t know how the code above looks adequate, don’t judge strictly

Answer the question

In order to leave comments, you need to log in

3 answer(s)
K
Konstantin Gromov, 2017-02-02
@uakoB

In your case, this refers to the root object everywhere, so nothing prevents you from getting the nested one and working with its properties:

function Mock() {
    this.val = 'val';
    this.log = {
        start: function() {
            this.log.timer = setInterval(function() {
                console.log(this.val);
            }.bind(this), 1000);
        }.bind(this),
        stop: function() {
            clearInterval(this.log.timer);
            delete this.log.timer;
        }.bind(this)
    };
}

But of course it's better to just separate the entities:
function Timer(handler, interval) {
    this.handler = handler;
    this.interval = interval;
}

Timer.prototype.start = function () {
    this.timer = setInterval(this.handler, this.interval);
};

Timer.prototype.stop = function () {
    clearInterval(this.timer);
    delete this.timer;
};

function Mock() {
    this.val = 'val';
    this.log = new Timer(function () {
        console.log(this.val);
    }.bind(this), 1000);
}

V
Vitaly, 2017-02-02
@vshvydky

if I understand correctly, then you want to get the value of the object by calling this.val anywhere in the code, but this is not correct.
Your case is the following:

let m = new mock();
m.log.start();
m.log.stop();

about this in the browser, this outside of any object will refer to window
in the node to the node object, which contains a lot of things (global, module, process, etc.)
Or are you talking about this?
function mock(number) {
  this.number = number;
  this.val = 'val';
  this.log = {
    start: function() {
      this.timer = setInterval(function() {
        console.log(this.number, ": ", this);
      }.bind(this), 1000);
    }.bind(this),
    stop: function() {
      clearInterval(this.timer);
      delete this.timer;
    }.bind(this)
  };
}

m = new mock('1')
> mock {number: "1", val: "val", log: Object}
n = new mock('2')
>mock {number: "2", val: "val", log: Object}
m.log.start(); n.log.start()

VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
VM2668:7 1 :  mock {number: "1", val: "val", log: Object, timer: 6480}
VM2668:7 2 :  mock {number: "2", val: "val", log: Object, timer: 6481}
m.log.stop(); n.log.stop()

A
Alexander Manakov, 2017-02-02
@gogolor

What you are looking for is similar to arrow functions in ES6.
I would do like this:

function mock() {
  this.val = 'val';
  this.startlog = () => {
     this.timer = setInterval(() => {
        console.log(this.val);
      }, 1000)
  };
  this.stopLog = () => {
      clearInterval(this.timer);
      delete this.timer;
  }
}

Or with classes:
class Mock {
   constructor() {
      this.val = 'val';
   }

   startlog() {
     this.timer = setInterval(() => {
        console.log(this.val);
      }, 1000)
  }

   stopLog() {
      clearInterval(this.timer);
      delete this.timer;
  }

}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question